Agent View Cockpit — Design Doc 2026-05-15
Phase 8FF-2 — design pass only, no code written. Author: phase-8ff2-tui-cockpit-design agent. Status: PROPOSAL — awaiting NAO sign-off before any implementation phase.
Goal
The OpenAlice operator (NAO, devs, future power users) today drives Alice from one of three surfaces — Telegram, the web Mission Control, and the alice tui chat TUI shipped in Wave K8. None of them answer the operator's real question on a busy day: "what is Alice doing right now, and what's about to fail?" The chat TUI is single-conversation; the web MC is heavyweight and remote; Telegram only shows the channel you opened. Mean- while we already ship every primitive the answer requires — A2A channels, sub-agent spec/running/result trees, the mission engine, the goal-drift detector, the lab probe harness, the rank ledger.
The Agent View Cockpit is a single-pane, terminal-first dashboard that joins those primitives into one live view: every active and recent agent across every chat scope, their goals, their sub-agent trees, their tool streams, their budget burn-down, and the controls to cancel / pause / retry / spawn — all without leaving the terminal and without breaking the chat TUI we already shipped. Claude Code v2.1.143 calls their version claude agents; Hermes v0.13.0 calls theirs the multi-agent Kanban. Ours is alice cockpit (working title) and it is the surface that turns Alice from "a single agent you chat with" into "an agent OS you operate."
UX promise in one sentence: open the cockpit, see everything, fix anything, in under 200ms per keystroke.
Reference comparison
Legend: yes / no / partial = ● ○ ◐ . The right column is honest — features that exist as data on disk but have no UI yet are scored "data-yes / UI-no".
| Feature | Claude Code Agent View (v2.1.143) | Hermes Mission Cockpit (v0.13.0 "Tenacity") | OpenAlice today |
|---|---|---|---|
| Live agent list | ● sidebar | ● Kanban columns (todo / doing / done) | ◐ data on disk (~/.openalice/data/{agent}/agents/), UI no |
| Sub-agent tree | ● | ● | ◐ data via ParentIndex (Wave T), UI no |
| Cross-chat aggregation | ● | ● | ◐ chat-scope folders enumerable, UI no |
| Per-agent permission/model/effort badges | ● inline pills | ● per-card | ◐ AgentSpec carries model/provider/scope, UI no |
Goal display ( /goal autonomy contract ) | ● elapsed time / turns / tokens | ● /goal command + Kanban card | ✗ not implemented (top snipe target in 2026-05-15 intel) |
| Live tool stream per agent | ● log tail | ● tool-call ribbon | ◐ chat TUI tool feed pane exists, single-agent only |
| Heartbeat / liveness | ◐ | ● heartbeat monitor | ✗ no heartbeat protocol |
| Retry budgets | ◐ | ● per-agent retry budget | ◐ BudgetSpec { tokens, wall } exists, no retry budget |
| Cancel / pause / resume | ● | ● | ◐ agent cancel exists in CLI, no pause/resume |
| Spawn new agent from cockpit | ● (claude agents new) | ● | ◐ alice-cli agent spawn CLI exists, no UI hotkey |
| A2A channel view | ✗ | ◐ (single-chat focus) | ◐ A2A tool surface complete (a2a_status/check/history) |
| Mission engine surface | ✗ | ◐ (/goal is the only autonomy contract) | ◐ Mission schema + mission_engine crate, no UI |
| Rank / integrity glyphs | ✗ | ✗ | ◐ rank ledger in store, no inline glyph |
| Connector health strip | ✗ | ◐ platform status panel | ◐ presence + connectors routes exist, no compact UI |
| Live probe / lab traces | ✗ | ✗ | ◐ openalice-lab harness probes, never surfaced live |
| Hotkey navigation | ● | ● | ◐ chat TUI has Ctrl+S/M/T, no cockpit hotkey map |
| Mouse support | ◐ | ◐ | ✗ |
| Themeable | ● | ◐ | ● ratatui theme module exists (ui::theme) |
| Built on | Ink + React (perf complaints) | React/Ink TUI v2 ("Interface" v0.11) | ratatui + crossterm (we win on perf) |
Three things this table makes obvious:
- We already own the data. Every primitive Claude Code and Hermes display has a backing store in OpenAlice today. The cockpit is a read layer, not a feature build, for ~70 % of the surface.
- We are missing `/goal` entirely. This is the only competitor item where we lack both data and UI. It is the single highest-leverage addition and is already top-1 in the 2026-05-15 competitor-intel snipe list.
- A2A live view + lab probes + mission engine are pure differentiators. Neither Claude Code nor Hermes has these. The cockpit gives us a place to show them off without confusing the chat TUI.
Information architecture
The cockpit is one full-screen ratatui app with three columns and a status strip. It is not a takeover of alice tui — it is a sibling subcommand (alice cockpit) so the chat TUI stays focused on conversation and the cockpit stays focused on supervision. Both share the crates/tui/ ratatui + crossterm runtime; the cockpit adds a new module crates/tui/src/cockpit/ (proposed).
Layout sketch (80×24 minimum, scales to terminal size)
┌─ alice cockpit ────────────────────────────────────────────── chat: all ▾ scope: tg-12345 ▾ ─┐
│ │
│ ┌─ AGENTS (12) ───────┐ ┌─ AGENT alice / sub-7f3a ──────────────┐ ┌─ TOOL STREAM ────────┐│
│ │ ● alice ▶│ │ goal: "ship 8FF-2 doc" │ │ 12:04:22 fs.read ││
│ │ ├─ scribe-2c1d ✓│ │ contract: turns≤8 tokens≤40k wall≤30m │ │ 12:04:22 → ok 1.4kb ││
│ │ ├─ curator-9d8e ▶│ │ status: ▶ running elapsed: 4m12s │ │ 12:04:24 web.search ││
│ │ └─ sub-7f3a ▶│ │ model: gpt-5.5 effort: high │ │ 12:04:25 → 7 results││
│ │ ⏸ katya │ │ rank: bronze · honesty 0.91 │ │ 12:04:26 a2a.send ││
│ │ ✓ bort (12m ago) │ │ budget: tokens 18k/40k wall 4m/30m │ │ 12:04:27 → ok ││
│ │ ✗ scribe-bbc1 fail │ │ a2a: 1 channel (alice ↔ katya) │ │ 12:04:30 fs.write ││
│ │ … scroll for 4 │ │ heartbeat: 12:04:30 ✓ │ │ ← tail follows live ││
│ └─────────────────────┘ └─────────────────────────────────────────┘ └──────────────────────┘│
│ │
│ ┌─ SUB-AGENT TREE ─────────────────────────────┐ ┌─ GOAL / MISSION / CONTRACT ─────────────┐│
│ │ alice ▶ (root, chat tg-12345) │ │ goal: ship 8FF-2 design doc ││
│ │ ├─ scribe-2c1d ✓ done · 2.1k tokens │ │ start: 12:00:10 +4m12s ││
│ │ ├─ curator-9d8e ▶ 4.4k tokens · 1m23s left │ │ exit-cond: doc committed + pushed ││
│ │ └─ sub-7f3a ▶ 18k tokens · spawned 7f3a-1 │ │ progress: 5/8 sections drafted ││
│ │ └─ 7f3a-1 ▶ depth 2 · 1.2k tokens │ │ probe: subagent-probe last: pass ││
│ │ (depth cap: 3 — 1 slot left) │ │ drift: none (cosine 0.04 vs anchor) ││
│ └──────────────────────────────────────────────┘ └─────────────────────────────────────────┘│
│ │
├──────────────────────────────────────────────────────────────────────────────────────────────┤
│ [1] agents [2] tree [3] tools [4] goal ⏎ inspect c cancel p pause r retry n spawn ? │
│ codex:gpt-5.5 · prod-alice · 24 features · 4 connectors ok · a2a 1 chan · rank A.83 · 12:04:31│
└──────────────────────────────────────────────────────────────────────────────────────────────┘Panes
| Pane | Position | Purpose |
|---|---|---|
| Agents list | left column, top half | All known agents in scope. Glyph: ▶ running, ⏸ paused, ✓ done, ✗ fail |
| Agent detail | centre column, top half | Selected agent's spec + status + contract + heartbeat |
| Tool stream | right column, top half | Live tail of selected agent's tool calls (and results) |
| Sub-agent tree | left+centre, bottom | Tree view of selected agent's children (Wave T ParentIndex) |
| Goal / Mission card | right, bottom | Goal autonomy contract + mission progress + probe + drift |
| Status strip | bottom row | Provider, model, rank, connectors, A2A channels, clock |
| Hotkey strip | bottom row | Always-visible hotkey crib |
Navigation + hotkeys
Discipline borrowed from opencode (leader key) but with single-key + numeric focus switching à la htop / k9s for raw speed:
| Key | Action |
|---|---|
1 … 5 | Focus pane 1 (agents) … 5 (mission) |
↑ ↓ j k | Move cursor inside focused pane |
g G | Top / bottom of focused pane |
/ | Filter agents (fuzzy: id, scope, model, status) |
Tab / Shift+Tab | Cycle scope (all → tg-12345 → discord-xxx → mc-xxx …) |
⏎ | Inspect selected agent — opens chat-TUI in read-only review |
c | Cancel selected agent (writes running/<id>.cancel = true) |
p | Pause selected agent (proposed — needs runner support) |
r | Retry selected agent (re-spawn with same spec) |
n | Spawn new agent — opens spec form overlay |
f | Toggle follow-mode on tool stream |
? | Help overlay (auto-generated from KeyMap) |
q Esc | Quit cockpit (chat TUI remains running if it was open) |
Ctrl+L | Hard refresh (re-scan disk + re-fetch HTTP) |
Ctrl+S | Toggle status strip (compact mode for narrow terminals) |
Leader-chord (Ctrl+X + letter) is reserved for v2; we ship single-key v1 because the cockpit is a supervision surface, not a text editor — there are no conflicting single-letter typing surfaces in the cockpit.
Modal overlays
The cockpit shares the chat TUI's overlay system (crates/tui/src/ui/overlay.rs):
- Spawn form (`n`) — agent_id (auto-uuid), task, scope, model, provider, budget tokens, budget wall, parent_id, background flag. Submit → POST to
/v1/agent/spawn(proposed; today the only entry point is the CLI). - Cancel confirm (`c`) — y/n, with budget burn-down summary.
- Inspect (`⏎`) — three sub-tabs: spec.json, running.json, result.json, rendered with the existing chat-TUI JSON theme.
- Help (`?`) — auto-generated from the KeyMap registry.
Data sources (mapped to existing OpenAlice infrastructure)
The cockpit reads from sources Alice already maintains. No new persistence is required for v1. Everything below already exists in the repo.
| Surface | Source today | Read mode | Refresh | ||
|---|---|---|---|---|---|
| Agent registry | state.kernel.scheduler.list_agents() exposed by GET /v1/agents | HTTP | poll 1 s | ||
| Sub-agent spec/running | `~/.openalice/data/{agent}/agents/spec\ | running\ | results/*.json + _parent_index.json` | direct FS read | poll 500 ms |
| Sub-agent (scoped) | ~/.openalice/data/{agent}/chat/{scope}/agents/... (Wave S/Phase 8AA-4 canonical layout) | direct FS read | poll 500 ms | ||
| A2A channels & history | mcp__openalice-a2a__a2a_status + _channels + _history (tool surface, transport HTTP) | HTTP via tool bridge | poll 2 s | ||
| A2A discovery | a2a_discover tool surface | HTTP | on demand | ||
| Mission state | Mission from openalice-agents::mission_engine + tools_mission.rs | HTTP (proposed /v1/missions) | poll 2 s | ||
| Goal contract | NEW — ~/.openalice/data/{agent}/chat/{scope}/goal.yaml (proposed Wave 8GG) | direct FS read | poll 1 s | ||
| Heartbeat | NEW — running/<id>.json already has started_at; extend with last_heartbeat_at | direct FS read | poll 500 ms | ||
| Tool stream | /v1/chat/stream SSE per-agent stream — already wired into chat-TUI tool_feed | SSE | live | ||
| Probe results | openalice-lab writes traces under lab-data/ — surfaced as last-pass/fail per scope | direct FS read (lab dir) | poll 5 s (optional) | ||
| Goal drift | agents-safety::goal_drift writes a drift score to store | HTTP /v1/safety/drift | poll 5 s | ||
| Rank glyph | rank ledger in store, exposed via /v1/agents/{id}/xp + /v1/rank_chart | HTTP | poll on selection | ||
| Connector health | /v1/connectors/* + /v1/presence | HTTP | poll 5 s | ||
| Features / version | openalice_schemas::features::FEATURES (linkme), already 502 entries | in-process | once at startup |
Polling vs SSE — pragmatic split:
- Anything backed by SSE today (tool stream) stays SSE.
- Disk-backed surfaces (specs, running, results, goal.yaml) are polled with
notify(inotify on Linux, ReadDirectoryChangesW on Windows) and fall back to 500 ms timer poll whennotifyis unavailable. - HTTP-backed surfaces poll on a 1 – 5 s cadence depending on cost.
- A single in-process refresh-bus broadcasts updates to all panes so we only read each source once even if multiple panes render it.
Why no new daemon / new store: the existing on-disk layout (spec/, running/, results/, _parent_index.json) was designed exactly for this. Wave T notes that agent list is the same operation a cockpit view performs. We're upgrading the verb (watch → cockpit), not the data.
Phased build plan
Total budget: ~7–12 days of focused work. Each phase ships independently, behind an alice cockpit subcommand that prints "v1 read-only — feature flag: cockpit.<phase>".
Phase A — Static read-only view rendering (1–2 days)
Deliverable: alice cockpit opens, reads agents/specs/running/results from disk once, renders the three-column layout, and quits. No live updates, no controls. Equivalent to agent list on steroids.
- New module
crates/tui/src/cockpit/mod.rs+layout.rs+panes/*.rs. - Read paths reuse
alice-cli::agent::layout::AgentLayout::list_agentsandParentIndex::load. - Snapshot tests via
insta(already wired for chat TUI) — at least three golden frames: empty / one running / full tree with depth-3 children. - linkme feature registry:
tui.cockpit.static, statusExperimental.
Exit criteria: alice cockpit renders three columns + status strip on a synthetic agents tree (regression-tests fixture) and matches insta golden.
Phase B — Live updates via polling + notify (2–3 days)
Deliverable: the cockpit refreshes panes in real time without flicker.
notify-based watcher on eachagents/root andgoal.yaml(when present).- Tokio-interval poll fallback (configurable, defaults 500 ms / 1 s / 2 s by surface).
- HTTP client reused from
crates/tui/src/client.rs; new typed endpoints in acockpit::clientsubmodule. - SSE tool stream for the focused agent only (we don't tail every agent — N tool streams would melt the terminal). Switching focus opens a new SSE.
- Two new feature flags:
tui.cockpit.live,tui.cockpit.tool_stream.
Exit criteria: with a synthetic spawner running, panes update within ≤ 1 s of disk change; tool stream tails the focused agent at ≥ 30 events/s without dropping.
Phase C — Interactive controls (3–5 days)
Deliverable: the cockpit becomes Mission Control — cancel, retry, spawn, pause.
ccancel → writesrunning/<id>.cancel = true(already supported byagent::runner::cancel_agent).rretry → re-reads the spec, generates a fresh agent_id, callsagent::runner::spawn_subagent(reuse Wave T code path, not via HTTP, to keep latency tight).nspawn → modal form that calls the samespawn_subagentAPI.ppause — proposed new runner verb: writesrunning/<id>.paused = true, worker polls the flag at 100 ms cadence (same loop as cancel). Resumes by clearing the flag. This is the only piece that needs runner-side support.- ⏎ inspect → opens a read-only chat-TUI tab against the running agent's chat scope (uses existing chat-TUI infrastructure — no new view).
- Hotkey strip + help overlay auto-generated from a
KeyMapregistry (copy the bubbletea pattern noted indocs/competitors-tui-2026-04-23.md§3.6). - Feature flag:
tui.cockpit.controls.
Exit criteria: scripted test (in crates/tui/tests/) spawns a synthetic agent, opens cockpit, cancels it, asserts terminal state writes the cancel flag and the agent transitions to results/<id>.json with outcome: cancelled within 1 s.
Phase D — Observability: metrics, history, probes (1–2 days)
Deliverable: the cockpit becomes the answer to "what is Alice's overall health, today?"
- Rank glyph in the agent-detail pane (read
/v1/agents/{id}/xp). - Goal drift score in the mission card (read
/v1/safety/drift). - Connector health strip (read
/v1/connectors/*+/v1/presence). - Last-N probe results in the mission card when
openalice-labis detected on disk (lab-data/<scope>/probe-*.json). oa_cockpit_*Prometheus metrics emitted from the cockpit binary itself (frame-time, refresh-lag, pane-render-time) — gated behindOPENALICE_COCKPIT_METRICS=1because most users won't want to expose a port from a TUI process.- Feature flag:
tui.cockpit.observability.
Exit criteria: cockpit renders a green-strip overview for a healthy system and a red-strip overview when we kill the discord connector in test.
Cross-cutting (every phase)
- Snapshot tests (
insta) for every layout state. - Linkme feature registration per feature.
- Doc comments on every public type.
- Real-life regression case: NAO opens cockpit while an A2A run is in flight, cancels it, sees graceful unwind. This becomes a scripted test.
Open questions
These are the decisions NAO needs to make before Phase A starts. Defaults shown in bold; everything is reversible.
- Subcommand vs separate binary.
alice cockpit(subcommand of the existing CLI) vs a newalice-cockpitstandalone binary. Subcommand wins on distribution (one binary, one install path, shared crates), but a standalone binary lets the cockpit run on a different host than the server. Default: subcommand because every supported deployment today has the cockpit on the same host as the Alice server (matches thecrates/tui/src/lib.rsrationale:DEFAULT_ENDPOINT = http://127.0.0.1:8080).
- Daemon mode (background watcher) — yes or no? A daemon-mode cockpit could run headless, exposing a
/v1/cockpit/snapshotJSON for the web MC to consume. We get this for free if every pane is reactive to the in-process refresh-bus, but it adds surface area (auth, lifecycle). Default: no daemon in v1. Re-evaluate after Phase D — if the web MC wants the same data we can extract the refresh-bus into a server crate.
- ratatui takeover (alternate-screen) vs scrollback-preserving render. Gemini-CLI v0.15 fixed this exact bug by restoring main buffer on quit (per
docs/competitors-tui-2026-04-23.md§3.8). Default: alternate screen on entry, restore on exit, plus an explicit `oa_cockpit_restore` feature-registered fix-test. No flicker; scrollback survives.
- `/goal` semantics — file format and writer. Hermes uses a
/goalslash-command inside the chat TUI; Claude Code uses a separate command. Where does the goal contract live in OpenAlice? Proposal:~/.openalice/data/{agent}/chat/{scope}/goal.yamlwith fieldsgoal,exit_conditions[],max_turns,max_tokens,max_wall_ms,started_at. Writer: a new toolgoal_setfrom the chat surface, readable by both chat TUI and cockpit. This is also a Wave J task- contract pre-req (memory notewave-j-pipeline-design-2026-04-27.md). Needs NAO confirm before Phase A so the cockpit doesn't read a format that gets renamed in Wave J.
- Pause/resume runner verb. Cancel exists in Wave T. Pause does not. We can ship Phase A–B without pause; Phase C needs runner support. Cheapest path: add
paused: booltoRunningState, worker polls it in the same 100 ms loop ascancel. Cost: ~50 LOC + tests. Default: yes, do it in Phase C. Needs NAO confirm because it touches the Wave T contract.
- Multi-host fleet view. Long-term we want to see agents across
alice.blal.pro+ futurealice.eu.openalicelabs.cometc. in one cockpit. Out of scope for v1 but the in-process refresh-bus must support a "source = remote" wrapper from day one, so v2 can layer it on without a rewrite. Confirm NAO is OK deferring fleet view to v2.
- A2A live channel UI inside cockpit vs new pane. Today the chat TUI has no A2A view at all. Cockpit shows a one-line "a2a: N channels" in the agent detail; clicking it should open a channel detail. Options: (a) push channel-detail into the cockpit as a sub-overlay, or (b) open a new chat-TUI tab in A2A-replay mode. Default: (a) overlay in cockpit because it preserves the supervisor mindset; chat-TUI is for conversation. Cheaper too.
- Permissioning model. Cockpit can cancel agents owned by other chat scopes. Should this require a confirmation prompt? Default: yes —
ccancel always confirms; in--unattendedit cancels without prompt. Aligns with HITL approval discipline.
Non-goals (v1)
We will explicitly not build the following in cockpit v1, to keep scope tight and to avoid duplicating chat-TUI features:
- Conversation surface. The cockpit does not let you talk to an agent. Use the chat TUI (
alice tui) for that. The cockpit can open a chat-TUI tab in read-only review mode (⏎ inspect), but it does not let you compose. - Web UI. No HTML, no SSE-over-WebSocket. Terminal-only. The web MC remains a separate surface; we may share data in v2 via the daemon-mode question above.
- Multi-host / fleet view. v2.
- Editing agent specs in place. Spawn-new is the v1 verb. Editing an existing spec is reserved for v2 once we know which fields are safe to hot-reload.
- Skill marketplace / Curator UI. Curator runs out-of-band (Hermes pattern, deferred per memory note
wave-i-pipeline-design). Cockpit shows curator activity in the tool stream when it runs but does not host its UI. - Voice. Voice in/out is a separate roadmap track (
voice-wakecrate). Cockpit does not embed it; it shows voice-agent activity like any other agent. - Mouse support. Single-key + arrow navigation only. Mouse is a Phase E ask if real users request it.
- Themeable inside cockpit. Cockpit uses the existing
ui::themepalette with one extracockpitpalette key. No/themesmodal in v1 — Phase E. - Recording / replay. Live observation only. Replay is a probe-harness concern; cockpit links out to lab traces but does not host the player.
- Authentication. Cockpit is local-only; binds to
127.0.0.1and trusts the local user. Multi-user remote cockpit is gated on auth crate maturity and is firmly v2.
Appendix — invariants the cockpit must respect
These come from existing memory notes; cockpit must not regress them.
- Single-writer Codex OAuth (
codex-oauth-single-writer-2026-04-22.md): cockpit is a reader of~/.codex/auth.jsononly. It must never spawn a child that competes with the main Alice process for the refresh token. - TEST_HOME_LOCK (
reference-test-home-lock-2026-05-13.md): cockpit tests useAgentLayout::with_root(<tempdir>)and never mutate HOME. - Memory archive, not delete (
feedback-memory-archive-not-delete): cockpit may surface "archive this run" but must not offer a destructive delete in v1. - No `.claude/` cleanup (
feedback-claude-history-untouchable-2026-05-09): cockpit's disk scanner must skip.claude/even if it appears under a chat scope. - deploy-safe (
feedback-no-build-without-permission): cockpit ships behindcockpit.<phase>feature flags; merging to mvp does not deploy. Lab-only validation until NAO says "деплой".
Appendix — file paths to touch (forecast, not actual changes)
Forecast for Phase A only, to make the scope concrete. Phases B–D will add roughly equal-sized increments.
crates/tui/Cargo.toml— addnotify,tokio-stream(already a dep tree member via reqwest).crates/tui/src/cockpit/mod.rs— entry + feature registry.crates/tui/src/cockpit/layout.rs— three-column ratatui layout.crates/tui/src/cockpit/panes/agents.rs— agent list pane.crates/tui/src/cockpit/panes/detail.rs— agent detail pane.crates/tui/src/cockpit/panes/tree.rs— sub-agent tree pane.crates/tui/src/cockpit/panes/tools.rs— tool stream pane (reuses existingToolFeed).crates/tui/src/cockpit/panes/mission.rs— goal/mission/probe card.crates/tui/src/cockpit/panes/status.rs— bottom strip.crates/tui/src/cockpit/refresh.rs— refresh-bus + notify watcher.crates/tui/src/cockpit/keymap.rs— KeyMap registry + auto help.crates/tui/tests/cockpit_snapshot.rs— insta goldens.crates/alice-cli/src/main.rs—cockpitsubcommand wired toopenalice_tui::cockpit::run.docs/design/agent-view-cockpit-2026-05-15.md— this doc.
No changes to agents-tools/, api-handlers/, agents-soul/, or agents-safety/ are required for Phase A — the cockpit reads only.
End of design doc. Awaiting NAO sign-off on the 8 open questions before Phase A kickoff.