Chapter 5, second edition working draft

Coordination

How agents divide work and combine their results.

Contents

An agent loop can keep taking actions, but each model call still has a limited context window. Instructions, source passages, tool results, and earlier decisions all occupy space in that input. As the work grows, the application must select or summarize what the next call receives. Memory preserves material for later retrieval, but each call still receives only what fits in its context. These techniques can keep one loop effective, but some parts of a task need extensive investigation whose intermediate details matter little to the rest of the work.

A product comparison, for example, may need to establish whether one product has actually shipped. Resolving that question could require many searches and conflicting documents. The comparison needs the finding, its evidence, and any remaining uncertainty. A separate agent can conduct the investigation in its own context and return those results, keeping the intermediate work out of the parent's input. The first design question is which parts of a task allow this separation: what information does each part need, and what must it return for the larger task to continue? Coordination concerns how we divide that work and bring its results together.

The Subagent Pattern

A subagent is an agent run created for a specific assignment from another agent. The parent supplies the assignment, and the application starts a child with its own context and tools. The child works through its own tool-calling loop, returns a result or a reason it stopped, then ends its run. A saved record or file can outlive that run; a new operating-system process is not required to create a subagent.

A parent delegates a release-evidence question through the runtime to a child with its own task, context, and tools. The child loop returns findings, sources, and unresolved questions to the parent, then ends. Saved evidence remains outside the child run boundary.
The parent delegates an assignment and receives the child's selected findings as an observation. The child run ends; its result and saved evidence can remain.

Delegation fits directly into the agent loop from the previous chapter. The parent requests a tool such as delegate, and the tool's implementation runs the child loop. The child's result becomes an observation in the parent's next context. The example below uses application interfaces. createChild constructs the child's context and execution limits from the assignment, the current parent run, and the configured tools and workspace. runAgent executes that bounded loop and returns a candidate result or a stopped status.

// parentRun and investigationConfig come from the application.
async function delegate(request, parentRun) {
  const child = await runtime.createChild({
    parentRun,
    configuration: investigationConfig,
    assignment: request.assignment,
    sourceIds: request.sourceIds,
  })

  return runAgent(child)
}

// The parent dispatcher handles a validated delegation request:
const result = await delegate(call.arguments, parentRun)
trace.push({ call, result })
// The parent's next context includes the child's returned outcome.

Task decomposition

A useful boundary separates work that needs substantial local detail but has a clear result for the larger task. “Establish product B's release status, with sources and unresolved questions” gives the child a result to pursue. The assignment must also supply product identifiers, relevant constraints, and what counts as “released.” A role name such as “researcher” leaves those requirements unspecified. If every step requires the parent's latest conclusions, or the parent must replay the whole investigation to use the answer, keeping the work in one loop may be simpler. Delegation earns its cost when a focused assignment and usable return save more context or time than the handoffs consume.

For each assignment, we need to decide when the subagent runs and what information it receives. A reviewer can start after an investigation finishes, yet still lack the evidence needed to review it. Copying the entire investigation history preserves more material but may bury the claims under search attempts. Selecting claims, supporting passages, and uncertainties gives the reviewer a focused input. The order of execution and the information passed between agents both affect whether the reviewer can do its job.

A sequential schedule appears above a data transfer that extracts evidence from one context into another worker’s focused context.
Execution flow determines when reasoning structures run. Data flow determines what each receives from the others.

Model-directed delegation

An orchestrator is an agent that manages assignments and combines their results. Its model can decide whether a task benefits from a separate investigation, formulate the question, and request another investigation after reading a result. A source conflict might lead to a narrowly scoped follow-up; sufficient evidence might lead directly to writing. As with the agent loop, the runtime supplies the repeated structure while model decisions determine the path through it. The full collection of subtasks need not be known before work starts.

The application sets up the child's environment: the source material, tools, and workspace it can use, along with limits on time or number of steps. These choices determine what the child can inspect and do. Separate contexts do not isolate shared files, so the application must also decide whether workers share a workspace or write separate outputs.

A known procedure can fix some of the decomposition. A comparison service may always investigate two source collections and require a review before accepting the synthesis. Within those stages, a model can choose narrower questions or additional searches. This combines predictable requirements with adaptable investigation. Further delegation can repeat the subagent pattern inside a child run, provided the runtime carries the scope and limits through to its descendants.

A proposed question, source scope, and expected result reach the application. It constructs a child run with context, tools, workspace, and execution limits. The child returns a candidate result or stopped status through the application to the next parent decision.
The model proposes work. The application constructs the child’s context, tools, workspace, and execution limits, then returns the outcome to the parent.

