kb://architecture/agent-view-cockpit-2026-05-15active2026-06-17

Agent View Cockpit — Design Doc 2026-05-15

openalicedesignalice-core

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".

FeatureClaude 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-cardAgentSpec 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 budgetBudgetSpec { tokens, wall } exists, no retry budget
Cancel / pause / resumeagent 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 tracesopenalice-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 onInk + React (perf complaints)React/Ink TUI v2 ("Interface" v0.11)ratatui + crossterm (we win on perf)

Three things this table makes obvious:

  1. 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.
  2. 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.
  3. 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

PanePositionPurpose
Agents listleft column, top halfAll known agents in scope. Glyph: ▶ running, ⏸ paused, ✓ done, ✗ fail
Agent detailcentre column, top halfSelected agent's spec + status + contract + heartbeat
Tool streamright column, top halfLive tail of selected agent's tool calls (and results)
Sub-agent treeleft+centre, bottomTree view of selected agent's children (Wave T ParentIndex)
Goal / Mission cardright, bottomGoal autonomy contract + mission progress + probe + drift
Status stripbottom rowProvider, model, rank, connectors, A2A channels, clock
Hotkey stripbottom rowAlways-visible hotkey crib

Navigation + hotkeys

Discipline borrowed from opencode (leader key) but with single-key + numeric focus switching à la htop / k9s for raw speed:

KeyAction
15Focus pane 1 (agents) … 5 (mission)
↑ ↓ j kMove cursor inside focused pane
g GTop / bottom of focused pane
/Filter agents (fuzzy: id, scope, model, status)
Tab / Shift+TabCycle scope (all → tg-12345 → discord-xxx → mc-xxx …)
Inspect selected agent — opens chat-TUI in read-only review
cCancel selected agent (writes running/<id>.cancel = true)
pPause selected agent (proposed — needs runner support)
rRetry selected agent (re-spawn with same spec)
nSpawn new agent — opens spec form overlay
fToggle follow-mode on tool stream
?Help overlay (auto-generated from KeyMap)
q EscQuit cockpit (chat TUI remains running if it was open)
Ctrl+LHard refresh (re-scan disk + re-fetch HTTP)
Ctrl+SToggle 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.

SurfaceSource todayRead modeRefresh
Agent registrystate.kernel.scheduler.list_agents() exposed by GET /v1/agentsHTTPpoll 1 s
Sub-agent spec/running`~/.openalice/data/{agent}/agents/spec\running\results/*.json + _parent_index.json`direct FS readpoll 500 ms
Sub-agent (scoped)~/.openalice/data/{agent}/chat/{scope}/agents/... (Wave S/Phase 8AA-4 canonical layout)direct FS readpoll 500 ms
A2A channels & historymcp__openalice-a2a__a2a_status + _channels + _history (tool surface, transport HTTP)HTTP via tool bridgepoll 2 s
A2A discoverya2a_discover tool surfaceHTTPon demand
Mission stateMission from openalice-agents::mission_engine + tools_mission.rsHTTP (proposed /v1/missions)poll 2 s
Goal contractNEW~/.openalice/data/{agent}/chat/{scope}/goal.yaml (proposed Wave 8GG)direct FS readpoll 1 s
HeartbeatNEWrunning/<id>.json already has started_at; extend with last_heartbeat_atdirect FS readpoll 500 ms
Tool stream/v1/chat/stream SSE per-agent stream — already wired into chat-TUI tool_feedSSElive
Probe resultsopenalice-lab writes traces under lab-data/ — surfaced as last-pass/fail per scopedirect FS read (lab dir)poll 5 s (optional)
Goal driftagents-safety::goal_drift writes a drift score to storeHTTP /v1/safety/driftpoll 5 s
Rank glyphrank ledger in store, exposed via /v1/agents/{id}/xp + /v1/rank_chartHTTPpoll on selection
Connector health/v1/connectors/* + /v1/presenceHTTPpoll 5 s
Features / versionopenalice_schemas::features::FEATURES (linkme), already 502 entriesin-processonce 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 when notify is 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 (watchcockpit), 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_agents and ParentIndex::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, status Experimental.

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 each agents/ root and goal.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 a cockpit::client submodule.
  • 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.

  • c cancel → writes running/<id>.cancel = true (already supported by agent::runner::cancel_agent).
  • r retry → re-reads the spec, generates a fresh agent_id, calls agent::runner::spawn_subagent (reuse Wave T code path, not via HTTP, to keep latency tight).
  • n spawn → modal form that calls the same spawn_subagent API.
  • p pause — proposed new runner verb: writes running/<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 KeyMap registry (copy the bubbletea pattern noted in docs/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-lab is 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 behind OPENALICE_COCKPIT_METRICS=1 because 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.

  1. Subcommand vs separate binary. alice cockpit (subcommand of the existing CLI) vs a new alice-cockpit standalone 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 the crates/tui/src/lib.rs rationale: DEFAULT_ENDPOINT = http://127.0.0.1:8080).
  1. Daemon mode (background watcher) — yes or no? A daemon-mode cockpit could run headless, exposing a /v1/cockpit/snapshot JSON 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.
  1. 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.
  1. `/goal` semantics — file format and writer. Hermes uses a /goal slash-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.yaml with fields goal, exit_conditions[], max_turns, max_tokens, max_wall_ms, started_at. Writer: a new tool goal_set from the chat surface, readable by both chat TUI and cockpit. This is also a Wave J task- contract pre-req (memory note wave-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.
  1. 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: bool to RunningState, worker polls it in the same 100 ms loop as cancel. Cost: ~50 LOC + tests. Default: yes, do it in Phase C. Needs NAO confirm because it touches the Wave T contract.
  1. Multi-host fleet view. Long-term we want to see agents across alice.blal.pro + future alice.eu.openalicelabs.com etc. 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.
  1. 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.
  1. Permissioning model. Cockpit can cancel agents owned by other chat scopes. Should this require a confirmation prompt? Default: yesc cancel always confirms; in --unattended it 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-wake crate). 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::theme palette with one extra cockpit palette key. No /themes modal 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.1 and 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.json only. 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 use AgentLayout::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 behind cockpit.<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 — add notify, 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 existing ToolFeed).
  • 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.rscockpit subcommand wired to openalice_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.