A delegation framework for AI coding agents: a set of agent definitions that turn one AI assistant into a small, disciplined team with a strict chain of responsibility. Built to run as subagents under OpenCode, but the patterns (tiers, loop, reports, recovery) are portable to any agent system that supports spawning child sessions.
The design priorities, in order: nothing gets read or rewritten silently, no work is lost when a session dies mid-flight, raw detail never floods the conversation, and a human is always the final authority.
Instead of one agent doing everything in one long session, agent-loop splits the work into specialized tiers. Each tier has exactly one job, a strict scope of files it may touch, and a duty to report what it did. Parent tiers spawn child tiers; children never spawn further children (except the two dispatching tiers listed below).
| Tier | Role | Spawned by |
|---|---|---|
| manager | Owns the conversation with the human operator: receives a task, dispatches exactly one orchestrator for it, relays results back, approves commits. Never edits code itself. | the human operator |
| orchestrator | Owns one task end-to-end: dispatches gather for research, chunks the work, dispatches one implement child per chunk, verifies independently, closes the report. | manager |
| gather | Read-only research: charts the surface before anything changes, validates every assumption against the actual code, returns findings with file:line evidence. Never edits. |
orchestrator |
| implement | The only code-writing tier: executes exactly one small, self-contained chunk, re-checks the directive's assumptions before the first edit, then builds and tests. | orchestrator |
| poller | Watches long-running jobs (builds, tests, deploys) by polling on a schedule instead of blocking; detects stalls and hangs and reports them upward. | orchestrator |
| document-master | Sole writer of the durable documentation: distills finished reports into the canon, keeps summaries faithful, keeps pointers terse. | manager |
The gather, implement, poller, and document-master tiers are leaves: they do the work, report, and stop. They never spawn delegates of their own.
Every task runs the same five steps:
- Gather — the orchestrator dispatches a gather delegate, which reads only the code the task
touches, verifies every assumption in the brief against what is actually on disk, and returns
findings with
file:lineevidence. Any mismatch is named, not silently reconciled. - Plan — the orchestrator reads the gather output and splits the work into small, self-contained chunks, each with its own directive: the goal, the authorized files, and the assumptions the implement child must re-verify. One chunk is small enough to finish in one session without guessing.
- Implement — one implement delegate per chunk. Before its first edit it checks the directive's assumptions against the real code; then it makes minimal, targeted edits and appends its own report section as it goes, so the record survives even if the session dies.
- Verify — the implement tier runs the package's build and tests and, for UI/service changes, checks the rebuilt or redeployed artifact — a green compile alone is never accepted as proof. The exact pass/fail line is captured verbatim. The orchestrator then verifies independently; the implement tier is the sole executor, so its recorded output is the only verification record.
- Report — one shared report file per task. Each tier appends its section in order (below), and a one-line digest climbs to the manager while the raw detail stays on disk.
Work is delivered as STATUS: COMPLETE or STATUS: PARTIAL with the remainder — a delegate that cannot finish everything says exactly what is left, rather than handing up half-information.
One shared report file per task lives in <WORKSPACE>/reports/, named
{unix_timestamp}-{report_title}.md. Sections are owned by tier and appended in order:
- Header — dispatch title, goal, problem.
- DIRECTIVE (orchestrator) — the dispatch title verbatim plus the assumptions the brief carries.
- GATHER (orchestrator, after research) — per-assumption CONFIRMED or DEVIATED, with
file:line. - IMPLEMENT (each implement child appends its own) — what, why, how, files touched, dead code purged, the build/test command run and its pass/fail line.
- ORCHESTRATOR NOTES — what completed, deviations and judgment calls, independent verification verdict, commit-readiness.
- LOG POINTERS (long jobs only) — the logfile path plus the specific lines carrying the outcome. The log body itself is never inlined.
Raw detail — file bodies, diffs, build logs — stops at the tier that produced it. What climbs
is the hand-up block: one line per report in the orchestrator's return to the manager, shaped
[absolute path] — digest (notable details / deviations / assumptions verified). The manager
relays that line verbatim to the human, and the document-master later consumes the full files from
disk. Big writes into reports are always chunked, never one monolithic write.
A delegate that stalls — empty return, aborted stream, wedged session — is resumed, never respawned. Respawning starts a fresh session that discards the delegate's preserved work and re-does what it already finished.
Recovery has three steps:
- Find the session id. Look it up in the session database under
<OPENCODE_DATA>(the delegate's session was auto-titled from its dispatch title, which is the recovery key). If you already hold the id, skip this. - Resume the same delegate. Dispatch again with the same task id and a status query: what is done, what remains, continue the rest.
- Verify identity. The returned task id must equal the id you passed. A mismatch means a fresh session was spawned silently — that counts as a failed resume attempt.
The same stalled delegate is force-resumed up to 10 attempts. After the 10th failure: stop all work and escalate to the human operator.
The loop is built to stop and ask rather than improvise. A delegate escalates and halts when:
- a directive's assumption contradicts the code on disk (missing file, mismatched signature, unexpected test failure), or a change is needed outside its authorized file scope;
- work would require touching files or decisions it was not granted;
- anything would re-open a decision the operator has locked;
- the 10th resume attempt of a stalled delegate fails.
Only the human operator approves commits, expands scope, or re-opens locked decisions. Every other conflict resolves into a questions report, not a guess.
The sanitized files in this repo use three path placeholders. Substitute your own values:
| Placeholder | Meaning |
|---|---|
<WORKSPACE> |
Your project workspace root — where your repos, reports, and orchestration docs live. |
<OPENCODE_CONFIG> |
Your opencode config directory — where opencode.json and agent definitions go. |
<OPENCODE_DATA> |
Your opencode data directory — the session database lives here. |
Agent frontmatter also carries three model placeholders: <PRIMARY_MODEL> (used by manager,
orchestrator, and document-master), <SUBAGENT_MODEL> (used by gather and poller), and
<IMPLEMENT_MODEL> (used by implement). Point each at whatever model routes you want for that role
— heavier models for dispatching and documentation, lighter/faster ones for research and polling is
the default shape.
The live system names its standing rules with opaque IDs. In this public copy every ID has been replaced by a plain phrase, used identically everywhere that rule appears. This table is the mapping; it is the only place in this repo where the original IDs appear.
| Original ID | Phrase used in the files | What it means |
|---|---|---|
| R-08 | consult the reports archive first | Search past reports before re-investigating anything; push detail into reports and keep pointers terse. |
| R-19 | regenerate generated files, never hand-edit | Rebuild generated artifacts (e.g. protobuf output) with the official toolchain; never edit them by hand. |
| R-23 | chart the surface before changing it | Map the code you are about to touch — callers, dependencies, behavior — before editing it. |
| R-28 | delegation concurrency | Enforce the delegation limit for your setup: where tiers share one resident model on a single slot, only one delegate may be in flight ever. |
| R-29 | validate on-touch | Treat summaries as provisional: check claims against the code at the moment you act, and hand raw data up instead of judging it in place. |
| R-30 | return PARTIAL with the remainder | If you cannot finish everything, return what you completed and state exactly what remains. |
| R-31 | poll, never block | Watch long-running jobs on a polling schedule; never sit blocking a session on one job. |
| R-36 | accuracy over agreement | Prefer technical accuracy over agreement; disagree and verify when warranted. |
| R-43 | read durable docs fully | Read the canon and other durable documents in full before acting on them — no skimming. |
| R-46 | never deliver half-information | Deliver complete, verified findings, or explicitly mark every gap; never blur the two. |
| R-ABORT | stop and report the mismatch | When reality contradicts the directive, stop and return a deviation report — do not improvise. |
| R-DELIVERY-INTEGRITY | verbatim output, never compile-green | Verify on the rebuilt/redeployed artifact and record the verbatim pass/fail lines; a green compile alone proves nothing. |
| R-NO-SKIP | attempt every question | Attempt every assigned question; skipping silently is forbidden. |
| R-LONGEVITY / R-ONE-PATH / R-OVERHAUL | right long-term solution, one path | Ship the durable fix with a single code path — no legacy fallbacks, compat shims, or stubs. |
| R-NO-SCOPE-CREEP | edit only authorized files | Stay strictly inside the file scope the chunk directive grants. |
| R-DIAGNOSE-WITH-LOGS | diagnose with logs, then remove them | Instrument with prefixed diagnostic logs, reproduce, fix, then delete all of them and confirm zero remain. |
Unification notes:
- R-38 / R-39 — the source material is genuinely ambiguous: both IDs introduce one combined zone-discipline clause. Both IDs were dropped in this copy; the combined prose is kept ("stable zone exempt; volatile zone budget-capped").
- R-29 unifies three consistent uses: the manager treats summaries as provisional, gather checks claims on-touch, and the poller defers judgment upward ("hand raw data up; the manager decides"). The single phrase validate on-touch covers all three.
- R-08 unifies "search the reports archive before re-investigating" with "push detail into reports, keep pointers terse". The single phrase consult the reports archive first covers both.
- Copy the agent definitions. Copy the files from
agents/into<OPENCODE_CONFIG>/agent/(manager.md,orchestrator.md,gather.md,implement.md,poller.md,document-master.md). The names are unprefixed here; keep them or add your own prefix — either way, keep each delegate's session title derived from its dispatch title, since that title is the recovery key for the resume protocol. - Set your model routes. In each agent's frontmatter, replace
<PRIMARY_MODEL>,<SUBAGENT_MODEL>, and<IMPLEMENT_MODEL>with your own model IDs, and wire the corresponding providers/models into<OPENCODE_CONFIG>/opencode.json. - Set your provider API key via an environment variable and reference it from the config
(e.g.
"apiKey": "env:MY_PROVIDER_KEY") — never commit a raw key.
After that, talk to the manager tier: give it a task, and the loop takes over.
This is a sanitized public copy of a working production system. The operator's live system contains additional product-specific rules, documents, and configuration not included here.