How AI Agents WorkCourse map

Chapter 7 · Capabilities built on the loop

Subagents

Handing part of a task to a second agent loop keeps the main context clean and can save time. But some information gets lost on the way, and the extra loop costs tokens.

A subagent is another loop

Suppose Patch needs every place in the code that checks whether a login token has expired. Finding them means searching and reading about thirty files, but the answer is three lines. If Patch searches itself, all thirty files land in its own context. In a simple loop they stay there until something compacts them (chapter 4).

Instead, Patch can call a tool named delegate with a short request. Behind that tool, your code starts a second agent loop. In the simplest design, that loop gets its own instructions, its own tools, and an empty history. When it stops, your code returns its final message to Patch as the tool result.

Main agent
    |
    | delegate("find every expiry check")
    v
Second agent loop      own instructions, own tools, empty history
    |   searches, reads, repeats
    | result: three file:line references
    v
Main agent             sees only the result

For the main agent, called the parent, this is an ordinary tool call. Only the inside of the tool is new: it runs a whole agent loop, called the child, instead of a function.

def delegate(call):                          # a tool, like read_file
    child = Agent(
        system=EXPLORER_PROMPT,              # its own instructions
        tools=[search_files, read_file],     # its own tools
    )
    report = child.run(call.args["objective"], max_steps=15)  # a whole loop
    return tool_result(call.id, report)      # the parent sees only this

What a subagent can change

A research agent might start one child per source, each with the same instructions and tools as the parent and a different brief. A coding agent might start a reviewer with its own prompt, read-only tools, and a cheaper model.

So "subagent" names a set of choices, and only the separate loop is fixed.

What a subagent can change
ChoiceOptionsWhy change it
InstructionsThe parent's, or a prompt for one jobFocus on that job
ToolsThe same, fewer, or differentA reviewer that cannot write
ModelThe same, or a cheaper oneCost and speed for simple searches
Starting contextOnly the brief, or a copy of the parent's conversationA clean start, or a cheap one
StateIts own, or shared files and dataPass big results by reference
BudgetSteps, tokens, timeCap what one delegation can cost
LifetimeThe parent waits, or it runs in the backgroundLong tasks and parallel work

The delegation contract

Suppose the parent writes the brief "look into the auth bug". If the child starts with no history, it does not know which bug, which files the parent already read, or what answer is wanted. So it will probably spend its budget rediscovering what the parent knew, then return a vague report.

A useful brief works like a contract between the two loops. It covers eight things:

brief = {
    "objective":   "List every place that checks token expiry. Do not fix anything.",
    "constraints": ["skip tests/fixtures", "all datetimes are timezone-aware"],
    "tools":       ["search_files", "read_file"],       # what it may do
    "output":      "path:line plus one sentence each, at most 900 tokens",
    "budget":      {"max_steps": 15, "max_tokens": 60_000, "timeout_s": 300},
    "owns":        ["notes/expiry-sites.md"],           # the only file it may write
    "cancel":      "the parent can stop it; notes written so far stay",
    "reconcile":   "the parent re-reads each line before editing it",
}

Some of these fields are only requests, and some can be guarantees. The objective and the output format are text, so the child may drift from them. But your code starts the child, so it can enforce the tools, the budget, and the files the child may write. For example, "do not edit files" is a request, while read-only tools make editing impossible.

In practice, the parent model writes the objective and the facts it knows. Your code fills in the tools, the budget, and the owned files from a fixed template, so the model cannot loosen them.

Call and return, or hand off

A support agent receives "I was charged twice." It could call a billing subagent, wait for its findings, and answer the customer itself. Or it could hand the whole conversation to a billing agent, which then talks to the customer directly.

The first pattern uses an agent as a tool: the parent calls it, waits for the result, and stays in charge. The second is a handoff: the first agent passes control to another agent and steps out.

Agent as a tool                      Handoff

Parent --delegate--> Child          Support --hand off--> Billing
Parent <--result---- Child                                 |
Parent answers the user                                 v
                                      Billing answers the user

Use call and return when the parent has to combine results or keep one voice toward the user. Use a handoff to route a conversation to a specialist. A handoff usually moves the conversation itself to the new agent, while a called child usually starts with only its brief.

Context isolation, and its limits

In chapter 4, Patch's explorer read 31,000 tokens of code and returned a 900-token report. The parent's context grew by 900 tokens, not 31,000. That is context isolation: the child's reading stays in the child's context.

But isolation only covers what each model sees, not what each agent can change. People often blur four different arrangements.

What parent and child share
ArrangementWhat is sharedGood forWatch out for
Shared filesA folder or repoPassing big results by reference: write notes, return the pathTwo children editing one file
Shared dataOne state object in your code, such as a todo listResults that flow back without entering the parent's contextParallel writes need merge rules
Shared conversationA copy of the parent's message historyA cheap start for the childNo isolation: the child inherits the clutter
Nothing sharedBrief in, report out; its own worktreeRisky or fully separate workEvery fact must travel in the brief or the report

If children write files, give each writer its own checkout or git worktree, so their edits cannot collide. A worktree is not an access limit, though, because an unrestricted process can still reach the others. To really block access, check paths in your tool code, or use mounts and OS permissions (chapter 10).

Specialization

Say a reviewer subagent's prompt says "you are a careful security reviewer", and it has no tool that can write. Only the missing tools are a guarantee. The prompt shapes what it tends to do, but the tools decide what it can do.

The cost is that a specialist knows less. For example, a reviewer that sees only the diff cannot tell whether the change matches the plan. Put what it needs in the brief.

Running children at the same time

Suppose three children take 2, 3, and 2.5 minutes. If the parent asks for all three in one reply, and nothing slows them down, they finish after 3 minutes. That is the time of the slowest one. One after another, they would take 7.5 minutes.

