C1 · lesson 4 · 9 min read
Handoffs and failure isolation
Write briefs a fresh subagent can act on, get structured reports back, and keep one worker's failure from sinking the whole run.
Հայերեն
A handoff is the moment work moves from one agent to another: orchestrator to worker, and back again with a report. Most multi-agent failures happen here, not inside the agents. A worker that gets a vague brief does vague work, and an orchestrator that gets an unstructured essay back has to guess.
The brief is all the worker knows
A non-fork subagent starts with its own system prompt, the project CLAUDE.md (if
it’s loaded), its tool definitions and the Agent tool’s prompt string. That’s
all. It doesn’t receive the parent’s conversation, its earlier tool results or its
system prompt. If the orchestrator spent ten turns finding that the 502s started
right after deploy a1b2c3, the worker doesn’t know that unless the brief says so.
A good brief contains:
- Goal. One sentence: “Find why checkout pods fail readiness after 14:10 UTC.”
- Known facts. Paths, IDs, timestamps and error strings, copied exactly.
- Scope and limits. Which namespaces or directories to look at, and what not to touch.
- Already ruled out. So the worker doesn’t repeat the parent’s work.
- Report format. What shape the answer must take.
Structured reports back
The parent receives the worker’s final message only, and may summarise it again. Ask for a fixed shape so the orchestrator can merge reports by machine rather than by vibes:
status: done | partial | blocked
findings:
- claim: readiness probe path changed from /healthz to /ready
evidence: k8s/checkout/deploy.yaml:42
next_step: confirm /ready exists in image tag 3.8.1
status matters most. A worker that says blocked: plan.txt not found is useful.
A worker that fills the gap with plausible guesses is dangerous, and in a fan-out
of five workers you won’t notice which one guessed.
Isolating failure
Context isolation is also failure isolation. A worker that goes down a rabbit hole burns its own context, not the orchestrator’s. Design for that:
| Failure | What happens / what to do |
|---|---|
| A tool errors inside the worker | It gets an is_error result in its own loop and can retry or report it. The parent sees only the final report |
| The worker runs out of turns | With maxTurns set, Claude Code marks the output as partial, so the parent knows the work is unfinished. You can resume it |
| An API error (for example a rate limit) ends it early | It is never delivered as the worker’s result, so the parent won’t mistake an error for findings |
| The worker needs more than its tools allow | It works without them, or reports blocked. Don’t “fix” this by giving every worker every tool |
| The whole tree overspends | max_budget_usd stops new spawns and ends the query with error_max_budget_usd |
The orchestrator should then make an explicit decision for each report: merge it, retry with a sharper brief, resume the worker, or escalate to a human. Retrying the same brief blindly usually gives the same failure.
Resuming instead of restarting
When a custom subagent finishes, the Agent tool result contains agentId: <id>.
To continue its work with its full history, resume the same session: pass
resume=<session_id> in a new query(), pass the same agents definitions, and
mention the agent ID in the prompt. The built-in Explore and Plan agents are
one-shot and don’t return an agentId, so use a custom agent or general-purpose
when you expect to resume.
Recap
- The worker knows only its own prompt,
CLAUDE.md, its tools and your brief. Put the goal, facts, scope, what’s been ruled out and the report format in the brief. - Ask for structured reports with an explicit
status, and treat them as data. - Context isolation contains failures. Partial output is marked, and API errors are never passed off as results.
- Resume a custom worker with its
agentIdin the same session instead of starting over.
$ ./try-it.sh
Try it: a worker that reports when it is blocked
- Add a
tf-plan-readerworker withtools=["Read", "Grep"],maxTurns=4, and the report format from this lesson in itsprompt. - Hand it a brief that names a plan file that doesn't exist. Check that it returns
status: blockedwith the missing path as evidence, and doesn't invent findings. - Hand it a real
terraform show -no-color plan.out > plan.txtoutput and check that every finding has afile:lineor resource address. - Capture
session_idfrom the result and theagentId:line from the Agent tool result. Then run a secondquery()withresume=session_idand ask it to resume that agent and list only the destroy actions.
Check yourself
5 questions. Original practice questions, not taken from the real exam.