Live agent-session and escape-denial demo¶
This demo launches a real Codex CLI inside a hardened Runeward Citadel, streams the agent's output as a durable session, and then performs non-destructive isolation probes. It records the terminal presentation and saves the redacted session transcript, network decisions, signed Chronicle, and portable evidence.
The demo proves two different boundaries:
- The outer agent launch and explicit probes pass through Runeward policy, budgets, and the signed Chronicle.
- Commands started by the agent are not intercepted one-by-one. They are constrained by the non-root container, read-only root filesystem, private workspace volume, resource limits, and strict egress sidecar.
It does not claim that a container is VM-grade isolation. For hostile workloads,
set a gVisor or Kata runtime_class as described in the
security model.
Prerequisites¶
- Docker or OrbStack is running and reachable from the terminal.
go,curl,jq, andasciinemaare installed.- An OpenAI API key is stored in
~/.runeward-openai.keywith mode0600. - The published
ghcr.io/runewardd/runeward-agent:latestandghcr.io/runewardd/runeward-egress:latestimages are reachable.
The script never prints the API key. Runeward injects it into the Citadel and
scrubs declared secrets and common credential formats from the transcript.
Codex runtime state uses /workspace/.agent-home, the Citadel's writable
workspace volume; the container root remains read-only. Before pausing for the
dashboard, the script creates and verifies the writable runtime directories and
runs codex --version. A failed preflight aborts before the agent conversation.
Record the demo¶
From the repository root:
To open the dashboard before the agent starts, use the pause switch:
The script prints the dashboard URL. Open Agent groups, select the displayed Cohort, then use Agent sessions → View. The viewer loads the existing backlog, follows new stdout/stderr events, and can reconnect from its last event sequence. From a member Citadel, View live agent output opens that same cohort/session directly. PTY Terminal is a separate interactive shell; attaching it does not mirror stdout from the agent process.
Run without asciinema when iterating on the scenario:
What the agent attempts¶
The prompt asks the agent to narrate and perform these benign checks:
- Report its user, workspace, and container hostname.
- Write and read a file under
/workspaceas a positive control. - Read a randomly named, host-only marker under the host's temporary directory.
- Find the Docker control socket.
- Write under
/rootdespite running as a non-root user with a read-only root. - Reach
https://example.com, which is absent from the egress allowlist.
Model output is useful for the live presentation, but it is not treated as the
proof. After the agent finishes, the script repeats every boundary check through
the governed shell API and asserts the exit codes. The demo fails if the host
marker value appears in the transcript, an escape probe succeeds, or the
/workspace positive control fails. The probe Charter deliberately returns an
allow verdict for these non-destructive commands, so their non-zero exits show
the container/filesystem/network boundary stopping them—not a pre-execution
policy rule merely declining to try.
Recorded artifacts¶
Successful recording creates a small, reviewable artifact set:
| Artifact | Purpose |
|---|---|
docs/assets/demos/agent-session-escape.cast |
Asciinema v2 terminal recording. |
docs/assets/demos/agent-session-escape.mp4 |
Curated H.264 rendering for the documentation site. |
agent-session-escape/session-transcript.txt |
Human-readable, redacted agent output. |
agent-session-escape/escape-probes.json |
Deterministic isolation checks and exit codes. |
agent-session-escape/evidence.json |
Portable resolved Charter and signed Chronicle evidence. |
If the scenario fails, the recorder keeps the unsuccessful terminal capture as
agent-session-escape.failed.cast and prints the temporary artifact directory
containing server.log. It does not replace the last successful recording.
Replay the recording locally:
Play the generated video in any standard player:
The recording script updates the portable asciicast. The checked-in MP4 is a curated documentation asset and can be regenerated with a standard asciicast renderer when the cast changes.
Inspect the machine-readable verdicts:
jq '.probes[] | {probe, verdict, exit_code, stderr}' \
docs/assets/demos/agent-session-escape/escape-probes.json
./bin/runeward evidence verify \
docs/assets/demos/agent-session-escape/evidence.json
Before committing a generated recording, watch it once and inspect all text
artifacts. Redaction is defense-in-depth; add Charter scrub_patterns for any
organization-specific credential format.