This saves time, but it does not save tokens. The extra tokens come from four places:

The time saving has limits too, because provider rate limits can make the children wait for each other.

Combining the results

In the simulator below, a child researching Redis reads a config file. It shows that the team's Redis server deletes old data when memory runs low. The child's short summary leaves that out. So the parent recommends Redis for a job queue, where losing jobs is a real problem.

This step, combining what the children send back, is called aggregation. Each result is a claim written by another model, not proof. Summaries drop details, and by the time the parent reads one, the child is usually gone. Results can conflict, and then the parent needs evidence, such as the original document or a test. Reports also go stale: a child says "the test passes", then another child changes a file the test depends on.

So design what comes back:

Returning full transcripts instead would lose nothing. But the parent's context would fill up with everything every child read, which undoes the isolation you delegated for.

Try it: the subagent simulator

Patch's team needs a job queue for background work. The parent asks three children to research one option each: Redis Streams, RabbitMQ, and Amazon SQS. Try each scenario, then change what comes back and whether the children run at the same time.

Interactive widget. Without JavaScript, here is the clean run in words. The parent sends one queue to each of three children, and each sends back a short report. Running at the same time, they finish in 3 minutes instead of 7.5. Together they use about 141,000 tokens, while one careful agent would use about 124,000.

When two children edit one file, each does what its brief says. The conflict comes from how the work was split.

Children that start children

Suppose every agent may start three children, and each of those may start three more. Three levels then give you 3 + 9 + 27 = 39 agent runs. Each level also passes along a summary of a summary, so details fade.

Most designs cap it with a maximum depth, a maximum number of children, and one budget shared by the whole tree. Hermes and Deep Agents both keep depth at one level by default, because their children get no tool for starting more children.

def delegate(call, depth, budget):
    if depth >= MAX_DEPTH:
        return error(call.id, "delegation depth limit reached")
    share = budget.take(steps=15, tokens=60_000)    # the whole tree shares one budget
    tools = CHILD_TOOLS if depth + 1 < MAX_DEPTH else CHILD_TOOLS - {"delegate"}
    report = run_child(call.args, tools, share, depth + 1)
    budget.give_back(share.unused())
    return tool_result(call.id, report)

When multiple agents help

Four problems justify a subagent most often:

Anthropic reports one result from its research system. A Claude Opus 4 lead with Claude Sonnet 4 subagents outperformed a single Claude Opus 4 agent by 90.2% on its internal research eval. The same post says multi-agent systems use "about 15× more tokens than chats", and that "most coding tasks involve fewer truly parallelizable tasks than research".

A complex task is not, by itself, a reason. It often needs one agent with a better context, not several agents that each see only part of it.

When they cost more than they give

Skip them in these cases:

Pi takes the skeptical side on purpose. It has no built-in subagent tool, though its repository ships an example extension that adds one. Its creator, Mario Zechner, calls parallel subagents building separate features "an anti-pattern in my book".

So start with one agent. When you add a subagent, measure whether it helped (chapter 16). Then check that the gain came from the extra agents (chapter 18).

Running example: Patch gets two helpers

Patch version 7 gets two subagents, both called like any other tool. The explorer searches the code and returns file:line references. The reviewer can only read, and its brief carries the diff and the test results. Patch still makes every edit itself, because edits to the auth code depend on each other.

# Patch v7: two subagents, called like any other tool
+ explorer = Subagent(prompt=EXPLORE, tools=[search_files, read_file],
+                     output="at most 900 tokens, path:line refs", max_steps=15)
+ reviewer = Subagent(prompt=REVIEW, tools=[read_file],
+                     output="findings with path:line, no edits", max_steps=8)
+ tools += [delegate(explorer), delegate(reviewer)]

What goes wrong

The summary dropped what mattered

Why it happens
The child chooses what to report under a size limit, and a free-form summary keeps the headline but drops the warning.
How to spot it
The parent acts on a claim that has no reference, and later the child's notes show the missing fact.
What to do
Ask for risks as their own field, with references, and keep full notes in a file the parent can read.

Two children edit the same file

Why it happens
Each child follows its own brief and does not know the other exists, so the last write wins.
How to spot it
Two children's change lists touch the same file, or the tests pass for each child and fail after merging.
What to do
Give each writer its own worktree, or do linked edits in one agent. Where a write must be blocked, check paths in your tool code.

Children disagree

Why it happens
They read different sources or misread the same one, and a wrong claim can sound as sure as a right one.
How to spot it
Compare the same field across reports, and flag contradictions before merging.
What to do
Settle it with evidence, such as the original source or a test. Chapter 15 goes deeper.

You decide, AI builds

Decide yourself

  • Whether a task needs a subagent at all.
  • Each subagent's tools, budget, output format, and writable files.
  • What parent and child share: files, data, the conversation, or nothing.
  • How the parent checks results before acting on them.

Delegate to AI

  • The delegate tool and the code that runs child loops.
  • Checking results against an output format, with one retry.
  • Counting tokens and steps across the whole tree.
  • Saving and linking each child's transcript.

Check yourself

What is a subagent, mechanically? (Q12)

Answer

A tool whose code runs another agent loop, with its own context and usually its own instructions, tools, and budget.

When should you avoid splitting work across several agents? (Q13, Q14)

  1. When the subtasks are independent research questions
  2. When two parts of the work edit the same files
  3. When the search would flood the main context
Answer

When the parts are linked. Separate contexts make separate choices, and the last write wins. The other two are good reasons to use subagents.

Three children take 4, 6, and 9 minutes, and nothing slows them down. How long do they take at the same time, and one after another?

Answer

9 minutes at the same time, because the parent waits for the slowest child, and 19 minutes one after another. The parent's own calls come on top.

Takeaways

Going deeper