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