Automation: exec, wait, run, history¶
These operations are implemented by the agent Hub engine. The CLI sends requests; it does not implement expect/send logic locally (except parsing run YAML before calling the API).
Exec¶
execConsole is one command, including show, ping, and traceroute. The agent joins or opens the Hub, learns the prompt, and completes when that prompt returns after the command was sent. Output is that command's bytes. Privilege and pager-disable run only when the command's own output requires them, or when this Hub already proved them.
eve-iac console exec ./lab n_1 "show version"
eve-iac console exec ./lab n_1 "ping 10.0.0.2"
- Omitted
session_idstill uses the Hub. It does not open a second Telnet beside an open console. - A
session_idthat no longer exists is reopened once.console_busyis not expiry. - Pass
--sessionwhen this call must share a specific human lease. - Default timeout 10 s; maximum 60 s (
timeout_mson the API). - A command that only takes longer than 10 s stays on exec. Pass a larger
timeout_ms. Do not move it to run. - These are system consoles. The node may still be booting, or waiting on
Press RETURN. On the first client of a Hub, one newline is sent only after about 5 seconds of silence with no prompt. Boot text restarts that wait. A Hub that already has another client is not sent that newline. - Connect timeout 5 s.
- Success includes
prompt,phase, andrx_to.recoveredis true when the session was reopened. command_timeoutis recoverable by retrying exec with a largertimeout_ms.auth_requiredis not.
SDK equivalent (Python):
client.exec_console(ExecConsoleRequest(**{**packed.payload, "node": "n_1", "command": "show version"}))
execConsoleMany runs the same or independent read-only commands on several nodes and joins each Hub. One target failure stays on that target.
runConsole is a real multi-step dialogue (a login with a secret you provide, a wizard, a config exchange). It is not the path for a single show, ping, or traceroute.
Wait¶
Wait is event-driven console matching — not polling, and not how show, ping, or traceroute finish. Those commands use exec.
- Scan retained Hub history.
- Then block on live console data until the pattern matches or time expires.
| Property | Value |
|---|---|
| Pattern | Go regexp |
| Spanning reads | Matches may span Telnet read boundaries |
| Max timeout | 600 s (timeout_ms) |
| Output | Bounded; timeout is distinguishable from cancel/error |
CLI:
eve-iac console wait ./lab n_1 \
--expect 'Router[#>]' \
--timeout-ms 180000
Python:
client.wait_console(WaitConsoleRequest(**{
**packed.payload,
"node": "n_1",
"pattern": r"Router[#>]",
"timeout_ms": 180_000,
}))
TypeScript:
await client.waitConsole({
...packed,
node: "n_1",
pattern: "Router[#>]",
timeout_ms: 180_000,
});
Go:
client.WaitConsole(ctx, eveiac.WaitConsoleRequest{
Lab: packed.Lab, Node: eveiac.Ptr("n_1"),
Pattern: eveiac.Ptr(`Router[#>]`), TimeoutMs: eveiac.Ptr(180_000),
})
Run / expect-send¶
Run executes an ordered list of steps on a Hub lease. Each step may expect a regexp, send text, or both.
Example YAML file (bootstrap.yaml):
steps:
- expect: "Press RETURN"
send: ""
- expect: "Router>"
send: "enable"
- expect: "Password:"
send_secret: "example-placeholder"
- expect: "Router#"
send: "configure terminal"
CLI:
eve-iac console run ./lab n_1 bootstrap.yaml
Step semantics¶
| Field | Meaning |
|---|---|
Omitted send |
Do not send anything (expect-only step) |
send: "" |
Send RETURN (empty line) |
send_secret |
Send value; never echoed in responses or transcripts |
timeout_ms |
This step's wait. Default 10 s. A larger value is honored, up to 600 s. |
An overall timeout_ms, if set, caps every step (maximum 600 s). Omit it to use the step budgets. On failure, failed_step is 0-based (-1 when all steps succeed). Secret output is redacted in API and MCP responses.
Run uses the agent engine. The CLI only parses YAML and calls runConsole.
Python:
from eveiac import ConsoleRunStep, RunConsoleRequest
client.run_console(RunConsoleRequest(**{
**packed.payload,
"node": "n_1",
"steps": [
ConsoleRunStep(expect="Router>", send="enable"),
ConsoleRunStep(expect="Password:", send_secret="example-placeholder"),
ConsoleRunStep(expect="Router#", send="configure terminal"),
],
}))
History¶
Hub history is a bounded tail of raw console bytes (after Telnet IAC filtering).
| Layer | Limit |
|---|---|
| Hub ring | 64 KiB (65536 bytes) |
| MCP default request | 8 KiB |
| MCP hard cap | 32 KiB |
CLI --bytes |
1–65536 |
There is no persistent log collector. History is available only while the Hub exists (including the 60 s idle window after the last client leaves). end_seq is the newest retained receive sequence. after_seq returns only newer bytes and sets truncated when that sequence has left the ring. History is the ring tail, not the result of the command that just ran (rx_to on exec).
CLI:
eve-iac console history ./lab n_1 --bytes 16384
Python:
client.get_console_history(GetConsoleHistoryRequest(**{
**packed.payload,
"node": "n_1",
"session_id": sess.session_id,
"max_bytes": 16_384,
}))
MCP eve_iac_console_history applies the same bounds at the VSIX boundary (default 8 KiB, max 32 KiB) and sets truncated when output is cut.