Skip to main content

19 · Orchestration in production

Multi-agent systems

Splitting work among several agents, checking each other's results, and when one agent is the better answer.

12 minCase study: docket (opens in new window) · Tack (opens in new window)

Picture a single with every tool and the task "implement this, review it and make sure the tests pass". Four problems show up. The agent that wrote the code decides whether the code is good, like students grading their own exams. By review time its memory of the task is cluttered with failed . It keeps full write access even while "reviewing". And when the result is bad, nobody can tell whether the planning, the building or the checking failed.

A splits that work across several agents, each with its own role, instructions, tools and often model. Done well, it fixes all four problems; done badly, it multiplies cost without improving anything. This lesson covers how to split work into roles, why role limits must be built into the system rather than written in instructions, how to check work with gates the model cannot argue with, and when one agent is the better choice.

Splitting by role

A team of agents needs two decisions: which roles exist, and how work passes between them. Each pass from one agent to the next is a . The diagram shows the common arrangements: a pipeline, where each agent passes to the next and a reviewer may send work back; a lead that hands out work; and agents running in parallel whose results are combined.

  • Pipelineeach agent passes to the next
    • A, then B, then C
    • A reviewer may send work back
  • Lead and workersone agent hands out the work
    • The lead picks who does what
    • Workers report back to it
  • Parallelseveral agents at once
    • One task split into pieces
    • Results combined at the end
Three ways to connect a team of agents. They differ in who decides the next step and in what can happen at the same time.

A pipeline is easy to follow and to resume after a crash. A lead that decides on the fly is flexible, but harder to test and to cap in cost. Parallel agents save time only when their tasks are truly independent, for example when they do not edit the same files.

For coding work, the classic roles look like this. The last column matters most:

Role Does Should not be able to
Lead plans and hands out work edit code
Implementer writes the change approve its own work
Reviewer reads the change, asks for fixes write or run anything
Tester runs the tests, reports pass or fail edit files

Limits built in, not written down

Telling the Reviewer "you are read-only" does not make it read-only. The model is the thing you are trying to control; it cannot also be the control. The reliable way is to never give the role the tool at all: if the Reviewer has no writing tool, no text can talk it into writing.

Written ban Built-in ban
instruction: "do not write files" the writing tool is not in its list
the model sees the tool the model never sees it
persuasive text can talk it round there is nothing to talk round
a violation can go unnoticed an attempt shows up in the log as an unknown tool

Handoffs deserve the same care. Pasting one agent's whole output into the next one's instructions grows without end and mixes noise with signal. docket passes a short structured summary instead, with a size (see Context, routing and cost), and takes the list of changed files from git rather than from the model (DOCKET Architecture). If a fact can be read from the real world, don't ask the model for it.

Gates the model cannot argue with

The Implementer says "done, tests pass". How do you know? With a gate: a condition checked outside the model before work moves on. There are three useful kinds:

  • A command decides. After the change, the system runs the project's own check, such as its test suite. If it fails, the task fails, whatever the agent claimed.
  • A verdict in a strict format. The Reviewer must answer with an explicit approve or request-changes, the Tester with pass or fail. An answer the system cannot read clearly counts as a failure, never a success.
  • A person approves. An operator must say yes before the step goes ahead.

In docket

  1. Leadplans; never edits code
  2. Implementerwrites the change
    • Gate: the project's check command
  3. Reviewerreads the change, gives a verdict
    • Gate: approve or request changes
  4. Testerruns the tests, gives a verdict
    • Gate: pass or fail, no second try

"request changes" returns the task to the Implementer, once by default

A full pod's pipeline. Each step after the Lead has a gate checked outside the model, and only the Reviewer can send work back. Source: Agent Teams (Pods)

That limit matters: without a ceiling, a demanding Reviewer and an unable Implementer go around, and spend, forever. And where a command can decide, let it; save model-based checking for what no command can check.

This is what independent verification means: the checker did not produce the work, does not share its context and does not hold its tools. A Reviewer that can write tends to "fix" things instead of asking for changes, and then nobody reviews what it wrote. It also reads the change, which may contain hostile text, and what that text can achieve depends entirely on the tools the Reviewer holds.

When one agent is better

Every extra agent adds model calls, waiting time, a handoff that loses some information, and one more thing that can fail. "It sounds more advanced" is not a reason.

Benefit Cost
independent review more calls, more waiting
each role gets only the access it needs badly designed roles block legitimate work
focused context information lost at every handoff
failures are easier to locate more states and more coordination code
checks the model cannot skip small models often get the verdict format wrong

docket's README points the same way: begin with just a Lead and an Implementer, and bring in a Reviewer or Tester only when there is a particular check you need them for.

Another boundary: the task itself

That is another valid way to divide the work: the board decides what work exists and in what order, and the agent decides how it gets done.

In Tack

  1. Board itemwhat to do, and in what order
  2. Run with agentthe item crosses the line
  3. Coding agentdecides how, its helpers included
  4. Record on the itemthe attempt, its events, its results
Tack never looks inside the agent's work. It hands over a whole task and keeps what came back on the item. Source: Agent Runners & Fleet Execution

Putting it into practice

  • Require a concrete reason for every extra role: a check that fails today, or access that is too broad today.
  • Put role limits in the system, not in the instructions. Check which tools each role can actually reach.
  • Prefer a command over a model's opinion as the gate, wherever a command can decide.
  • Decide where the line sits: coordinating roles inside your own system, or handing whole tasks to an outside agent you observe from the edge.

Go deeper

The docket and Tack documentation go further into both ways of dividing the work:

  • Agent Teams (Pods) is docket's central guide: the roles and what each may edit, how the pipeline runs one real agent turn per step, and the gates between steps.
  • Workflow guide follows a pod from setup to a committed change, and shows custom pipelines with parallel steps, bounded rework and a person's sign-off.
  • Agent Runners & Fleet Execution explains how Tack hands an item to a coding agent, what each supported agent can and cannot promise, and what runs end to end today.

Key takeaways

  • Splitting work into roles addresses self-grading, cluttered context and excess access, at a price in cost and coordination.
  • A role's limits are enforced by removing tools, not by instructions the model may ignore.
  • Handoffs should be short structured summaries, filled from real data where possible.
  • Gates checked outside the model, with unclear answers counted as failures, make bad work visible.
  • Start with the smallest system and add roles only when a measured need calls for them.

Check yourself

Why is removing the writing tool from the Reviewer stronger than forbidding writing in its instructions?

The model never sees the tool, so no text can persuade it to use it, and any attempt shows up as an unknown tool. An instruction only works if the model chooses to obey it.

A Reviewer's reply contains both "approve" and "request changes". What should the system do, and why?

Treat it as unreadable and block progress, just like a rejection. Counting an unclear answer as success would let bad work through whenever the model is confused.

When is a single agent the better choice?

When no concrete check or access boundary justifies another role, or when the subtasks share a lot of context and depend on each other. Then more agents add cost and lossy handoffs without improving the result.