Core Concepts

Multi-agent coordination

Durable child-agent graph

The root AgentSupervisor owns an agent graph and independently spawned async workers; the root Agent never stores child Agent values. A child id is its durable session id. AgentSpawned is the first event in that session and is committed in the same SQLite transaction as session creation, carrying the root/parent relationship, name, optional type, depth, and compact delegation brief. Status, queued/delivered messages, reports, interrupt, and close are append-only child-session events. Graph replay reduces those events in stable name/id order. A persisted Starting or Running state with no surviving runtime is reconciled once to Interrupted; it is never rerun implicitly.

First starts reserve the worker registry before publishing the child in the runtime graph. First starts and reconstruction share the registry lock through worker creation and registration, so concurrent messages cannot create a second worker or replace the worker carrying the initial delegation brief.

The model-facing schema is fixed: spawn_agent, send_agent_message, continue_agent, wait_agents, list_agents, interrupt_agent, and close_agent exist regardless of graph contents. Spawn is asynchronous; queue-only messages do not wake an idle child, while continue starts a turn or uses the child's steering queue at its next safe boundary. wait_agents returns statuses only — report bodies travel on exactly one channel, the durable kernel notification delivered with the request that reads the wait result. Interrupt cancels a turn but retains the worker/mailbox. Close cancels, waits for resource release, and records the terminal lifecycle. Root shutdown closes all live workers. A child whose worker restarts still owes its opening turn: an undelivered delegation brief is replayed from AgentSpawned ahead of any follow-up. Depth is limited to one, so a child receives the stable tools but every agent control call fails with a normal terminal tool result.

Child context begins fresh: its first user turn is the delegation brief, and its session context independently loads workspace repository instructions. Task state, evidence, failure and progress supervision, continuity, and cache epochs are reconstructed solely from that child session. AgentReport exposes only semantic evidence references; it never imports evidence into the parent ledger. All executors share the root workspace mutation/ownership coordinator and the live root policy locks as a capability ceiling, but processes, grants, and permission brokers remain session-local. OpenAI-compatible transports that use session metadata are cloned with the child id, preserving OpenCode Go's stable x-opencode-session behavior.

Workers never append provider-visible events to the parent asynchronously. They queue compact reports in the supervisor; the root loop drains them only before constructing a model request or after a plain assistant answer, when all prior tool calls already have terminal results. It then appends AgentNotificationDelivered, the sole graph event visible to parent context and the durable resume dedupe marker; the TUI renders it as one quiet transcript line. Internal graph/mailbox events are also excluded from FTS recall.

Agent groups: durable coordination overlay

Three layers stay separate. AgentGraph owns topology and lifecycle, AgentSupervisor owns execution and control, and AgentGroup is an optional, root-scoped coordination overlay: a shared task DAG, atomic claims, a durable peer mailbox, and replayable progress state. The group never owns workers and never replaces the supervisor; children remain independent durable sessions created by the existing spawn path.

The group is created lazily on first use (create task, join, message, or a spawn delegated with task_id), so an ordinary session never grows group state. One root session has at most one group in this version. A group id is durable and stable across resume.

Group events are ordinary durable events in the root session: AgentGroupCreated, AgentGroupMemberJoined, GroupTaskCreated, GroupTaskClaimed, GroupTaskStatusChanged, GroupTaskReleased, GroupMessageQueued, and GroupMessageDelivered. A SQLite projection (agent_groups, group_members, group_tasks, group_messages, group_message_deliveries) exists for atomic claims and efficient lookup, and is rebuilt from the event log at every store open; no group truth lives only in the projection. GroupState::replay reduces the same events deterministically for status, readiness, blockers, and conflict warnings.

A task is a small coordination record: title, description, status, dependency ids, optional assignee, required (default true), and summary/findings/touched paths on completion. A task is ready only when it is Pending and every dependency is Completed. The graph is validated as a real DAG at creation: unknown ids, self-dependency, duplicates, and cycles are hard local errors, and a cyclic graph is never silently repaired. Blocked and Cancelled dependencies never satisfy a dependent task; group status and group_status surface those dependency failures explicitly.

Claiming is a true atomic compare-and-set. EventStore::claim_group_task opens BEGIN IMMEDIATE, re-reads the projection, verifies Pending with complete dependencies, appends GroupTaskClaimed, and commits — so any number of concurrent claimers produce exactly one owner. Release, start, complete, block, cancel, and reassignment use the same transactional pattern with the ownership check inside the transaction. Only the assignee may transition a task; only the root may create, cancel, or reassign one, and only to a group member. Completing a group task is coordination truth, never root evidence: the child evidence ledger and root certification remain untouched.

Membership is explicit and durable (AgentGroupMemberJoined); children of the root join when they are delegated a task or first participate. Messages are compact text and information-only: no transcript copying and no automatic context merging. GroupMessageQueued is durable in the root log; delivery happens only at a recipient's safe model boundary, where GroupMessageDelivered is appended to that recipient's own session in the same transaction as its delivery marker. FIFO per recipient, exactly-once across restarts, and sending never wakes an idle or completed child — an explicit continue_agent is still required for new work.

The kernel gates terminal root complete: while the active group has required tasks that are not Completed or Cancelled, the completion tool returns a concise denial and canonical completion does not become terminal. Optional and cancelled tasks never block. If a child is interrupted, its claimed task stays assigned; only an explicit release, completion, reassignment, or cancellation changes ownership. Groups remain coordinated concurrency, not a swarm: there is no autonomous scheduler, no automatic claiming, no recursive spawning, and depth stays one. The workspace stays shared; overlapping expected_paths/touched_files on concurrently active tasks produces an advisory conflict warning only, never a hard edit block.

The model-facing surface is exactly three fixed tools: group_task (create, list, claim, start, complete, block, release, cancel), group_message (send, list), and group_status (one compact snapshot). spawn_agent gained an optional task_id, so the root can delegate a ready task in one atomic step without a new spawn primitive.

Edit this page on GitHub ↗Source: docs/ARCHITECTURE.md

Type to search. Results stay in your browser.