diff --git a/docs/architecture/index.html b/docs/architecture/index.html new file mode 100644 index 000000000..46bd2dcac --- /dev/null +++ b/docs/architecture/index.html @@ -0,0 +1,1000 @@ + + + + + + Agent Orchestrator Architecture + + + +
+ + +
+
+
Verified against source · Last generated for this worktree
+

How AO turns one task into a durable, observable coding agent.

+

Agent Orchestrator (AO) is a pluggable TypeScript monorepo for spawning AI coding agents in isolated workspaces, supervising their lifecycle, wiring PR/CI/review feedback loops, and exposing all of it through a Next.js dashboard with live terminal attachment.

+
+
31pnpm package manifests under packages/**
+
8architectural slots: 7 plugin slots + core lifecycle
+
0databases; durable state is JSON/YAML flat files
+
3prompt layers: base + config + repo rules
+
+
+ +
+
+
+ 01 · Overview +

One-screen architecture

+

The high-level model in CLAUDE.md describes AO as parallel AI coding agents, each in an isolated git worktree with its own PR, supervised from one dashboard CLAUDE.md:3-5. The source verifies that the implementation is centered on a small core, pluggable edges, and flat-file persistence.

+
+
+ +
+
System architecture: core engine surrounded by plugin slots
+
flowchart LR
+  User["Human / Orchestrator"]:::user --> CLI["ao CLI\nstart · spawn · stop · restore"]:::cli
+  CLI --> Core["@aoagents/ao-core\nConfig · Registry · Session Manager\nLifecycle Manager · Metadata"]:::core
+  Config["agent-orchestrator.yaml\nZod validated"]:::file --> Core
+
+  subgraph Slots["Plugin extension boundary"]
+    Runtime["Runtime\ntmux / process"]:::runtime
+    Agent["Agent\nClaude Code / Codex / OpenCode / Aider / Cursor"]:::agent
+    Workspace["Workspace\nworktree / clone"]:::workspace
+    Tracker["Tracker\nGitHub / Linear / GitLab"]:::tracker
+    SCM["SCM\nPR · CI · reviews"]:::scm
+    Notifier["Notifier\ndesktop / Slack / Discord / webhook"]:::notifier
+    Terminal["Terminal\niTerm2 / web"]:::terminal
+  end
+
+  Core --> Runtime
+  Core --> Agent
+  Core --> Workspace
+  Core --> Tracker
+  Core --> SCM
+  Core --> Notifier
+  Core --> Terminal
+  Core --> Lifecycle["Lifecycle\ncore state machine + poller"]:::lifecycle
+  Lifecycle --> Events["Events + reactions"]:::event
+  Events --> Notifier
+
+  Core --> Store["Flat-file state\n~/.agent-orchestrator"]:::file
+  Core --> WebAPI["Next.js API routes"]:::web
+  WebAPI --> Mux["Mux WebSocket\nsession snapshots + terminal streams"]:::web
+  Mux --> Dashboard["React dashboard\nKanban + xterm.js"]:::web
+
+  classDef core fill:#172554,stroke:#60a5fa,color:#eff6ff,stroke-width:2px;
+  classDef cli fill:#0f172a,stroke:#94a3b8,color:#e2e8f0;
+  classDef file fill:#1e293b,stroke:#64748b,color:#e2e8f0;
+  classDef user fill:#312e81,stroke:#a78bfa,color:#f5f3ff;
+  classDef runtime fill:#164e63,stroke:#22d3ee,color:#ecfeff;
+  classDef agent fill:#4c1d95,stroke:#a78bfa,color:#faf5ff;
+  classDef workspace fill:#064e3b,stroke:#34d399,color:#ecfdf5;
+  classDef tracker fill:#78350f,stroke:#fbbf24,color:#fffbeb;
+  classDef scm fill:#831843,stroke:#f472b6,color:#fdf2f8;
+  classDef notifier fill:#7c2d12,stroke:#fb923c,color:#fff7ed;
+  classDef terminal fill:#1e3a8a,stroke:#60a5fa,color:#eff6ff;
+  classDef lifecycle fill:#7f1d1d,stroke:#fb7185,color:#fff1f2;
+  classDef web fill:#0f766e,stroke:#2dd4bf,color:#f0fdfa;
+  classDef event fill:#3f3f46,stroke:#a1a1aa,color:#fafafa;
+
+ +
+
+

Core owns orchestration

+

session-manager.ts owns spawn/kill/restore/send, while lifecycle-manager.ts owns detection, state transitions, reactions, and notifications packages/core/src/session-manager.ts:1-12 packages/core/src/lifecycle-manager.ts:1-10.

+
+
+

Plugins own replaceable integrations

+

The public contract is PluginModule<T>: a manifest, a create function, and optional detection. The registry normalizes default/named exports and loads built-ins/configured plugins packages/core/src/types.ts:1728-1753 packages/core/src/plugin-registry.ts:297-312.

+
+
+

Files are the database

+

Session metadata lives under ~/.agent-orchestrator/projects/{projectId}/sessions/{sessionId}.json; status is computed from canonical lifecycle when read packages/core/src/metadata.ts:1-11 packages/core/src/metadata.ts:159-163.

+
+
+
+ +
+
+
+ 02 · Monorepo +

Repository layout and build topology

+

The root workspace includes both first-party packages and plugin packages via packages/* and packages/plugins/* pnpm-workspace.yaml:1-3. The root build script runs recursive pnpm builds package.json:12-27; workspace dependencies make the effective topology core → plugins → cli/web, matching the high-level docs CLAUDE.md:11-33.

+
+
+ +
+
Monorepo dependency map
+
flowchart TB
+  Root["Root workspace\nNode >=20.18.3 · pnpm 9.15.4"]:::root --> Core["packages/core\ninterfaces · config · lifecycle · metadata"]:::core
+  Root --> Plugins["packages/plugins/*\nagent · runtime · workspace · tracker · scm · notifier · terminal"]:::plugins
+  Root --> CLI["packages/cli\nao command · start/stop · supervisor"]:::app
+  Root --> Web["packages/web\nNext.js 15 dashboard · mux WS · xterm.js"]:::app
+  Root --> AO["packages/ao\nglobal CLI wrapper"]:::app
+  Root --> Tests["packages/integration-tests"]:::test
+  Root --> NotifierMac["packages/notifier-macos"]:::plugins
+
+  Core --> Plugins
+  Core --> CLI
+  Core --> Web
+  Plugins --> CLI
+  Plugins --> Web
+  Web --> CLI
+
+  classDef root fill:#0f172a,stroke:#94a3b8,color:#f8fafc;
+  classDef core fill:#172554,stroke:#60a5fa,color:#eff6ff,stroke-width:2px;
+  classDef plugins fill:#312e81,stroke:#a78bfa,color:#f5f3ff;
+  classDef app fill:#064e3b,stroke:#34d399,color:#ecfdf5;
+  classDef test fill:#78350f,stroke:#fbbf24,color:#fffbeb;
+
+ + + + + + + + + +
LayerWhat lives thereRepresentative source
CoreTyped integration contracts, config loader, plugin registry, lifecycle, session manager, path and metadata helpers.packages/core/src/types.ts:3-18
PluginsConcrete implementations. For example, tmux exports a runtime manifest/create/default module and Codex exports an agent manifest/create/detect/default module.packages/plugins/runtime-tmux/src/index.ts:21-26 packages/plugins/agent-codex/src/index.ts:41-47
CLIPackages the command surface and depends on core, web, and many built-in plugins.packages/cli/package.json:35-61
WebNext.js dashboard, API routes, WebSocket mux, xterm.js terminal client; depends on core, selected plugins, Next/React/ws/xterm.packages/web/package.json:48-70
+ +
+

Why this split?

+

The core stays stable and testable while every environment-specific edge is swappable. New agents, SCMs, notifiers, or terminal UIs can be introduced as packages without changing the state machine or session manager contracts.

+
+
+ +
+
+
+ 03 · Plugins +

The plugin-slot model

+

AO documents eight architectural slots, but the TypeScript PluginSlot union exposes seven loadable plugin slots; Lifecycle is intentionally core/non-pluggable CLAUDE.md:80-96 packages/core/src/types.ts:1718-1726. The interfaces are all centralized in types.ts, which makes plugin changes explicit and reviewable packages/core/src/types.ts:3-18.

+
+
+ + + + + + + + + + + + + +
SlotInterface linesResponsibilityExamples / defaults
Runtimepackages/core/src/types.ts:386-424Create, attach to, send input to, and destroy the process environment where an agent runs.tmux, process
Agentpackages/core/src/types.ts:477-576Define how to detect, launch, prompt, and observe a particular coding tool.Claude Code, Codex, OpenCode, Aider, Cursor, Grok, Kimi
Workspacepackages/core/src/types.ts:650-688Create isolated code workspaces and clean/restore them.worktree, clone
Trackerpackages/core/src/types.ts:707-749Fetch issue/task context and update external task status.GitHub, GitLab, Linear
SCMpackages/core/src/types.ts:786-900Inspect branches, PRs, CI checks, review comments, and mergeability.GitHub, GitLab
Notifierpackages/core/src/types.ts:1160-1181Deliver lifecycle and attention notifications to humans.Desktop, Slack, Discord, webhook, Composio
Terminalpackages/core/src/types.ts:1196-1215Open or attach a human-facing terminal UI.iTerm2, web terminal
Lifecyclepackages/core/src/lifecycle-manager.ts:1-10Core state machine, polling loop, reactions, escalation, cleanup. Not a registry plugin.Built into @aoagents/ao-core
+ +
+
+

Registry and discovery

+

Built-in packages are enumerated by slot in plugin-registry.ts packages/core/src/plugin-registry.ts:38-72. The registry supports register, get, list, loadBuiltins, and loadFromConfig packages/core/src/plugin-registry.ts:420-623.

+
+
+

Export contract

+

A plugin module exports manifest, create(config?), and optional detect. The registry also handles default-export modules packages/core/src/types.ts:1728-1753 packages/core/src/plugin-registry.ts:297-312.

+
+
+ +
// Shape verified in packages/core/src/types.ts:1728-1753
+export interface PluginModule<T> {
+  manifest: PluginManifest;
+  create(config?: Record<string, unknown>): T | Promise<T>;
+  detect?(): Promise<boolean>;
+}
+
+ +
+
+
+ 04 · Lifecycle +

Canonical state machine + derived legacy status

+

AO separates durable lifecycle truth from UI/back-compat display status. Canonical lifecycle has eight states and structured reasons packages/core/src/types.ts:29-57; legacy SessionStatus remains a broader display/API vocabulary packages/core/src/types.ts:118-137.

+
+
+ +
+
Session lifecycle state machine
+
stateDiagram-v2
+  [*] --> not_started: metadata reserved
+  not_started --> working: runtime created + agent launched
+
+  working --> idle: ready / no activity / waiting on PR
+  working --> needs_input: agent explicitly waits for human
+  working --> detecting: runtime or agent signal is uncertain
+  working --> done: agent reports completion without further action
+  working --> terminated: fatal reason
+
+  idle --> working: new activity / human sends instruction
+  idle --> detecting: stale runtime suspicion
+  idle --> terminated: auto_cleanup / pr_merged / manually_killed
+
+  needs_input --> working: human response sent
+  needs_input --> stuck: waiting too long / escalation exhausted
+  needs_input --> terminated: manually_killed
+
+  detecting --> working: probe resolves alive
+  detecting --> stuck: probe cannot recover
+  detecting --> terminated: runtime_lost / probe_failure / agent_process_exited
+
+  stuck --> working: agent recovers / restore succeeds
+  stuck --> terminated: manually_killed / error_in_process
+
+  done --> [*]
+  terminated --> [*]
+
+  note right of terminated
+    Terminal reasons include:
+    manually_killed, pr_merged, auto_cleanup,
+    runtime_lost, agent_process_exited,
+    probe_failure, error_in_process
+  end note
+
+ +
+
+

Canonical storage

+

createInitialCanonicalLifecycle creates new lifecycle objects, while parseCanonicalLifecycle accepts new lifecycle or legacy statePayload data packages/core/src/lifecycle-state.ts:162-193 packages/core/src/lifecycle-state.ts:415-430.

+
+
+

Legacy status is computed

+

deriveLegacyStatus maps canonical state/reason and PR runtime metadata into UI statuses. Metadata patches deliberately do not persist status; it is computed on read packages/core/src/lifecycle-state.ts:432-488 packages/core/src/lifecycle-state.ts:490-505.

+
+
+ +
+

Why canonical vs legacy?

+

Canonical lifecycle keeps the durable state space compact and reasoned: terminated plus runtime_lost is different from terminated plus pr_merged. The old status vocabulary can still represent dashboard buckets like ci_failed, review_pending, approved, or mergeable by deriving them from canonical lifecycle plus PR state packages/core/src/lifecycle-state.ts:432-488.

+
+ +
+
+

Detection and precedence

+

determineStatus probes runtime, agent activity/process, PR state, fresh self-reports, idle thresholds, and uncertain detecting decisions packages/core/src/lifecycle-manager.ts:900-1397. Fresh agent reports outrank weak inference, but not runtime death, waiting-input, or SCM truth packages/core/src/lifecycle-manager.ts:1299-1328.

+
+
+

Polling and reactions

+

The manager enriches PR metadata, checks each session, persists transitions, emits events, notifies humans, dispatches CI/review/conflict work, and performs merge cleanup last packages/core/src/lifecycle-manager.ts:530-748 packages/core/src/lifecycle-manager.ts:2438-2765.

+
+
+ +
+

Poll

pollAll lists sessions, batch-enriches PRs, checks sessions concurrently, prunes old state, and can stop when all work is complete packages/core/src/lifecycle-manager.ts:2865-3043.

+

Decide

resolveProbeDecision is part of the path that turns uncertain runtime/activity evidence into a stable lifecycle transition packages/core/src/lifecycle-manager.ts:1202-1214.

+

React

Reactions can retry, escalate, send instructions to agents, and call notifiers packages/core/src/lifecycle-manager.ts:1399-1624 packages/core/src/lifecycle-manager.ts:2261-2307.

+

Clean

PR merge cleanup is intentionally deferred while agents are busy and delegates deletion to sessionManager.kill when safe packages/core/src/lifecycle-manager.ts:2309-2436.

+
+
+ +
+
+
+ 05 · Session Manager +

Spawn, list, kill, send, restore

+

The session manager is the imperative coordinator. Its own header summarizes the contract: create workspace, create runtime, launch agent, list metadata plus live runtime state, kill, cleanup, and send packages/core/src/session-manager.ts:1-12.

+
+
+ +
+
Spawn orchestration path
+
flowchart LR
+  Task["User task / issue"] --> Resolve["Resolve project + plugins"]:::core
+  Resolve --> Tracker["Fetch issue context\n(optional tracker)"]:::tracker
+  Tracker --> Reserve["Reserve session id\nO_EXCL metadata"]:::file
+  Reserve --> Branch["Compute branch"]:::workspace
+  Branch --> Workspace["workspace.create + hooks"]:::workspace
+  Workspace --> Prompt["buildPrompt\nbase + config + rules + task"]:::prompt
+  Prompt --> AgentConfig["agent.getLaunchConfig"]:::agent
+  AgentConfig --> Runtime["runtime.create\nAO env vars"]:::runtime
+  Runtime --> Metadata["write metadata\ncanonical lifecycle"]:::file
+  Metadata --> Post["postLaunchSetup / initial send"]:::agent
+
+  classDef core fill:#172554,stroke:#60a5fa,color:#eff6ff;
+  classDef tracker fill:#78350f,stroke:#fbbf24,color:#fffbeb;
+  classDef file fill:#1e293b,stroke:#64748b,color:#e2e8f0;
+  classDef workspace fill:#064e3b,stroke:#34d399,color:#ecfdf5;
+  classDef prompt fill:#312e81,stroke:#a78bfa,color:#f5f3ff;
+  classDef agent fill:#4c1d95,stroke:#a78bfa,color:#faf5ff;
+  classDef runtime fill:#164e63,stroke:#22d3ee,color:#ecfeff;
+
+ + + + + + + + + + + + +
OperationWhat it doesSource
Resolve pluginsLocates project-scoped runtime/agent/workspace/tracker/scm/notifier/terminal instances through the registry.packages/core/src/session-manager.ts:902-918
SpawnReserves IDs, creates workspace, builds prompt, configures agent, creates runtime with AO environment, writes metadata, then does post-launch setup. Rollback is guarded by a cleanup stack.packages/core/src/session-manager.ts:1212-1598
Orchestrator spawnUses the same primitives but launches an AO orchestrator session with generated prompt and permissionless settings.packages/core/src/session-manager.ts:1619-2070 packages/core/src/session-manager.ts:1871-1888
List / getReads metadata across projects, enriches runtime state, and computes display status. get fetches one enriched record.packages/core/src/session-manager.ts:2235-2368 packages/core/src/session-manager.ts:2386-2443
Kill / cleanupDestroys runtime and workspace, handles idempotency, and writes canonical terminated lifecycle.packages/core/src/session-manager.ts:2445-2607 packages/core/src/session-manager.ts:2609-2801
Send / restorePrepares or restores runtime as needed, sends input, and can rebuild workspace/runtime for restorable sessions.packages/core/src/session-manager.ts:2803-3119 packages/core/src/session-manager.ts:3271-3618
Claim PRAttaches an existing pull request to a session record.packages/core/src/session-manager.ts:3121-3244
+ +
+

Important invariant: list can detect stale runtimes, but not terminate them

+

sessionManager.list() may persist a detecting state with runtime_lost when a tmux/process runtime disappears, but comments make the lifecycle manager the “single authority on terminal decisions” packages/core/src/session-manager.ts:2303-2306 packages/core/src/session-manager.ts:2324-2348.

+
+
+ +
+
+
+ 06 · Storage +

Flat files, no database

+

AO persists durable state in YAML and JSON files under a project-oriented layout. Current V2 paths are under ~/.agent-orchestrator/projects/{projectId}; older hash-based helpers remain marked deprecated/legacy in paths.ts packages/core/src/metadata.ts:1-11 packages/core/src/paths.ts:1-15 packages/core/src/paths.ts:152-200.

+
+
+ +
+
Durable state layout
+
flowchart TB
+  LocalConfig["agent-orchestrator.yaml\nnearest config found from cwd"]:::yaml
+  GlobalConfig["~/.agent-orchestrator/config.yaml\nregistered projects + identity"]:::yaml
+  Home["~/.agent-orchestrator"]:::dir
+  Home --> GlobalConfig
+  Home --> Running["running.json\ncurrent ao start PID / port / projects"]:::json
+  Home --> LastStop["last-stop.json\nsessions stopped by ao stop / Ctrl+C"]:::json
+  Home --> Projects["projects/{projectId}/"]:::dir
+  Projects --> Sessions["sessions/{sessionId}.json\nsession metadata + lifecycle"]:::json
+  Projects --> Orchestrator["orchestrator.json\norchestrator session metadata"]:::json
+  Projects --> Worktrees["worktrees/{sessionId}/\nagent workspaces"]:::dir
+  Projects --> Feedback["feedback / code-reviews"]:::dir
+  LocalConfig --> Loader["loadConfig()\nYAML + Zod + defaults"]:::core
+  GlobalConfig --> Loader
+
+  classDef yaml fill:#312e81,stroke:#a78bfa,color:#f5f3ff;
+  classDef json fill:#1e293b,stroke:#94a3b8,color:#e2e8f0;
+  classDef dir fill:#064e3b,stroke:#34d399,color:#ecfdf5;
+  classDef core fill:#172554,stroke:#60a5fa,color:#eff6ff;
+
+ +
+
+

Config

+

config.ts loads agent-orchestrator.yaml, validates with Zod, applies defaults, and expands paths packages/core/src/config.ts:1-11 packages/core/src/config.ts:247-381 packages/core/src/config.ts:927-959 packages/core/src/config.ts:996-1018. Resolution checks AO_CONFIG_PATH, cwd parents, global config, and legacy locations packages/core/src/config.ts:747-822.

+
+
+

Global project registry

+

The global config path can come from AO_GLOBAL_CONFIG, XDG, or ~/.agent-orchestrator/config.yaml packages/core/src/global-config.ts:75-99. It is loaded/saved atomically and merges global identity with local project behavior packages/core/src/global-config.ts:341-384 packages/core/src/global-config.ts:857-886.

+
+
+

Metadata

+

metadataPath, readMetadata, atomic writes, locked mutation, list, and O_EXCL ID reservation provide file-backed session state packages/core/src/metadata.ts:137-146 packages/core/src/metadata.ts:280-325 packages/core/src/metadata.ts:331-459 packages/core/src/metadata.ts:508-546.

+
+
+

CLI process state

+

running.json tracks the active ao start process and dashboard port; last-stop.json stores sessions killed by stop/Ctrl+C so startup can offer restore packages/cli/src/lib/running-state.ts:16-29 packages/cli/src/lib/running-state.ts:171-205 packages/cli/src/lib/running-state.ts:311-353.

+
+
+ +
+

Why flat files?

+

AO is a local developer tool that needs transparent, inspectable, crash-resilient state rather than a server database. Atomic JSON writes and file locks keep session metadata durable while keeping setup to “install packages and run ao start.”

+
+
+ +
+
+
+ 07 · Data flow +

From ao start to dashboard render

+

The user-facing flow begins in the CLI, starts the dashboard and project supervisors, ensures an orchestrator session, then uses core services and web API routes to render session state.

+
+
+ +
+
Sequence: startup, supervision, and dashboard updates
+
sequenceDiagram
+  autonumber
+  actor Human
+  participant CLI as ao CLI
+  participant Config as Config loader
+  participant Registry as Plugin registry
+  participant SM as SessionManager
+  participant LM as LifecycleManager
+  participant Store as Flat files
+  participant API as Next.js API
+  participant Mux as mux WebSocket
+  participant UI as React dashboard
+
+  Human->>CLI: ao start
+  CLI->>Config: load agent-orchestrator.yaml + global config
+  Config->>Registry: create registry + load/register plugins
+  CLI->>SM: createSessionManager(config, registry)
+  CLI->>API: start dashboard server
+  CLI->>SM: ensure orchestrator session
+  SM->>Store: write orchestrator/session metadata
+  CLI->>LM: start per-project lifecycle worker
+  LM->>SM: list sessions
+  SM->>Store: read metadata + enrich runtime state
+  LM->>Registry: query SCM / agent / runtime plugins
+  LM->>Store: persist lifecycle transitions + events
+  UI->>API: GET /api/sessions initial snapshot
+  API->>SM: list/listCached sessions
+  API->>Store: read supplemental metadata
+  API-->>UI: sessions + stats + orchestrators
+  UI->>Mux: open WebSocket
+  Mux->>API: poll /api/sessions/patches every 3s
+  Mux-->>UI: session snapshot / terminal messages
+  UI-->>Human: Kanban, detail, xterm terminal
+
+ +
+

CLI startup

runStartup starts the dashboard and resolves the port, ensures an orchestrator session, starts the project supervisor, restores last-stop sessions if requested, then registers running.json with PID, config path, port, and projects packages/cli/src/commands/start.ts:900-949 packages/cli/src/commands/start.ts:953-1019 packages/cli/src/commands/start.ts:1021-1160 packages/cli/src/commands/start.ts:1746-1757.

+

Lifecycle workers

The project supervisor reconciles lifecycle workers based on non-terminal sessions and runs a 60-second supervisor loop. Each worker creates a lifecycle manager and starts it with the default 30-second interval packages/cli/src/lib/project-supervisor.ts:118-240 packages/cli/src/lib/lifecycle-service.ts:30-75.

+

Web services

Web uses a singleton service module to load dashboard config, create a registry, register static plugins, and create session/lifecycle managers. Comments clarify that CLI polling is authoritative and web lifecycle is mainly for webhook checks packages/web/src/lib/services.ts:1-13 packages/web/src/lib/services.ts:104-133.

+

API and live transport

/api/sessions lists, filters, serializes, and enriches sessions packages/web/src/app/api/sessions/route.ts:72-201. /api/sessions/patches returns lightweight dashboard patches from cached sessions packages/web/src/app/api/sessions/patches/route.ts:8-44.

+
+ +
+

Verified current-source note about SSE

+

Older high-level docs mention an SSE stream. In the current source inspected for this document, live dashboard updates are implemented through the mux WebSocket: the server polls /api/sessions/patches every 3 seconds and broadcasts snapshots, while the client merges mux updates and uses full refreshes for membership/staleness. No current text/event-stream/EventSource route was found in the web package during this audit packages/web/server/mux-websocket.ts:1-7 packages/web/server/mux-websocket.ts:77-198 packages/web/src/hooks/useSessionEvents.ts:148-340.

+
+
+ +
+
+
+ 08 · Web +

Dashboard, mux WebSocket, and xterm.js

+

The dashboard is a Next.js 15 app with React 19 and xterm.js. It reads session snapshots from API routes, subscribes to mux WebSocket messages, and renders project-scoped Kanban lanes while the sidebar can include all projects.

+
+
+ +
+
+

Session data

+

Dashboard.tsx calls useSessionEvents and intentionally does not filter session events by project at the hook boundary; it filters the Kanban client-side and groups sessions by attention level packages/web/src/components/Dashboard.tsx:146-179 packages/web/src/components/Dashboard.tsx:287-300.

+
+
+

Mux provider

+

MuxProvider builds the WebSocket URL, reconnects, re-opens terminal streams, subscribes to session and notification channels, and handles terminal/session/notification messages packages/web/src/providers/MuxProvider.tsx:84-237.

+
+
+

Terminal setup

+

DirectTerminal delegates xterm setup to useXtermTerminal, which dynamically imports xterm/addons, opens a mux terminal, sends input/resizes, and re-sends dimensions after reconnect packages/web/src/components/DirectTerminal.tsx:35-72 packages/web/src/components/terminal/useXtermTerminal.ts:80-115 packages/web/src/components/terminal/useXtermTerminal.ts:278-390.

+
+
+

HTTP refresh path

+

The session API routes remain the canonical refresh/snapshot path. The patch endpoint is intentionally lightweight and is polled by the mux broadcaster rather than every browser tab polling independently packages/web/src/app/api/sessions/route.ts:72-201 packages/web/server/mux-websocket.ts:170-198.

+
+
+
+ +
+
+
+ 09 · Prompts +

Prompt assembly and orchestrator prompt generation

+

Agent prompts are intentionally layered so AO can enforce operational behavior while still letting project configuration and repository rules shape local coding style.

+
+
+ +
+
Prompt layering
+
flowchart LR
+  Base["Layer 1: Base AO agent prompt\nmanaged session lifecycle + PR workflow"]:::base
+  Config["Layer 2: Config-derived context\nproject name, repo, agent behavior, defaults"]:::config
+  Rules["Layer 3: User rules\nagentRules + agentRulesFile"]:::rules
+  Task["Task / issue prompt"]:::task
+  Agent["Coding agent launch config"]:::agent
+
+  Base --> Config --> Rules --> Task --> Agent
+
+  OrchTemplate["orchestrator.md template"]:::base --> OrchData["project + dashboard + reactions + rules"]:::config --> OrchPrompt["Orchestrator session prompt"]:::agent
+
+  classDef base fill:#172554,stroke:#60a5fa,color:#eff6ff;
+  classDef config fill:#064e3b,stroke:#34d399,color:#ecfdf5;
+  classDef rules fill:#78350f,stroke:#fbbf24,color:#fffbeb;
+  classDef task fill:#312e81,stroke:#a78bfa,color:#f5f3ff;
+  classDef agent fill:#4c1d95,stroke:#a78bfa,color:#faf5ff;
+
+ +
+
+

Agent prompt builder

+

prompt-builder.ts documents the three layers, defines the base agent prompt, gathers config-derived context, reads user rules from config/files, then builds the final prompt with optional orchestrator back-channel instructions and task content packages/core/src/prompt-builder.ts:1-11 packages/core/src/prompt-builder.ts:21-57 packages/core/src/prompt-builder.ts:111-182 packages/core/src/prompt-builder.ts:188-237.

+
+
+

Orchestrator prompt

+

orchestrator-prompt.ts renders the bundled orchestrator.md template with project path/name/repo/default branch, session prefix, dashboard port, reaction descriptions, and orchestrator rules packages/core/src/orchestrator-prompt.ts:1-8 packages/core/src/orchestrator-prompt.ts:33-68 packages/core/src/orchestrator-prompt.ts:144-199.

+
+
+ +
+

Why layers?

+

Base behavior protects AO invariants such as PR creation, status reporting, and lifecycle signals. Config and repo rules then adapt that behavior to a project without forking agent plugins or the session manager.

+
+
+ +
+
+
+ 10 · Platform +

Cross-platform abstractions

+

AO treats macOS, Linux, and Windows as first-class. The project’s golden rule is to avoid ad-hoc process.platform === "win32" checks and centralize branching in helpers from @aoagents/ao-core docs/CROSS_PLATFORM.md:9-19.

+
+
+ +
+
+

Central helper module

+

platform.ts defines isWindows, isMac, isLinux, chooses default runtime (process on Windows, tmux elsewhere), resolves shells, kills process trees, finds PIDs by port, and normalizes env defaults packages/core/src/platform.ts:8-29 packages/core/src/platform.ts:44-62 packages/core/src/platform.ts:88-143 packages/core/src/platform.ts:154-245.

+
+
+

Deep compatibility guide

+

docs/CROSS_PLATFORM.md inventories helpers and calls out Windows gotchas such as PowerShell vs bash, PATH wrappers, process probing, localhost binding, and agent-plugin specifics docs/CROSS_PLATFORM.md:43-68 docs/CROSS_PLATFORM.md:172-181.

+
+
+ +
+

Why centralize OS branching?

+

Platform checks are otherwise hard to mock and easy to regress. A single helper layer lets tests simulate Windows/macOS/Linux behavior and keeps plugin/runtime code from silently drifting into POSIX-only assumptions.

+
+
+ +
+
+
+ 11 · Source index +

Key files for future readers

+

If you are new to AO, read these files in order. The list is intentionally biased toward source of truth over high-level docs.

+
+
+ +
+

Orientation: CLAUDE.md:3-33 skills/agent-orchestrator/SKILL.md:7-27

+

Workspace/package shape: pnpm-workspace.yaml:1-3 package.json:7-27 packages/cli/package.json:35-61 packages/web/package.json:48-70

+

Core interfaces and plugins: packages/core/src/types.ts:3-18 packages/core/src/types.ts:1718-1753 packages/core/src/plugin-registry.ts:38-72 packages/core/src/plugin-registry.ts:420-623

+

Lifecycle: packages/core/src/lifecycle-state.ts:45-127 packages/core/src/lifecycle-state.ts:432-505 packages/core/src/lifecycle-manager.ts:900-1397 packages/core/src/lifecycle-manager.ts:2438-3043

+

Session orchestration: packages/core/src/session-manager.ts:1212-1598 packages/core/src/session-manager.ts:2235-2368 packages/core/src/session-manager.ts:2445-2801 packages/core/src/session-manager.ts:3271-3618

+

Storage/config: packages/core/src/metadata.ts:1-11 packages/core/src/paths.ts:112-145 packages/core/src/config.ts:247-381 packages/core/src/global-config.ts:75-99 packages/cli/src/lib/running-state.ts:16-29

+

CLI + web flow: packages/cli/src/commands/start.ts:900-1019 packages/cli/src/lib/project-supervisor.ts:118-240 packages/web/src/lib/services.ts:104-133 packages/web/server/mux-websocket.ts:77-198 packages/web/src/hooks/useSessionEvents.ts:148-340

+

Prompt/platform: packages/core/src/prompt-builder.ts:1-237 packages/core/src/orchestrator-prompt.ts:1-199 packages/core/src/platform.ts:8-245 docs/CROSS_PLATFORM.md:9-68

+
+
+ + +
+
+ + + +