# Agent Fleet Architecture
Agent Fleet is a Pi-centered multi-agent orchestration system. This page maps
the runtime responsibilities and where each module lives in the repository.
## Runtime layers
| Layer | Role | Implementation |
| --- | --- | --- |
| **Pi Coding Agent** | Primary local runtime — runs the dispatcher and specialist subagents | `.pi/harnesses/`, `.pi/extensions/`, `.pi/agents/`, `.pi/prompts/` |
| **agent-hub** | Thin-context multi-agent harness: dispatcher + specialists + research helpers + Verification Contract | `.pi/harnesses/agent-hub/` |
| **Herdr** | Fleet/workspace control plane — spawns peer teams as tiled workspaces, presence via push events, snapshot/resume | [herdr.dev](https://herdr.dev); client in `.pi/harnesses/lib/herdr-client.ts`, layout in `scripts/lib/herdr-layout.ts` |
| **coms** | Peer communication protocol/data plane — envelope-based P2P messaging between agents | `.pi/harnesses/coms/`, `scripts/lib/coms-envelope.ts`, `scripts/coms-cli.ts` |
| **Claude Code bridge** | Makes an interactive Claude Code pane a bidirectional coms peer | `scripts/coms-claude-bridge.ts`, `hooks/coms-stop-hook.mjs`, `skills/peer-coms/` — see [claude-code-coms-bridge.md](claude-code-coms-bridge.md) |
| **Hermes bridge** | Remote human control — relays hub questions to Telegram, races phone vs. local answers, conductor/liaison skills | `scripts/coms-hermes-bridge.ts`, `.pi/harnesses/ask-user-remote/`, `hermes/skills/` — see [coms-hermes-bridge.md](coms-hermes-bridge.md) |
| **Hermes local monitor transport** | Local, authenticated visibility/control contract for hub-owned task generations; presentation is supplied by an external consumer | `.pi/harnesses/agent-hub/monitor-*.ts`, `scripts/lib/hermes-monitor-{model,store,registry,socket}.ts` — see [Hermes artifacts](../hermes/README.md#local-agent-hub-monitor-integration) |
| **Codex remote-control conductor** | Experimental outbound-only, user-systemd-managed Android conductor; verified on Codex CLI 0.144.x | `scripts/codex-remote-control.ts`, `scripts/codex-conductor.ts`, `codex/CONDUCTOR.md`, `systemd/user/`; runtime under `~/.local/state/agent-fleet/codex-conductor/` — see [codex-remote-conductor.md](codex-remote-conductor.md) |
| **Skill library** | Lifecycle workflows and quality gates every agent follows | `skills/` (native) + `vendor/agent-skills-upstream/skills/` (vendored) — see [UPSTREAM-SKILLS.md](UPSTREAM-SKILLS.md) |
| **Personas** | Reusable specialist definitions, transformed per harness | `agents/`, `bin/lib/transform-persona.js` |
## Fleet hierarchy
Agent Fleet is layered on purpose. Work flows **down** (delegate); evidence and status flow **up** — as compact structured returns, never raw dumps.
```mermaid
flowchart TD
You(["You · Hermes inbound relay · Codex outbound conductor on your phone"])
subgraph HUBL["HUB — thin dispatcher (just hub · just hub-team)"]
Hub["agent-hub harness + orchestrator persona
routes tasks · owns the Verification Contract on disk
never swallows research dumps into its own context"]
end
subgraph TEAML["TEAM — named roster (.pi/agents/teams.yaml)"]
Team["default: planner · plan-reviewer · builder · test-engineer · code-reviewer · documenter
also: debug · frontend · security · hotfix · release · info"]
end
subgraph RESL["RESEARCH HELPERS — read-only, always available"]
Research["researcher (fast tier — simple reads)
deep-researcher (deep tier — hard, cross-cutting questions)"]
end
subgraph SUBL["SUB-AGENTS — focused children, narrow tools + models"]
Subs["planner → scout · rules · risk
plan-reviewer → feasibility · deps
builder → recon · verifier
test-engineer → coverage-scout · conventions
code-reviewer → preflight · quality · perf · docs
security-auditor → recon · input-sweep · secrets-sweep"]
end
You -->|task| Hub
Hub -->|"dispatch_agent — one persona = one specialist session"| Team
Hub -->|"spawn_research"| Research
Research -.->|"findings written to disk — hub gets paths, not dumps"| Hub
Team -->|"subagents: block (delegate_depth ≥ 1)"| Subs
Subs -.->|"results return to the parent agent only"| Team
Team -.->|"structured return + evidence"| Hub
Hub -.->|"one status line: Assertions: 2✓ 1○ 1✗"| You
```
Every specialist session is one persona from [`agents/`](../agents/) — *skills* tell each agent **how** to work; *personas* define **who** they are (see [agents.md](agents.md)).
The same idea as a tree:
```text
hub (orchestrator)
├── team: default
│ ├── planner → scout · rules · risk
│ ├── plan-reviewer → feasibility · deps
│ ├── builder → recon · verifier
│ ├── test-engineer → coverage-scout · conventions
│ ├── code-reviewer → preflight · quality · perf · docs
│ └── documenter
├── research helpers (spawn_research, any time)
│ ├── researcher
│ └── deep-researcher
└── optional fleet peers (herdr + coms)
├── architect / releaser / web-debugger panes
├── Claude Code peer (coms bridge)
├── Hermes (phone human · inbound ask_user)
└── Codex Remote Control (Android · outbound coms delegation)
```
Composition rule: **the hub (or a slash command) orchestrates; personas do not invoke other personas as peers.** Specialists may only fan out to their configured **sub-agents**. Research helpers write findings to disk; the hub resumes specialists with paths, not raw dumps.
### Research search supervision
The shared `spawnPiAgent` seam supervises every `read`/`grep`/`find`/`ls` call from native
research helpers and nested delegate children. The supervisor tracks JSONL `toolCallId` values
independently, with a default 120-second deadline (`recon-search-timeout-s: 1..3600|off` under
`## agent-hub`). It is a per-tool watchdog; the whole-run bound is separate — the execution
mode's per-run deadline (`agent-turn-timeout-s`), which terminates a hung run as `turn_timeout`.
On timeout or caller cancellation it owns and terminates the child's process group (SIGTERM,
then SIGKILL after a bounded grace), has a separate settlement timer for missing `close`/pipe
drain, and reports timeout separately from cancellation. Research helpers and nested delegates
are each given safe process-group ownership; delegates forward parent termination so no detached
child is orphaned. Full pattern catalog: [references/orchestration-patterns.md](../references/orchestration-patterns.md).
### Execution modes & turn budgets
The hub enforces per-user-turn budgets in code (`run-budget.js`): `fast`/`standard`/`strict`
modes cap `dispatch_agent` calls, `spawn_research` calls, and wall clock per turn, set the
per-run deadline above, and control nested delegation. Exhausted budgets make the dispatch
tools refuse with "summarize and ask the user"; a new user message opens a fresh window.
Specialist context pressure is measured over input + cacheRead + cacheWrite, and specialist
sessions are recycled (fresh spawn instead of `-c` resume) after `session-recycle-runs` runs
or ≥60% measured context — resumed sessions otherwise re-bill their accumulated context on
every model call. Configured under `## agent-hub` (`mode`, `max-dispatches-per-turn`,
`max-research-per-turn`, `turn-wall-time-s`, `agent-turn-timeout-s`, `session-recycle-runs`);
switched live with `/hub-mode`.
On top of the mode sit three qualitative guardrails. **Task triage**: the dispatcher
classifies each turn via the `set_task_tier` tool (`trivial`/`small`/`feature`/`project`)
and the caps drop to min(mode, tier); a duplicate-dispatch guard refuses near-identical
re-dispatches within a turn. **Drift watchdog** (`drift-watchdog.js`): armed dispatches are
observed in-flight from the JSON event stream — deterministic rules (out-of-scope writes
against the declared `scope` globs, tool-call loops, consecutive failures, tool-call cap)
escalate to a one-shot cheap LLM judge whose DRIFTING/STUCK verdict terminates the run as
`drift_stop` (exit 125, partial output preserved); enabled per hub/agent/dispatch
(`watchdog` key, `/watchdog`, `watchdog` param). **Dynamic teams**: `/agents-add`,
`/agents-drop`, `/agents-save` restructure the roster live (the system prompt rebuilds
every turn), and the gated `team_adjust` tool lets the dispatcher itself adjust the roster
outside fast mode, with user notification. `/hub-report` accounts each turn's dispatches,
tokens (billed = input + cacheRead + cacheWrite), recycles, drift stops, and refusals.
## Runtime stack (tools the fleet sits on)
```mermaid
flowchart TD
AF["Agent Fleet
agent-hub · personas · skills · coms · bridges · CLI"]
AF -->|primary runtime| PI["pi
coding agent — loads harnesses,
extensions, prompts, personas"]
AF -->|control plane| HERDR["herdr
tiled peer workspaces,
presence, snapshot/resume"]
AF -->|peer + install target| CC["Claude Code
bidirectional peer via
the coms bridge"]
AF -->|install target| OC["OpenCode
skill-driven execution
(AGENTS.md + skill tool)"]
AF -->|remote human| HERMES["Hermes
hub questions relayed
to your phone (Telegram)"]
AF -->|outbound remote delegation| CODEX["Codex Remote Control
Android-approved calls to
listed coms peers (experimental)"]
```
### External dependencies
These are the external systems Agent Fleet assumes or integrates with — not npm packages, but the **runtime stack** the fleet operates on top of.
| Dependency | Role | Required? |
| --- | --- | --- |
| **[pi](https://github.com/badlogic/pi-mono)** (or your pi install) | Primary coding-agent runtime; loads harnesses, extensions, prompts, and personas | Yes for full fleet mode (`just hub`) |
| **[herdr](https://herdr.dev)** | Workspace control plane: tiled peer panes, presence push events, team snapshot/resume | Yes for fleet recipes (`just team-up`, `just hub-team`, …); optional for solo hub |
| **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** | First-class peer via the [coms bridge](claude-code-coms-bridge.md); also a supported install target for skills/personas | Optional peer / alternate harness |
| **[OpenCode](https://opencode.ai)** | Skill-driven execution target (`AGENTS.md` + `skill` tool); `af-*` slash commands | Optional alternate harness |
| **Hermes** | Remote human-in-the-loop (Telegram relay for hub questions) — [coms-hermes-bridge](coms-hermes-bridge.md) | Optional |
| **Codex CLI + ChatGPT Android** | Experimental outbound remote-control conductor on supported `0.144.x`; requires Node `22.6+`, user systemd, interactive pairing, and per-command mobile approvals — [runbook](codex-remote-conductor.md) | Optional / revalidate after minor-version or mobile-client changes |
| **[addyosmani/agent-skills](https://github.com/addyosmani/agent-skills)** | Upstream skill library (manually vendored) | Bundled (vendored) |
| **[disler/pi-vs-claude-code](https://github.com/disler/pi-vs-claude-code)** | Source inspiration / MIT port origin for pi harnesses | Design lineage (ported in-repo) |
| **LLM providers** | Models per persona (`model:` / `models:` in agent frontmatter) — e.g. OpenAI Codex, GitHub Copilot, Ollama, … | Yes (at least one provider your agents can call) |
| **Chrome DevTools MCP** / **Playwright Agent CLI** | Browser verify (`browser-testing-with-devtools`) and headless automation (`bowser`) | Optional, feature-specific |
| **Node.js + npm** | CLI (`npx @chankov/agent-fleet`), package install, `just` recipes | Yes for install & tooling |
## Repository module map
```text
.pi/ # Pi runtime: harnesses, extensions, agents config, prompts
skills/ # Agent Fleet-native skills (shadow vendored names)
agents/ # Personas/subagents used by Agent Fleet
scripts/ # CLI helpers, bridges, team launchers (pure logic in scripts/lib/)
hermes/ # Hermes-facing skills/integration assets
codex/ # Canonical Codex conductor contract (runtime copy lives outside checkout)
systemd/user/ # Owned user-unit template for Codex remote control
vendor/agent-skills-upstream/ # Manually imported upstream skills (pinned SHA)
bin/ # npm CLI: init/update/doctor/transform-persona
hooks/ # Session lifecycle + coms Stop hooks
references/ # Supplementary checklists (see fleet-coordination-patterns.md)
docs/ # This file, setup guides, bridge references, vendoring policy
```
Reserved for future modules (do not repurpose these paths):
```text
apps/dashboard/ # future dashboard: Kanban state, Herdr workspaces, peer status
packages/fleet-core/ # future extracted core orchestration library
packages/herdr-bridge/ # future Herdr integration package
packages/hermes-bridge/ # future Hermes integration package
```
## Design rules
- **Thin dispatcher context.** Nothing lands persistently in the dispatcher's
context if it can live on disk or in a one-line status. Research findings,
the Verification Contract ledger, and team snapshots are all disk-first.
- **Herdr owns panes, presence, and lifecycle; coms owns messages.** Fleet
recipes hard-require a running herdr server and refuse with an actionable
message otherwise; non-fleet recipes never touch herdr.
- **External agents are peers, not plugins.** Claude Code (and future CLI
agents) join the fleet through bridge adaptors that speak coms envelopes —
the fleet core stays agent-agnostic. Hermes remains the inbound `ask_user`/
Telegram route; the experimental Codex conductor is outbound-initiated only,
approval-gated, and restricted to listed peers through the validated wrapper.
- **Hermes monitor presentation is outside the fleet core.** Agent Fleet owns task state,
bounded output, leases, and generation-safe cancellation, and exposes them only through
owner-only discovery and a local Unix socket. A Hermes-facing consumer owns its UI and
reconnect behavior; no Hermes backend/Desktop plugin is bundled or installed.
- **External conductor contracts are advisory.** Pi damage-control wraps Pi
tool calls, not Hermes or Codex processes; human approvals and their
contracts reduce risk but do not provide an OS command allowlist.
- **Destructive fleet verbs are damage-control-guarded.** Specialists cannot
spawn/close herdr panes; the human confirms destructive actions.
- **Native-over-vendored skills.** The skill catalogue resolves `skills/`
first, then the vendored upstream import; upstream updates are explicit
maintainer actions ([UPSTREAM-SKILLS.md](UPSTREAM-SKILLS.md)).
## History
Agent Fleet began as a fork of `addyosmani/agent-skills` and was split into a
standalone repository in July 2026, with upstream demoted to vendored content.
The one-time migration record, including the history-filtering commands, lives
in [MIGRATION-agent-fleet.md](MIGRATION-agent-fleet.md); the product
requirements that drove the split are in
[prd-agent-fleet-split.md](prd-agent-fleet-split.md).