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.