Parallel execution

Dependencies determine which assignments can usefully run together. An investigation of company filings and an investigation of product documentation may start independently. Their synthesis needs both findings, and a review of the synthesis needs the draft. That task therefore has parallel investigations followed by dependent stages. If one investigation discovers information the other requires, the orchestrator must pass that information on or revise the assignments. Parallel execution is useful when the work is sufficiently independent and combining it is inexpensive.

A join collects the outcomes of separate runs before deciding how to continue. In TypeScript, Promise.allSettled waits for each run to return or throw an error. A fulfilled promise can still contain a child that stopped early, so the code preserves the child's status. The illustrative assessCoverage check compares the returned evidence and unresolved questions with the information needed for synthesis.

const settled = await Promise.allSettled(
  assignments.map(request => delegate(request, parentRun)),
)

const outcomes = settled.map((entry, i) => ({
  assignmentId: assignments[i].id,
  result: entry.status === "fulfilled"
    ? entry.value
    : { status: "run_error", reason: "No child result returned" },
}))

const coverage = await assessCoverage({ goal, outcomes })
if (!coverage.sufficient) {
  return { status: "needs_followup", outcomes, coverage }
}

return {
  status: "candidate",
  answer: await synthesize({ goal, outcomes }),
}

The first delegation example waits for a child before the parent continues. An asynchronous interface can instead return a run identifier, allowing the parent to do other work and collect the result later. Waiting for all required investigations, taking the first adequate answer, and processing findings as they arrive are different continuation rules. The rule follows what the next stage needs. An unavailable source remains missing coverage; a faster result does not make that gap disappear.

A lead assigns filings and documentation to separate workers, receives evidence from one and an unavailable result from the other, and alone writes the briefing.
A join collects status as well as evidence. One failed branch must remain visible to the lead that owns the final artifact.

Results, verification, and recombination

A returned result needs enough detail for the parent's next decision. “Research complete” reports a status without providing the findings. A useful release-status result identifies the product, separates an announcement from evidence of availability, cites the supporting passages, and preserves unresolved questions. The parent can then compare findings, inspect a source, or commission another bounded investigation. Finishing a child run establishes that execution ended; the result still needs to satisfy its assignment.

Combining results requires interpreting them. Two workers may have examined different dates or used different meanings of “released.” The parent must resolve those differences before combining their claims. Code can check for missing fields or assignments that returned no result. Judging whether the evidence supports a conclusion may need another model call or a person's review. When the evidence is insufficient, the next step is a more precise assignment or an explicit statement of the gap. Joining two reports into one document does not resolve their disagreement.

The result can travel as text, a structured summary, or a reference to saved work. Full history carries more detail at a higher context cost. A summary selects meaning and can lose a qualification. A file or document reference keeps the return small, but the receiver must be able to fetch the relevant version. The representation should follow what the next decision needs. Source references and remaining uncertainty help the parent recover detail without loading every step the child took.

Three aligned representations of one research handoff contrast full history, a summary with evidence and uncertainty, and a versioned reference that needs a lookup.
Full history, a structured summary, and a reference preserve different things. A reference is useful only if the receiver can resolve it.

Shared workspaces

Subagents can leave work in an environment that survives their runs. An investigator might write research/product-b.md and return its path with a short account of the findings. The parent reads the note when it needs the evidence. Each worker can focus on its assignment while files or database records provide a common place for results. The workers need no direct conversation with each other when the parent and shared workspace supply the necessary connections.

A message can announce that a document changed while the document holds the actual work. If an investigator reports that revision 13 contains a new source, a reviewer can read that revision before continuing. This separates notification from evidence: the message directs attention, and the read supplies the material for the next decision. Shared state can therefore support coordination alongside returned messages.

Shared access still needs ownership. Two subagents can have separate contexts while editing the same file and overwriting each other's changes. Separate output files, a single parent that integrates proposals, or version-checked updates can control that interference. The environment's operations determine which changes can safely coexist. The next chapter develops these artifacts and operations as parts of the system in their own right.

A worker commits a source to a briefing, emits a versioned notification, and a reviewer reads the committed record rather than treating the message as the source of truth.
Notifications and artifacts can cooperate. The stored version remains the reference for the work, and updates still need a conflict policy.

The subagent pattern lets a model turn a broad task into bounded assignments, inspect their outcomes, and adapt the remaining work. Context limits explain why information needs to be distributed; dependencies explain when results must come together. The runtime makes those boundaries executable while the model decides how to use them. The work can outlive any particular run through the artifacts those runs produce.