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: one-shot vs session¶
This distinction is important.
Without session_id — historical one-shot¶
eve-iac console exec ./lab n_1 "show version"
- Opens a separate one-shot Telnet connection via the internal console manager.
- Does not join an open VSIX terminal or existing Hub.
- Default timeout 10 s; maximum 60 s (
timeout_mson the API). - Connect timeout 5 s.
SDK equivalent (Python):
client.exec_console(ExecConsoleRequest(**{**packed.payload, "node": "n_1", "command": "show version"}))
With explicit session_id — Hub session¶
eve-iac console exec ./lab n_1 "show ip int brief" --session sess-7f3a
- Uses the existing Hub/session.
- No fallback to one-shot if the session is invalid or closed.
- Shares the same EVE Telnet TCP as other leases on that session.
Use session-backed exec when a human terminal or an earlier createConsoleSession already holds the Hub open.
Wait¶
Wait is event-driven console matching — not polling.
- 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: "terminal length 0"
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 |
Per-step cap (optional) |
Global run timeout maximum: 600 s. 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="terminal length 0"),
],
}))
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).
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.