Domain 1 — Agentic Architecture & Orchestration
stop_reason, coordinator/subagent topologies, explicit context passing, programmatic enforcement of critical orderings, hooks for deterministic guarantees, task decomposition strategies, and session state management. It is the largest domain (27%) because every other domain plugs into it: tools are only useful inside a loop, prompts only steer an agent that has somewhere to go, and context management only matters once an agent runs long enough to accumulate history. It is also the domain where the tempting answers are most often wrong — the exam repeatedly contrasts model-driven decision-making against pre-configured pipelines, and deterministic enforcement against prompt-based persuasion. Expect scenario-based items from the Customer Support Resolution Agent (Scenario 1), the Multi-Agent Research System (Scenario 3) and Developer Productivity (Scenario 4).Design and implement agentic loops for autonomous task execution
What you need to know
-
stop_reasonis the sole termination signal:"tool_use"iterates,"end_turn"exits. - Push back the whole assistant message, then all matching
tool_resultblocks in one user message. - Nothing is discarded between turns; the growing history is the reasoning substrate.
- Model-driven means Claude composes the sequence at runtime. A decision tree ships only your predictions.
- A tripped iteration cap is an incident to alert on, never a finished task.
Walk the four steps of the loop — send the request, inspect stop_reason, execute the requested tools, append their results — and show that the only transition signal is the structured stop_reason field: "tool_use" sends tool results back into conversation history before the next request, "end_turn" leaves the loop, and an iteration or time limit is the other exit.
Click a transition to highlight which stop_reason value produces it.
Worked examples
The canonical loop, written correctly
Scenario 1 · Customer Support Resolution AgentA support agent has get_customer, lookup_order, process_refund and escalate_to_human exposed as MCP tools. The loop below never inspects text and never counts iterations to decide completion — it branches on stop_reason alone, and it returns all tool results in one user message so parallel tool use keeps working.
typescript Model-driven agentic loop: stop_reason is the control flow
const messages: MessageParam[] = [{ role: 'user', content: userRequest }];
while (true) {
const response = await client.messages.create({
model: 'claude-opus-5',
max_tokens: 4096,
tools,
messages,
});
// Append the FULL assistant content — tool_use blocks must be preserved.
messages.push({ role: 'assistant', content: response.content });
if (response.stop_reason === 'end_turn') break; // the only normal exit
if (response.stop_reason === 'tool_use') {
const toolUses = response.content.filter((b) => b.type === 'tool_use');
const results = await Promise.all(
toolUses.map(async (b) => ({
type: 'tool_result' as const,
tool_use_id: b.id,
content: await executeTool(b.name, b.input),
})),
);
// ALL results go back in ONE user message; this becomes the next iteration's context.
messages.push({ role: 'user', content: results });
continue;
}
// Anything else (e.g. max_tokens) is an operational condition, not "task complete".
throw new AgentLoopError(response.stop_reason);
}Emergent tool sequences you never wrote down
Scenario 1 · Customer Support Resolution AgentA customer writes: "my order arrived smashed, and I think I was double-charged last month." No decision tree in the codebase covers "damaged goods plus a billing dispute". In a model-driven loop, Claude calls get_customer to establish identity, then lookup_order for the damaged item, notices the second concern in the accumulated context, looks up the billing history, and only then decides whether process_refund covers both or whether the policy exception requires escalate_to_human.
The correct architectural response to a case like this is to keep the loop model-driven and improve the inputs to reasoning — richer tool descriptions, clearer escalation criteria — not to add a pre-turn classifier that picks tools by keyword. A classifier would have routed on "smashed" and silently dropped the billing concern.
Distinguishing a circuit breaker from a stopping mechanism
Scenario 4 · Developer Productivity with ClaudeA codebase-exploration agent is given "find every place we validate email addresses". Legitimate runs take 30–60 tool calls across Grep, Glob and Read. A team ships if (iterations > 10) return partialAnswer and immediately sees truncated, confidently-wrong answers.
The fix is to separate the two concerns. Termination stays bound to stop_reason === "end_turn". A cap of, say, 200 iterations remains — but it throws, logs, and alerts, because reaching it means the agent is looping, not that it finished. Same for a wall-clock timeout: it is an incident signal, not a result.
typescript Cap as circuit breaker, not exit path
const MAX_ITERATIONS = 200; // runaway protection only
let iterations = 0;
while (true) {
if (++iterations > MAX_ITERATIONS) {
// Loud failure — NOT a successful completion.
metrics.increment('agent.runaway');
throw new RunawayLoopError({ iterations, lastToolCalls: recentToolNames });
}
const response = await step(messages);
if (response.stop_reason === 'end_turn') return response; // the real exit
// ... execute tools, append results, continue
}Anti-patterns
- Parsing natural-language signals ("I'm done", "that completes the task") from the assistant text to terminate the loop, instead of branching on
stop_reasonbecause Claude routinely writes conversational prose in the same message as atool_useblock and the loop exits mid-task. - Using an arbitrary iteration cap as the primary stopping mechanism instead of
stop_reason === "end_turn"because legitimate investigations vary enormously in length and the cap silently truncates them into confident partial answers. - Treating the presence of assistant text content as a completion indicator instead of reading
stop_reasonbecause text and tool requests coexist in the same response. - Executing tools but not appending their results to conversation history (or appending only a summary of them) instead of returning proper
tool_resultblocks because the model then re-requests the same tools or reasons from stale context.
How it is examined
- When a stem describes a loop that "sometimes stops early" or "returns incomplete answers", scan the options for the one that binds termination to
stop_reason; options mentioning text parsing, keyword detection, or iteration limits are the distractors. - Options that add a pre-turn routing classifier, a keyword-based tool selector, or a fixed tool sequence are testing whether you understand model-driven decision-making — they are almost always over-engineered and wrong unless the stem explicitly requires deterministic ordering (that is 1.4 territory).
- Watch for options that "summarize tool results to save tokens" before appending them; discarding raw tool results breaks the reasoning chain this statement is about.
Why this is true
An agentic loop is the smallest unit of autonomy in the Claude Agent SDK. You hand Claude a goal and a tool inventory. Claude — not your code — picks the next tool from everything it has learned so far.
The lifecycle
Each iteration has four steps:
- Send the current conversation (system prompt, tools, full message history) to the model.
- Inspect
stop_reason, and branch on it alone. - Execute every requested tool. One assistant message may carry several
tool_useblocks — run them and collect all results. - Append and repeat. Push the assistant message in full (the
tool_useblocks must survive), then push one user message containing every matchingtool_result. Loop back to step 1.
stop_reason |
Claude's meaning | Loop action |
|---|---|---|
"tool_use" |
Needs tools run before it can continue | Execute, append results, iterate |
"end_turn" |
Turn finished, answer produced | Exit — the only normal exit |
Anything else (max_tokens) |
An operational condition | Raise and alert; never read as "complete" |
Two invariants make this work. First, stop_reason is a structured field the model emits deliberately, so branching on it is deterministic. Second, tool results are appended to history, not consumed and discarded. That accumulation is what lets Claude reason about the next action: having seen lookup_order return "delivered", it can decide a replacement is appropriate without you writing a rule for it.
Model-driven vs pre-configured
A pre-configured decision tree or fixed tool sequence encodes the paths you anticipated. A model-driven loop encodes the goal and lets Claude compose paths at runtime — including ones you never enumerated. That is the whole point of the pattern, and it is why "add a routing classifier that pre-selects the tool" is almost always the wrong answer on the exam: it replaces reasoning with keyword matching.
The trade is that termination must be read from the protocol, not guessed from the prose. Claude often writes a friendly closing sentence while still requesting a tool, so scanning for "done" or "I have completed" ends turns early and mid-task. A hard cap used as the primary stopping mechanism truncates legitimate long investigations. Caps and timeouts are circuit breakers for runaway behavior — logged and alerted on — never the normal exit path.
Exam guide, verbatim — what is measured
Knowledge of
- The agentic loop lifecycle: sending requests to Claude, inspecting stop_reason ("tool_use" vs "end_turn"), executing requested tools, and returning results for the next iteration
- How tool results are appended to conversation history so the model can reason about the next action
- The distinction between model-driven decision-making (Claude reasons about which tool to call next based on context) and pre-configured decision trees or tool sequences
Skills in
- Implementing agentic loop control flow that continues when stop_reason is "tool_use" and terminates when stop_reason is "end_turn"
- Adding tool results to conversation context between iterations so the model can incorporate new information into its reasoning
- Avoiding anti-patterns such as parsing natural language signals to determine loop termination, setting arbitrary iteration caps as the primary stopping mechanism, or checking for assistant text content as a completion indicator
Orchestrate multi-agent systems with coordinator-subagent patterns
What you need to know
- Hub-and-spoke: the coordinator mediates every subagent interaction, so there are no direct subagent-to-subagent edges.
- Subagents have isolated context — they inherit nothing from the coordinator automatically and share no memory across invocations.
- When every subagent succeeds but the output has coverage gaps, suspect the coordinator's task decomposition, not the subagents.
- A good coordinator selects subagents dynamically by query complexity instead of always running the full pipeline.
- Partition scope explicitly (distinct subtopics or source types) to minimize duplicated retrieval and wasted tokens.
- Iterative refinement — evaluate synthesis for gaps, re-delegate targeted queries, re-synthesize — is the mechanism that reaches sufficient coverage.
- Subagents recover from transient failures locally (bounded retry) and propagate to the coordinator only errors they cannot resolve — with the failure type, what was attempted and any partial results attached.
Show that all communication radiates from the coordinator, that there are no spoke-to-spoke edges, and that each subagent has its own isolated context.
Click the coordinator to highlight the delegation and return edges that touch it.
Show that synthesis is evaluated for coverage gaps and re-delegated with targeted queries until coverage is sufficient, rather than emitted after one forward pass.
Worked examples
Diagnosing coverage gaps: blame the decomposition
Scenario 3 · Multi-Agent Research SystemA research system produces a report on "the impact of AI on creative industries" that covers only visual arts. Logs show the web-search subagent found relevant articles, the document-analysis subagent summarized them correctly, and the synthesis subagent produced coherent prose. The coordinator's log shows three subtasks: "AI in digital art creation", "AI in graphic design", "AI in photography".
Every downstream agent did exactly what it was asked. The root cause is upstream: the coordinator's decomposition collapsed a broad domain into one sector. Fixes that actually address it are (a) instructing the coordinator to enumerate the sectors of a domain before assigning subtopics, and (b) adding a coverage-evaluation step that compares synthesis output against the enumerated sectors and re-delegates for the missing ones. Fixes that do not address it: telling the synthesis agent to look for gaps in what it received (it never received music sources), broadening the search agent's queries (it was scoped to "digital art"), or loosening the document agent's relevance filter.
Dynamic subagent selection instead of a fixed pipeline
Scenario 3 · Multi-Agent Research System"What year was the Transformer paper published?" does not need document analysis, synthesis and report generation. "Compare regulatory approaches to AI in the EU, US and China across the last three years, with citations" needs all of them, plus multiple refinement rounds.
The coordinator should classify requirements — breadth, recency, whether sources must be cited, whether a formal deliverable is expected — and invoke only the matching subagents. A coordinator prompt that says "always run search, then analysis, then synthesis, then report" burns tokens and latency on trivial queries and, worse, teaches the system that the pipeline is the plan rather than the goal.
typescript Coordinator prompt fragment: goals and selection criteria, not a fixed procedure
const coordinatorSystemPrompt = `
You coordinate a research team. Your goal is a comprehensive, correctly cited answer.
Available subagents: web-search, document-analysis, synthesis, report-generator.
Selection:
- Invoke only the subagents the query actually requires. A single-fact lookup
needs web-search alone; a broad comparative study needs the full team.
- Before assigning subtopics, enumerate the distinct sectors, regions or source
types the query spans. Assign each to exactly one subagent so scope does not overlap.
- Spawn independent subagents in the SAME response so they run in parallel.
Refinement:
- After synthesis, compare the output against your enumerated sectors.
- For each gap, re-delegate a targeted query to web-search or document-analysis,
then re-invoke synthesis. Repeat until coverage is sufficient.
Quality criteria: every claim carries a source URL; no sector left unaddressed;
contradictions between sources are surfaced, not averaged away.
`;Structured error context flowing back through the hub
Scenario 3 · Multi-Agent Research SystemThe web-search subagent times out on a complex topic. A timeout is a transient failure, so the subagent's first move is the right one: recover locally — a bounded retry with backoff, perhaps a narrower query. Subagents are expected to resolve transient failures themselves and propagate to the coordinator only what they cannot resolve locally.
What goes wrong is the shape of that propagation. Returning a generic "search unavailable" once the local retries are exhausted discards the failure type, the query attempted, the partial results already gathered and the plausible alternatives — precisely the material the only component with a whole-task view needs. The internal retry was correct; the information-free status is the defect. Return the structured payload instead and the coordinator can retry with a narrower query, switch to document analysis, or proceed with partial coverage and say so explicitly.
That payload goes to the coordinator and nowhere else: all subagent communication flows through the hub, which is what makes error handling observable and consistently handled across every spoke. (5.3 compares the candidate propagation designs side by side.)
The general rule: subagents recover locally, then report; coordinators decide. Unresolved error handling lives at the hub because that is where the whole-task view lives.
Anti-patterns
- Letting subagents call each other directly instead of routing through the coordinator because you lose the single observability, error-handling and information-flow boundary that makes the system debuggable.
- Decomposing a broad topic into a handful of narrow, same-flavor subtasks instead of first enumerating the domain's distinct sectors because every subagent then succeeds while the aggregate output silently misses whole areas.
- Always routing every query through the full subagent pipeline instead of selecting subagents by query complexity because trivial requests pay the full latency and token cost for no gain.
- Treating synthesis as a single forward pass instead of running an iterative refinement loop because gaps discovered at synthesis time then never get filled.
How it is examined
- When a stem says "each subagent completes successfully" but the output is incomplete, the answer is almost always the coordinator's decomposition — resist options that blame a downstream agent that worked within its assigned scope.
- For error-propagation items, prefer the option that returns rich structured context (failure type, attempted input, partial results, alternatives) to the coordinator; the distractors are a generic information-free status ("search unavailable"), empty-but-successful results, and workflow-killing exceptions. A bounded internal retry on a transient failure is not itself the flaw — swallowing the detail afterwards is.
- Options offering "give every subagent access to all tools so it can handle anything itself" test separation of concerns — prefer a narrowly scoped tool for the common case while complex work still routes through the coordinator.
Why this is true
Once one loop is not enough, the exam expects a hub-and-spoke topology: a single coordinator agent at the hub, specialized subagents on the spokes, and no spoke-to-spoke edges. All inter-subagent communication, error handling and information routing pass through the coordinator.
Why the hub matters
Routing everything through the coordinator buys three properties that a mesh cannot:
- Observability. Every delegation and every result crosses one boundary you can log, trace and cost-attribute.
- Consistent error handling. Unresolved failures arrive in one place, in one shape, from every spoke.
- Controlled information flow. The coordinator decides what each subagent is allowed to see, which keeps context windows small and attribution intact.
Consistent error handling is the one worth spelling out. When the search subagent times out and cannot recover locally, it returns structured error context to the coordinator: failure type, the query attempted, any partial results, plausible alternatives. The coordinator is the only component with enough view of the whole task to choose between retrying with a narrower query, substituting another source type, and proceeding with partial coverage.
Isolated context is the defining constraint
Subagents do not inherit the coordinator's conversation history, and they do not share memory between invocations. Whatever a subagent needs must be in the prompt the coordinator sends it. This is not a limitation to work around; it is what keeps a broad research task from collapsing into one enormous context window. But it means the coordinator's job is heavier than "call four things in order".
What the coordinator actually does
- Decompose the query into subtopics — and here is the failure mode the exam loves. If the coordinator decomposes "impact of AI on creative industries" into digital art, graphic design and photography, every subagent will succeed and the final report will still miss music, writing and film. Overly narrow decomposition produces incomplete coverage even when no component fails. Coverage is the coordinator's responsibility.
- Partition scope so subagents do not duplicate work — distinct subtopics, distinct source types, distinct time ranges.
- Select dynamically. A simple factual query should not traverse the full search → analyze → synthesize → report pipeline. The coordinator analyzes requirements and invokes only the subagents that query complexity warrants.
- Aggregate and refine. After synthesis, the coordinator evaluates the output for gaps, re-delegates targeted queries to search and analysis, and re-invokes synthesis. That iterative refinement loop — not a single forward pass — is how coverage converges.
Exam guide, verbatim — what is measured
Knowledge of
- Hub-and-spoke architecture where a coordinator agent manages all inter-subagent communication, error handling, and information routing
- How subagents operate with isolated context—they do not inherit the coordinator's conversation history automatically
- The role of the coordinator in task decomposition, delegation, result aggregation, and deciding which subagents to invoke based on query complexity
- Risks of overly narrow task decomposition by the coordinator, leading to incomplete coverage of broad research topics
Skills in
- Designing coordinator agents that analyze query requirements and dynamically select which subagents to invoke rather than always routing through the full pipeline
- Partitioning research scope across subagents to minimize duplication (e.g., assigning distinct subtopics or source types to each agent)
- Implementing iterative refinement loops where the coordinator evaluates synthesis output for gaps, re-delegates to search and analysis subagents with targeted queries, and re-invokes synthesis until coverage is sufficient
- Routing all subagent communication through the coordinator for observability, consistent error handling, and controlled information flow
Configure subagent invocation, context passing, and spawning
What you need to know
-
allowedToolson the coordinator must include"Task"— without it the coordinator physically cannot spawn subagents. - Subagents inherit no parent context and share no memory across invocations, so every needed finding must be pasted into the subagent prompt.
- An
AgentDefinitioncarries a routing-orienteddescription, a role/system prompt, and least-privilege tool restrictions. - Pass context as structured data that keeps metadata (source URL, document name, page number) separate from content so attribution survives the handoff.
- Emit multiple
Taskcalls in one coordinator response to get real parallelism; separate turns serialize the fan-out. - Write coordinator prompts as goals plus quality criteria, not procedural step lists, so subagents can adapt.
- Fork-based session management passes a shared analysis baseline to divergent explorations by inheritance rather than by pasting it into each prompt — every branch starts from identical context.
Show that parallel subagents come from multiple Task calls in one coordinator response, and that each Task prompt must carry its own complete context.
Worked examples
Declaring subagents and enabling delegation
Scenario 3 · Multi-Agent Research SystemEach subagent is an AgentDefinition with a description written to help the coordinator route, a system prompt that states the output contract, and a minimal tool set. Note that the synthesis agent gets no search tools at all — least privilege keeps it synthesizing — and that the coordinator's allowedTools includes "Task".
typescript AgentDefinition set plus the required "Task" entry
const agents: Record<string, AgentDefinition> = {
'web-search': {
description:
'Finds current public sources for ONE assigned subtopic. Use when the query needs recent or external information.',
prompt:
'You research a single assigned subtopic. Return JSON only: ' +
'{ findings: [{ claim, sourceUrl, sourceTitle, retrievedAt }] }. ' +
'Do not synthesize across subtopics; that is another agent\'s job.',
tools: ['WebSearch', 'WebFetch'],
},
'document-analysis': {
description:
'Extracts claims from supplied documents. Use when the coordinator has PDFs or files rather than web sources.',
prompt:
'Analyze only the documents provided. Return JSON: ' +
'{ findings: [{ claim, documentName, pageNumber }] }.',
tools: ['Read', 'Grep'],
},
synthesis: {
description:
'Combines findings supplied in the prompt into a cited narrative. Never gathers new information.',
prompt:
'You synthesize ONLY the findings given to you. Cite every claim with the ' +
'sourceUrl or documentName/pageNumber attached to it. Flag contradictions explicitly.',
tools: [], // least privilege: cannot search, cannot wander
},
};
const coordinatorOptions = {
agents,
// Without "Task" the coordinator cannot spawn ANY subagent.
allowedTools: ['Task', 'Read', 'Write'],
systemPrompt: coordinatorSystemPrompt,
};Passing complete findings with attribution preserved
Scenario 3 · Multi-Agent Research SystemA common bug: the coordinator sends the synthesis subagent a prose paragraph summarizing what search found. The synthesis agent then produces a plausible report with invented or misattributed citations, because the URLs were never actually passed.
The fix is to pass the complete findings as structured data, with metadata in named fields. The synthesis agent's prompt then contains everything it needs and every claim is traceable. This is also why the synthesis agent's tool list is empty: it should never need to go looking for a source that should already be in its prompt.
typescript Explicit, structured context handed to the synthesis subagent
// Coordinator builds the synthesis prompt from prior agents' raw outputs.
const synthesisPrompt = [
'Synthesize the findings below into a report on: ' + topic,
'',
'Quality criteria: every claim cites its source; no sector unaddressed;',
'contradictions between sources are surfaced, not averaged.',
'',
'FINDINGS (JSON — content and metadata are separate fields):',
JSON.stringify(
{
webFindings: webSearchResult.findings, // { claim, sourceUrl, sourceTitle, retrievedAt }
docFindings: docAnalysisResult.findings, // { claim, documentName, pageNumber }
sectorsAssigned: enumeratedSectors,
},
null,
2,
),
].join('\n');
// Spawn synthesis via the Task tool with the FULL context inline —
// it inherits nothing from this conversation.Parallel fan-out in a single response
Scenario 4 · Developer Productivity with ClaudeA developer-productivity agent must map an unfamiliar service: read the routing layer, read the data models, and read the test suite. These are independent. If the coordinator emits one Task call, waits for the result, then emits the next, wall-clock time is the sum of three subagent runs.
Emitting all three Task calls in the same assistant response runs them concurrently and the coordinator receives three results before its next decision. The coordinator prompt should say so explicitly — "when subtasks are independent, spawn them in the same response" — because the default conversational rhythm is one-at-a-time.
markdown Coordinator instruction that produces real parallelism
## Delegation
When two or more subtasks are independent (different files, different modules,
different source types), emit ALL of their Task calls in the SAME response so
they execute in parallel. Only serialize when a subtask genuinely needs a
previous subtask's result as input.
Each Task prompt must be self-contained: the subagent inherits none of this
conversation. Include the goal, the exact scope assigned to it, the output
format, and any findings from earlier agents it needs to do its job.Passing a shared baseline by inheritance instead of by prompt
Scenario 4 · Developer Productivity with ClaudeTwo ways to give two divergent explorations the same starting knowledge of a codebase, and the choice is a context-passing choice.
Prompt-level passing: run the mapping analysis once, summarize it, and paste that summary into two fresh subagent prompts. That is the right shape when the two units need different slices of context — but as a way to share one baseline it is lossy twice over. Whatever the mapping pass noticed and did not write down is gone, and each branch pays again to re-derive it.
Fork-based passing: run the mapping analysis once as a session, then fork_session from it for each branch. Every branch inherits the whole baseline — each file read, each dependency observed — with nothing re-serialized and nothing dropped, and each branch's later work stays out of the other's context. Use it when the baseline is expensive and the branches start from the same place; use explicit prompt context when they do not.
Anti-patterns
- Omitting
"Task"from the coordinator'sallowedToolswhile relying on the system prompt to request delegation because the coordinator has no mechanism to spawn subagents and will silently do the work itself. - Assuming a subagent can see the coordinator's conversation history or a previous invocation's findings instead of passing them explicitly in the prompt because subagent context is isolated and nothing carries over.
- Passing prior findings as a prose summary instead of structured data with separate metadata fields because source URLs, document names and page numbers are lost and the synthesis agent fabricates or misattributes citations.
- Spawning parallel subagents across separate coordinator turns instead of emitting multiple
Taskcalls in one response because the fan-out serializes and latency multiplies. - Writing coordinator prompts as step-by-step procedures instead of goals plus quality criteria because it removes the subagent adaptability that motivated the multi-agent design.
How it is examined
- A stem where "the coordinator never delegates" or "subagents are never invoked" is usually the
allowedTools/"Task"item — check configuration before prompt wording. - When an option says a subagent "will have access to the earlier analysis", treat it as false unless that analysis is explicitly in the prompt; isolated context is tested directly.
- Latency-reduction items often hinge on whether parallel
Taskcalls are emitted in one response versus across turns — read the option for where the calls are emitted, not just whether they are described as "parallel".
Why this is true
This statement is the mechanical half of 1.2: how a coordinator actually spawns and feeds subagents in the Claude Agent SDK.
The Task tool and allowedTools
Subagents are spawned with the Task tool. A coordinator that cannot see Task cannot delegate, no matter how good its prompt is — so allowedTools on the coordinator must include "Task". This is a favorite exam detail: a stem describes a coordinator that "keeps doing the work itself instead of delegating", and the correct answer is the missing Task entry, not a prompt rewrite.
AgentDefinition
Each subagent type is declared as an AgentDefinition with three parts:
| Part | What it holds | Why it carries weight |
|---|---|---|
description |
How the coordinator recognizes when this subagent applies | It is doing selection work — write it as a routing signal, not a label |
| System prompt | The subagent's role, output contract and quality bar | Nothing is inherited, so this is the only place the role is stated |
| Tool restrictions | Least privilege for that role | A synthesis agent that cannot search cannot wander off and start researching |
Context must be explicit
Because subagents have isolated context, complete findings from prior agents must be included directly in the subagent's prompt. If the synthesis subagent needs the web-search results and the document-analysis output, the coordinator pastes them in. There is no ambient state, no shared scratchpad by default, and no memory carried between two invocations of the same subagent type.
That makes the format of passed context load-bearing. Use structured data that separates content from metadata — source URL, document name, page number, retrieval timestamp — as distinct fields rather than prose. Attribution survives the handoff, and the synthesis agent can cite precisely instead of guessing which claim came from which source.
Parallelism and prompt style
To run subagents concurrently, the coordinator must emit multiple Task tool calls in a single response. Spreading them across separate turns serializes them and multiplies latency — and repeatedly signals to the model that one-at-a-time is the expected shape.
Finally, coordinator prompts should specify research goals and quality criteria, not step-by-step procedures. Procedural scripts freeze the plan at design time and remove exactly the adaptability you spawned subagents to get. Say "every claim must carry a source URL and no sector may be unaddressed"; do not say "first call search with these five queries".
Fork-based context passing
Everything above passes context forward by writing it into a prompt. Fork-based session management is the complementary mechanism: rather than re-serializing a baseline into each new unit's prompt, fork_session branches from a session that already holds it, so every branch starts from the identical shared analysis baseline. It is the one case where a divergent exploration does not need its context pasted in — it inherits it by construction.
That makes it the right choice when the baseline is expensive and the branches genuinely start from the same place: map a codebase once, then explore two approaches from it. It is the wrong choice when the branches need different slices of context, which is ordinary prompt-level context passing. (1.7 covers the operational decision between resuming, forking and restarting.)
Exam guide, verbatim — what is measured
Knowledge of
- The Task tool as the mechanism for spawning subagents, and the requirement that allowedTools must include "Task" for a coordinator to invoke subagents
- That subagent context must be explicitly provided in the prompt—subagents do not automatically inherit parent context or share memory between invocations
- The AgentDefinition configuration including descriptions, system prompts, and tool restrictions for each subagent type
- Fork-based session management for exploring divergent approaches from a shared analysis baseline
Skills in
- Including complete findings from prior agents directly in the subagent's prompt (e.g., passing web search results and document analysis outputs to the synthesis subagent)
- Using structured data formats to separate content from metadata (source URLs, document names, page numbers) when passing context between agents to preserve attribution
- Spawning parallel subagents by emitting multiple Task tool calls in a single coordinator response rather than across separate turns
- Designing coordinator prompts that specify research goals and quality criteria rather than step-by- step procedural instructions, to enable subagent adaptability
Implement multi-step workflows with enforcement and handoff patterns
What you need to know
- Prompt instructions and few-shot examples give probabilistic compliance; hooks and prerequisite gates give deterministic compliance.
- When errors have financial or legal consequences, enforce ordering programmatically — a non-zero failure rate is not acceptable there.
- A prerequisite gate blocks downstream tool calls until the prerequisite has returned the required state (e.g.
process_refundblocked untilget_customerreturns a verified ID). - Restricting which tools are available addresses availability, not ordering — it does not solve a sequence-violation problem.
- Decompose multi-concern requests into distinct items, investigate them in parallel over shared context, then synthesize one unified resolution.
- Escalation handoffs must be structured artifacts (customer ID, root cause, amount, recommended action) because the human agent cannot see the transcript.
Show that the gate sits between the model's tool request and execution, denies with an actionable reason, and records verified state only from the prerequisite tool's result.
Show identity established once, three concern branches investigated in parallel against that shared context, and a single synthesized resolution.
Worked examples
Blocking process_refund until identity is verified
Scenario 1 · Customer Support Resolution AgentProduction data shows that in 12% of cases the agent skips get_customer and calls lookup_order from a customer-stated name alone, occasionally misidentifying accounts and issuing incorrect refunds. Strengthening the system prompt reduces the rate; adding few-shot examples reduces it further; neither reaches zero.
The effective change is a programmatic prerequisite: track verified state per conversation, and intercept outgoing tool calls to refuse lookup_order and process_refund until get_customer has produced a verified customer ID. The denial message tells the agent what to do instead, so the loop self-corrects on the next iteration rather than failing the customer.
typescript Prerequisite gate implemented as a tool-call interception hook
const GATED_TOOLS = new Set(['lookup_order', 'process_refund']);
// Per-conversation state, populated only by a successful get_customer result.
type SessionState = { verifiedCustomerId?: string };
function gateToolCall(toolName: string, state: SessionState) {
if (GATED_TOOLS.has(toolName) && !state.verifiedCustomerId) {
return {
decision: 'deny' as const,
// The agent SEES this and can recover on the next iteration.
reason:
'Blocked: customer identity is not verified. Call get_customer first and ' +
'use the verified customer ID it returns.',
};
}
return { decision: 'allow' as const };
}
// Recorded from the tool RESULT, never from what the model claims:
function recordCustomerVerification(result: GetCustomerResult, state: SessionState) {
if (result.verified) state.verifiedCustomerId = result.customerId;
}Multi-concern decomposition over shared context
Scenario 1 · Customer Support Resolution Agent"My headphones arrived cracked, I was charged twice in March, and please update my shipping address." Three concerns, one customer.
Verify identity once, then fan out: a damaged-goods branch (order lookup, warranty eligibility, replacement vs refund), a billing branch (transaction history, duplicate detection), and an account branch (address update). All three read the same verified customer and account context instead of re-establishing it. Then synthesize: one reply that states the replacement is shipping, the duplicate charge is refunded at a specific amount, the address is updated, and — crucially — reconciles the two monetary outcomes into one coherent total.
Answering each concern in a separate pass with independent context is what produces replies that contradict themselves on amounts or eligibility.
A structured handoff the human can act on
Scenario 1 · Customer Support Resolution AgentThe agent determines that a refund exceeds policy and must escalate. The human agent picking this up sees a ticket, not the conversation. A structured summary with required fields turns a 10-minute re-investigation into a 30-second decision — and because the fields are required, the agent cannot escalate with a vague "customer is unhappy".
json Structured escalation handoff payload
{
"customerId": "cust_8842",
"verifiedAt": "2026-03-11T09:14:22Z",
"orderIds": ["ord_55120"],
"rootCause": "Carrier damage in transit; photo evidence provided. Item is outside the 30-day replacement window by 4 days.",
"requestedOutcome": "Full refund",
"amountAtStake": 742.00,
"policyConflict": "Refund exceeds the $500 autonomous limit and falls outside the replacement window.",
"actionsAlreadyTaken": [
"Identity verified via get_customer",
"Order and delivery status confirmed via lookup_order",
"Photo evidence reviewed and accepted"
],
"recommendedAction": "Approve one-time goodwill refund of $742.00; damage is documented and the window overrun is marginal.",
"conversationSummary": "Customer reported a cracked item on arrival, supplied photos, and asked for a refund rather than a replacement."
}Anti-patterns
- Strengthening the system prompt or adding few-shot examples to guarantee a critical tool ordering instead of adding a programmatic prerequisite because prompt-based compliance is probabilistic and the residual failure rate has financial consequences.
- Adding a routing classifier that enables only the tools appropriate to a request type instead of gating tool order because that changes tool availability and leaves the ordering violation untouched.
- Recording prerequisite state from the model's assertion ("I verified the customer") rather than from the prerequisite tool's actual result because the gate then trusts exactly the thing it exists to check.
- Escalating with a free-text note instead of a structured handoff containing customer ID, root cause, amount and recommended action because the human agent has no transcript access and must redo the investigation.
How it is examined
- Any stem with a percentage failure rate on a required tool sequence ("in 12% of cases the agent skips…") is asking for programmatic enforcement — the prompt-improvement and few-shot options are deliberate distractors.
- Distinguish ordering from availability: an option that restricts which tools are exposed does not fix when they may be called.
- For escalation items, the winning option is the one whose payload a human with no transcript could act on immediately; anything relying on "the human can review the conversation" is wrong by construction.
Why this is true
Some orderings must never be violated. Verify the customer before refunding them. Check the deploy target before running migrations. This statement is about the difference between asking for that ordering and enforcing it.
Prompt guidance is probabilistic; enforcement is deterministic
A system prompt that says "you must always call get_customer before any order operation" works most of the time. Most of the time is a non-zero failure rate, and when the consequence is a refund sent to the wrong account, the tolerable rate is zero. Few-shot examples move the number; they do not change its class. The exam states this directly: when deterministic compliance is required, prompt instructions alone have a non-zero failure rate.
Programmatic enforcement means a prerequisite gate in code: a hook or interceptor that inspects each outgoing tool call and blocks it unless the prerequisite has already produced the required state. process_refund and lookup_order are refused until get_customer has returned a verified customer ID for this conversation. The block is not silent — the agent receives an explanatory error and can recover by calling the prerequisite, which is exactly the behavior you want.
Note what a gate is not: it is not a routing classifier that decides which tools are available for a request type. That addresses tool availability, not tool ordering, and it is the classic distractor on this item. Nor is it a forced tool_choice. Forcing a specific tool (see 2.3) pins the first call of a turn; it cannot enforce a prerequisite that has to hold across the many turns of an agentic loop. That is exactly why the prerequisite lives in code, as a programmatic gate.
Decomposing multi-concern requests
Real support requests bundle concerns: a damaged item, a duplicate charge and a change of address in one message. The pattern has three moves: decompose the request into distinct items, investigate each in parallel using shared context, then synthesize a single unified resolution. The shared context — the verified customer, the account history — is established once and reused by every branch. Investigating serially wastes latency; answering each concern in isolation produces a reply that contradicts itself on totals or eligibility.
Structured handoff on escalation
When the agent escalates mid-process, the human receiving it has no access to the conversation transcript. A handoff that says "customer is upset about an order" forces a full re-investigation and destroys the time saved. A structured handoff summary carries the load-bearing facts: customer ID, order references, the root cause analysis the agent reached, the amount at stake, what has already been attempted, and a recommended action. Treat it as a typed artifact with required fields, not free prose — that is what makes it reliably complete.
Exam guide, verbatim — what is measured
Knowledge of
- The difference between programmatic enforcement (hooks, prerequisite gates) and prompt-based guidance for workflow ordering
- When deterministic compliance is required (e.g., identity verification before financial operations), prompt instructions alone have a non-zero failure rate
- Structured handoff protocols for mid-process escalation that include customer details, root cause analysis, and recommended actions
Skills in
- Implementing programmatic prerequisites that block downstream tool calls until prerequisite steps have completed (e.g., blocking process_refund until get_customer has returned a verified customer ID)
- Decomposing multi-concern customer requests into distinct items, then investigating each in parallel using shared context before synthesizing a unified resolution
- Compiling structured handoff summaries (customer ID, root cause, refund amount, recommended action) when escalating to human agents who lack access to the conversation transcript
Apply Agent SDK hooks for tool call interception and data normalization
What you need to know
-
PostToolUsehooks intercept tool results and transform them before the model processes them — the right place for data normalization. - Outgoing tool-call interception hooks enforce compliance by blocking policy-violating actions before they execute.
- A blocked call should redirect to an alternative workflow (e.g. human escalation), not just return an opaque error.
- Choose hooks when a business rule requires guaranteed compliance; choose prompt instructions only for judgment-based guidance.
- Normalizing timestamps, status codes and units in code removes reasoning the model would otherwise do imperfectly and for free tokens.
- Hooks are auditable artifacts — a reviewer can verify a few lines of code instead of sampling model behavior.
Show that heterogeneous MCP results pass through a PostToolUse hook and reach the model in a single canonical shape.
Give the learner a decision rule: hard business rules go in hooks for deterministic guarantees, judgment calls go in the prompt.
Click a rule type to reveal a worked example of each.
Worked examples
PostToolUse normalization across heterogeneous MCP tools
Scenario 1 · Customer Support Resolution Agentlookup_order (legacy service) returns { created: 1772585501, status: 3 }. get_customer (new service) returns { createdAt: "2026-03-01T12:00:00Z", status: "active" }. A billing MCP server returns amounts in cents; another in dollars.
A PostToolUse hook maps every result into one canonical shape before it reaches the model. The agent then compares dates, reasons about statuses and totals amounts without ever seeing the underlying inconsistency — and without you having to describe four formats in tool descriptions.
typescript PostToolUse hook normalizing timestamps, statuses and currency
const STATUS_CODES: Record<number, string> = {
1: 'pending', 2: 'processing', 3: 'shipped', 4: 'delivered', 5: 'canceled',
};
// PostToolUse: runs after the tool executes, before the model sees the result.
function normalizeToolResult(toolName: string, raw: unknown) {
const out = structuredClone(raw) as Record<string, any>;
// Unix epoch seconds -> ISO 8601
for (const key of ['created', 'updated', 'createdAt', 'updatedAt']) {
const v = out[key];
if (typeof v === 'number') out[key] = new Date(v * 1000).toISOString();
}
// Numeric status codes -> enumerated vocabulary
if (typeof out.status === 'number') {
out.status = STATUS_CODES[out.status] ?? 'unknown';
}
// Cents -> decimal currency, always with an explicit unit
if (typeof out.amountCents === 'number') {
out.amount = out.amountCents / 100;
out.currency = out.currency ?? 'USD';
delete out.amountCents;
}
return out; // the model only ever sees the canonical shape
}Blocking a refund above threshold and redirecting to escalation
Scenario 1 · Customer Support Resolution AgentPolicy: refunds above $500 require human approval. A prompt instruction gets this right most of the time; a hook gets it right every time.
The interception hook inspects the outgoing process_refund call, denies it when the amount exceeds the threshold, and returns a reason that names the alternative. The agent reads the denial in its next iteration and calls escalate_to_human with a structured handoff (see 1.4). Note that the check runs on the tool input, so it cannot be talked around.
typescript Outgoing tool-call interception with redirection
const REFUND_LIMIT = 500;
function interceptToolCall(toolName: string, input: Record<string, any>) {
if (toolName === 'process_refund' && Number(input.amount) > REFUND_LIMIT) {
return {
decision: 'deny' as const,
reason:
'Blocked: refunds above $' + REFUND_LIMIT + ' require human approval. ' +
'Call escalate_to_human with the customer ID, root cause, amount and a ' +
'recommended action instead.',
};
}
return { decision: 'allow' as const };
}
// Deterministic: the limit is enforced on the actual tool input, so no prompt
// wording, jailbreak or reasoning slip can exceed it.Choosing the mechanism: hook or prompt?
Scenario 1 · Customer Support Resolution AgentSort each rule by whether a single violation is acceptable.
| Rule | What one violation costs | Mechanism |
|---|---|---|
| "Refunds over $500 need approval" | A financial incident | Hook |
"Never call process_refund before identity is verified" |
Money sent to the wrong account | Hook — a prerequisite gate (1.4) |
| "Offer a replacement before a refund for damaged goods under warranty" | A suboptimal but defensible choice | Prompt |
| "Match the customer's tone; be concise" | A worse reply, nothing more — pure judgment | Prompt |
| "Timestamps must be ISO 8601 before reasoning" | The model converts epochs itself, imperfectly | PostToolUse hook, not a prompt instruction |
The trap on the exam is an option that proposes prompt reinforcement for something in the first two rows, or an elaborate classifier/ML pipeline for something in the last row.
Anti-patterns
- Relying on prompt instructions to enforce a hard business rule such as a refund ceiling instead of an interception hook because prompt compliance is probabilistic and one violation is one financial incident.
- Asking the model to normalize heterogeneous timestamps, status codes or units in its reasoning instead of doing it in a
PostToolUsehook because you pay tokens for work code does exactly and for free. - Blocking a policy-violating tool call with an opaque error and no alternative instead of redirecting to an escalation workflow because the agent has no path forward and the customer gets a dead end.
- Deriving enforcement state from what the model says rather than from actual tool inputs and results because the hook then trusts the very thing it is meant to constrain.
How it is examined
- The phrase "guaranteed", "always", "must never" in a stem is a hook signal; "prefer", "when appropriate", "calibrate" is a prompt signal.
-
PostToolUseis the term the guide uses for intercepting results before the model processes them — expect it named explicitly in options about data format inconsistency across MCP tools. - Distractors often propose a self-reported confidence score, a sentiment threshold, or a separately trained classifier where a deterministic hook or a prompt tweak is the proportionate answer; prefer the mechanism that matches the rule's hardness.
Why this is true
Hooks are the Agent SDK's interception points around tool use. They matter for two reasons the exam cares about: data normalization on the way in, and policy enforcement on the way out. Both give you deterministic behavior in a system that is otherwise probabilistic.
PostToolUse: transform results before the model sees them
A PostToolUse hook fires after a tool executes and before the result enters the model's context. That is the right place to normalize heterogeneous formats. In practice an agent talks to several MCP servers written by different teams: one returns Unix epoch seconds, another ISO 8601 strings, a third returns numeric status codes where a fourth returns human labels. Left alone, the model spends tokens reconciling formats and occasionally gets it wrong — comparing a 10-digit epoch to a date string, or guessing that status 3 means shipped.
Normalizing in a PostToolUse hook means the model only ever sees one canonical shape: ISO 8601 timestamps, an enumerated status vocabulary, consistent currency units. The transformation is code, so it is exact and free of reasoning cost. It also keeps tool descriptions honest: you are not documenting four date formats and hoping.
Interception on the outgoing side: enforce policy
The mirror-image pattern intercepts an outgoing tool call and can block it. This is where business rules with hard boundaries live — refunds above $500, deletions outside a sandbox, writes to production. A blocked call should not merely fail: it should redirect to an alternative workflow, typically by returning a denial that tells the agent to escalate instead. The agent then calls escalate_to_human on the next iteration, and the outcome is a correct escalation rather than an error.
Deterministic vs probabilistic compliance
The decision rule the exam wants: a business rule that must always hold goes in a hook; guidance goes in the prompt.
| Mechanism | Put the rule here when | Compliance you get | Worked example |
|---|---|---|---|
| Interception hook | The rule is a hard boundary that must always hold | Deterministic — checked in code against the actual tool input | "Never refund more than $500 without approval" |
| Prompt instruction | The rule is guidance the model should weigh | Probabilistic — a non-zero failure rate you have accepted | "Prefer offering a replacement before a refund for damaged goods" |
Hooks are also independently auditable: you can point a compliance reviewer at a few lines of code rather than at a distribution of model behavior.
The two patterns compose. Normalize inputs so the model reasons over clean data, gate outputs so its decisions cannot cross a hard line, and reserve the prompt for everything that genuinely requires judgment.
Exam guide, verbatim — what is measured
Knowledge of
- Hook patterns (e.g., PostToolUse) that intercept tool results for transformation before the model processes them
- Hook patterns that intercept outgoing tool calls to enforce compliance rules (e.g., blocking refunds above a threshold)
- The distinction between using hooks for deterministic guarantees versus relying on prompt instructions for probabilistic compliance
Skills in
- Implementing PostToolUse hooks to normalize heterogeneous data formats (Unix timestamps, ISO 8601, numeric status codes) from different MCP tools before the agent processes them
- Implementing tool call interception hooks that block policy-violating actions (e.g., refunds exceeding $500) and redirect to alternative workflows (e.g., human escalation)
- Choosing hooks over prompt-based enforcement when business rules require guaranteed compliance
Design task decomposition strategies for complex workflows
What you need to know
- Prompt chaining (fixed sequential steps) fits predictable multi-aspect work; dynamic decomposition fits open-ended investigation.
- Split large reviews into per-file local passes plus a separate cross-file integration pass to defeat attention dilution.
- A larger context window does not fix attention dilution — uneven depth and contradictory findings are an attention problem, not a capacity problem.
- Adaptive plans generate subtasks from what each step discovers, so newly found dependencies reshape the remaining work.
- For open-ended tasks: map structure, identify high-impact areas, then build a prioritized plan that adapts.
- Hybrids are legitimate — use a dynamic phase to produce the item list, then a fixed chain over those items.
Let the learner pick a decomposition pattern from one property: whether the subtasks are enumerable before work begins.
Show that equal-depth per-file analysis and a dedicated cross-file pass together cover what a single combined pass cannot.
Worked examples
Restructuring a 14-file review into focused passes
Scenario 5 · Claude Code for Continuous IntegrationA pull request touches 14 files in the stock-tracking module. The single-pass review gives detailed feedback on some files and superficial comments on others, misses obvious bugs, and contradicts itself — flagging a pattern as problematic in one file while approving identical code elsewhere in the same PR.
Restructure as prompt chaining: one focused pass per file for local issues (correctness, error handling, naming, tests), then one integration pass that receives only the per-file summaries and the diff's cross-file surface, and looks specifically at data flow, contract changes and consistency of patterns across files. Every file now gets equal depth, and the contradictions disappear because consistency is explicitly the integration pass's job.
Rejected alternatives: making developers split the PR (moves the burden), a bigger context window (does not improve attention quality), and majority voting over three full-PR passes (suppresses intermittently-detected real bugs).
typescript Prompt chaining: per-file passes then a cross-file integration pass
// Phase 1 — one focused pass per file. Equal depth, independent contexts.
const perFile = await Promise.all(
changedFiles.map((file) =>
runReviewPass({
prompt: 'Review ONLY this file for local issues: correctness, error handling, ' +
'naming, missing tests. Do not comment on other files.',
context: { path: file.path, diff: file.diff, fullText: file.after },
}),
),
);
// Phase 2 — integration pass sees the summaries, not 14 full files.
const integration = await runReviewPass({
prompt: 'You receive per-file review summaries and the cross-file surface of this PR. ' +
'Examine data flow between files, contract and signature changes, and ' +
'consistency: flag any pattern judged differently across files.',
context: { summaries: perFile, changedSignatures, callGraphDelta },
});
return mergeFindings(perFile, integration);Adaptive decomposition for "add comprehensive tests to a legacy codebase"
Scenario 4 · Developer Productivity with ClaudeThere is no correct fixed step list here, because the right subtasks depend on facts not yet known. The agent maps structure first (modules, entry points, existing test coverage, build and test tooling), then identifies high-impact areas (complexity, change frequency, code paths handling money or auth), then emits a prioritized plan.
The plan then adapts. Discovering that the payments module constructs its own HTTP client inline means a seam must be introduced before it can be tested, which inserts a refactor subtask ahead of the test-writing subtask and may reorder everything downstream of it. A fixed pipeline written before the mapping phase would have had no place to put that.
markdown Adaptive investigation plan that regenerates subtasks
## Phase 1 — Map (before planning anything)
- Enumerate modules, entry points and public interfaces
- Measure existing coverage; identify the test runner and fixtures already in use
## Phase 2 — Identify high-impact areas
- Rank by: cyclomatic complexity x change frequency x blast radius
- Flag money, auth and data-mutation paths as highest priority regardless of rank
## Phase 3 — Prioritized, adaptive plan
For each target, in priority order:
1. Attempt a characterization test against the current behavior.
2. If the code is untestable as written, INSERT a seam-extraction subtask before it
and re-evaluate the remaining priority order — a new dependency may promote or
demote later targets.
3. Record what was learned so later targets reuse the discovered fixtures.
Re-plan whenever a step reveals a dependency the plan did not account for.Picking the pattern from the workload
Scenario 4 · Developer Productivity with ClaudeTwo requests, two shapes.
"Review this diff for security, performance and style issues" — the three aspects are known before you start. Chain three focused passes, one per aspect, and merge. Fixed pipeline.
"Why does the checkout flow intermittently double-charge?" — you cannot enumerate the steps: the second step depends on what the logs say, the third on whether the retry path or the idempotency key is implicated. Dynamic decomposition, where each finding generates the next subtask.
The hybrid case is the most common in practice: "review this 40-file PR" needs a dynamic phase to determine which files interact (producing the item list) followed by a fixed per-item chain and an integration pass. Choosing purely on "big task ⇒ pipeline" is the mistake — choose on whether the subtasks are knowable in advance.
Anti-patterns
- Reviewing many files in one combined pass instead of per-file passes plus an integration pass because attention dilutes and you get uneven depth, missed bugs and self-contradictory findings.
- Moving to a larger context window to fix uneven review quality instead of restructuring the decomposition because context capacity and attention quality are different problems.
- Running several independent full passes and reporting only findings that appear in a majority because it suppresses real bugs that are detected intermittently.
- Imposing a fixed step-by-step pipeline on an open-ended investigation instead of generating subtasks from intermediate findings because discovered dependencies have nowhere to go and the plan cannot absorb them.
How it is examined
- Symptoms of attention dilution — "detailed for some files, superficial for others", "contradictory feedback within one PR" — point at per-file passes plus an integration pass, not at model or context-window upgrades.
- Options that push work back to humans ("require developers to split the PR") or add consensus voting are standard distractors on decomposition items.
- For "add comprehensive X to a legacy codebase" stems, look for map → prioritize → adapt; any option offering a complete fixed step list up front is claiming knowledge nobody has yet.
Why this is true
Decomposition is the choice of shape for a multi-step job. The exam contrasts two shapes and expects you to match them to workload characteristics.
Fixed sequential pipelines (prompt chaining)
When the aspects to cover are known in advance, break the work into an ordered chain of focused steps, each with a narrow prompt and a clean context. The canonical case is code review: analyze each file individually for local issues, then run a separate cross-file integration pass examining data flow and contracts between them.
The reason this works is attention dilution. A single pass over fourteen files produces uneven results: detailed feedback on some files, superficial comments on others, obvious bugs missed. Worst is the self-contradiction — a pattern flagged in one file and approved in another within the same review. Splitting into per-file passes gives every file the same depth; the integration pass then catches exactly what per-file analysis structurally cannot see.
Two tempting non-fixes: a larger context window does not solve attention quality, it only makes the dilution possible at greater scale; and requiring humans to split large pull requests shifts the burden without improving the system. Voting across repeated full-PR passes is worse still — it suppresses real bugs that are only caught intermittently.
Dynamic adaptive decomposition
When you cannot know the subtasks until you have looked, the plan must be generated as you go. "Add comprehensive tests to this legacy codebase" has no fixed step list: the right work depends on what the structure turns out to be. The pattern runs in three phases: map first (module layout, entry points, existing coverage), identify high-impact areas (complexity, change frequency, blast radius), then produce a prioritized plan that adapts as dependencies are discovered. Finding that a module cannot be tested without a seam changes the plan, and the plan should absorb that.
Choosing between them
The discriminator is whether the aspects to examine are enumerable up front:
| Discriminator | Pattern | Worked example |
|---|---|---|
| The aspects are known before you start | Prompt chaining — a fixed sequence of focused steps, plus an integration pass if cross-item interactions matter | Review a diff for security, performance and style; one pass per file across N files |
| The subtasks only appear once you have looked | Dynamic decomposition — each step's findings generate the next subtasks | Understand an unfamiliar system; find the root cause of an intermittent failure; plan a migration |
| A discovery phase can produce the item list | Hybrid — dynamic mapping first, then a fixed chain over what it found | Review a 40-file PR: work out which files interact, then chain per item and add an integration pass |
Hybrids are normal and often correct, so do not treat the third row as a compromise.
Exam guide, verbatim — what is measured
Knowledge of
- When to use fixed sequential pipelines (prompt chaining) versus dynamic adaptive decomposition based on intermediate findings
- Prompt chaining patterns that break reviews into sequential steps (e.g., analyze each file individually, then run a cross-file integration pass)
- The value of adaptive investigation plans that generate subtasks based on what is discovered at each step
Skills in
- Selecting task decomposition patterns appropriate to the workflow: prompt chaining for predictable multi-aspect reviews, dynamic decomposition for open-ended investigation tasks
- Splitting large code reviews into per-file local analysis passes plus a separate cross-file integration pass to avoid attention dilution
- Decomposing open-ended tasks (e.g., "add comprehensive tests to a legacy codebase") by first mapping structure, identifying high-impact areas, then creating a prioritized plan that adapts as dependencies are discovered
Manage session state, resumption, and forking
What you need to know
- Use
--resume <session-name>with meaningful names to continue a specific named investigation across work sessions. - Use
fork_sessionto branch independently from a shared analysis baseline so each branch inherits the expensive exploration without contaminating the others. - Staleness of the tool results, not elapsed time, is what makes a fresh session with an injected summary beat
--resume. - Stale tool results are worse than no context — the agent reasons confidently from file contents and test output that no longer reflect reality.
- When resuming after code changes, tell the agent exactly which files changed so it re-analyzes those targets instead of trusting cache or re-exploring everything.
- Writing a structured summary (findings, decisions, open questions, files touched) at the end of a session makes both resumption and clean restart cheap.
Give the learner a decision path keyed on whether prior tool results are still valid and whether divergent branches are needed.
Click a decision node to highlight the branch it selects.
Show that one expensive baseline is inherited by independent branches whose contexts never mix, and that only one branch is carried forward.
Worked examples
Named resumption with targeted re-analysis
Scenario 4 · Developer Productivity with ClaudeYesterday's session named payment-refactor mapped the payments module and identified three seams to extract. Overnight, a colleague merged changes to billing/invoice.ts and payments/gateway.ts.
Resuming blind means the agent still believes the old contents of both files. Resuming with an explicit change notice keeps the valuable architectural understanding and invalidates only what actually moved — far cheaper than a full re-exploration and far safer than trusting the cached reads.
bash Resume a named session and scope re-analysis to what changed
# Continue the specific named investigation from yesterday.
claude --resume payment-refactor
# First message of the resumed session — invalidate only the stale reads:
# "Since our last session, two files changed on main:
# - billing/invoice.ts
# - payments/gateway.ts
# Re-read both before continuing. Your earlier reads of these files are stale;
# everything else from our analysis still holds. Then confirm whether the three
# seams we identified are still the right extraction points."Forking a shared baseline to compare two testing strategies
Scenario 4 · Developer Productivity with ClaudeAn agent has spent significant effort building a baseline: module map, dependency graph, existing coverage report, test tooling conventions. Now the team wants to compare two strategies for the payments module — integration tests through the public API versus unit tests behind injected dependencies.
Forking gives each branch that baseline for free and keeps their contexts independent, so one branch's abandoned attempts do not confuse the other. The branches run in parallel and are compared on concrete outcomes (coverage achieved, execution time, refactor cost), and only the winner is carried forward. Re-running the baseline analysis twice would cost the same expensive exploration twice; continuing in one session would interleave two incompatible lines of reasoning.
typescript Illustrative pseudocode — two branches from one analysis baseline via fork_session
// ILLUSTRATIVE PSEUDOCODE. The shape of the flow is the point; the field and
// function names below are not an SDK signature. The guide's term for the
// mechanism is fork_session.
// One expensive baseline: module map, dependency graph, coverage, conventions.
const baseline = await runSession({
sessionName: 'payments-baseline',
prompt: 'Map the payments module: dependencies, entry points, existing coverage, test conventions.',
});
// Two divergent branches, each inheriting the baseline, neither polluting the other.
const [integrationBranch, unitBranch] = await Promise.all([
runSession({
resume: baseline.sessionId,
fork_session: true, // independent branch from the shared baseline
prompt: 'Strategy A: integration tests through the public API. Report coverage, runtime, refactor cost.',
}),
runSession({
resume: baseline.sessionId,
fork_session: true,
prompt: 'Strategy B: unit tests with injected dependencies. Report coverage, runtime, refactor cost.',
}),
]);
// Compare on measured outcomes; carry exactly one forward.When a structured summary beats resuming
Scenario 2 · Code Generation with Claude CodeAn investigation session from two weeks ago contains hundreds of tool results: file reads, grep output, test runs. Since then the module was substantially rewritten. Resuming loads all of that stale evidence into context, where it competes with reality — and the agent will happily cite a function signature that no longer exists.
The reliable move is a fresh session seeded with a structured summary of the conclusions, not the raw tool output. The summary is small, current in its claims, and explicitly marks what must be re-verified. The agent starts clean and re-reads the code as it is now.
markdown Injected summary for a fresh session (conclusions, not stale tool output)
## Prior investigation summary — checkout double-charge (2 weeks ago)
### Conclusions reached
- Double charges correlate with client retries during gateway timeouts.
- The idempotency key is derived from the cart hash, which changes on retry.
### Decisions taken
- Key idempotency on a client-generated request ID instead of the cart hash.
### Open questions
- Does the gateway honor idempotency keys on the refund path too?
### Must be re-verified (code has changed since)
- checkout/service.ts and payments/gateway.ts were rewritten. Re-read both.
- The failing test named in the old session may no longer exist. Re-run the suite.
Do not rely on any file contents or test output from the previous session.Anti-patterns
- Resuming a session after significant code changes without telling the agent which files changed because it reasons from stale cached tool results that look authoritative and produces confidently wrong edits.
- Resuming a long-stale session instead of starting fresh with a structured summary because stale raw tool output competes with current reality and a summary of conclusions is more reliable.
- Re-running the full baseline analysis for each alternative approach instead of using
fork_sessionfrom a shared baseline because you pay for the same expensive exploration repeatedly. - Exploring two divergent approaches in one continuing session instead of separate forks because each branch's dead ends contaminate the other's reasoning.
- Relying on opaque auto-generated session identifiers instead of named sessions with
--resume <session-name>because you cannot reliably find the right prior investigation later.
How it is examined
- For resume-versus-restart items, the discriminator in the stem is always whether prior tool results are still accurate — not how long ago the session ran or how much context it holds.
- When a stem describes comparing two approaches from the same understanding of a codebase, the answer names
fork_session; options that re-analyze per branch or that continue in one session are the distractors. - Options offering "resume and let the agent re-explore everything" are inefficient but not wrong-by-mechanism; prefer the option that scopes re-analysis to the specific files that changed.
Why this is true
Long-running agent work spans days and branches. This statement covers the three levers: resume, fork, and deliberate restart.
| Lever | Reach for it when | What the next session starts from |
|---|---|---|
--resume <session-name> |
Prior context is still substantially valid | The whole prior conversation, cached tool results included |
fork_session |
Two approaches should diverge from one expensive baseline | The shared baseline, inherited — no branch sees another's work |
| Start fresh with a structured summary | Prior tool results are stale | A short summary of conclusions that you inject; no raw tool output |
Named resumption with --resume
--resume <session-name> continues a specific prior conversation, with its accumulated exploration, findings and decisions intact. Naming sessions is what makes this usable: --resume payment-refactor is a reliable handle for the investigation you were running yesterday, whereas an opaque identifier is not. Use it when picking up an investigation whose prior context is still substantially valid.
fork_session for divergent exploration
fork_session creates an independent branch from a shared baseline. The value is that the expensive part — mapping the codebase, understanding the data model, reading the existing tests — is done once, and each branch inherits it. You then explore genuinely divergent approaches in parallel without contaminating each other. Fork A pursues integration tests through the public API while fork B pursues unit tests with dependency injection; or fork A tries the incremental refactor and fork B the rewrite. Compare outcomes and keep one. Without forking you either re-derive the baseline per branch or let one branch's dead ends pollute the other's context.
One terminology warning, because nothing else in the guide flags it: "fork" means two unrelated things. fork_session here creates a branch that inherits a shared analysis baseline. context: fork in skill frontmatter (Domain 3, §3.2) isolates a skill's output so it never enters the main conversation. Same word, opposite concern — inheritance versus isolation — and the two share no mechanism.
Resume versus start fresh
The important judgment call. Resume when prior context is mostly valid. Start a new session with an injected structured summary when prior tool results are stale.
Staleness is the crux. A resumed session's history contains tool results — file contents, test output, grep matches — captured at a point in time. If the code has since changed, those results are now confidently wrong, and the agent will reason from them: editing a function that no longer exists, citing a line number that moved, assuming a test still fails. A resumed session with stale tool results is more dangerous than a fresh one, because the errors look grounded.
So if files changed since the last session, you have two options. The more reliable one is to start fresh with a structured summary of the conclusions, not the raw tool output. The other is to resume and explicitly inform the agent which files changed, so it re-reads exactly those instead of trusting cached content or re-exploring the entire codebase. Targeted re-analysis is the middle path: cheaper than a full re-exploration, safer than blind trust.
A useful habit: end each work session by having the agent write a structured summary — findings, decisions, open questions, files touched. That artifact makes both resume-with-updates and fresh-start-with-summary cheap.
Exam guide, verbatim — what is measured
Knowledge of
- Named session resumption using --resume
to continue a specific prior conversation - fork_session for creating independent branches from a shared analysis baseline to explore divergent approaches
- The importance of informing the agent about changes to previously analyzed files when resuming sessions after code modifications
- Why starting a new session with a structured summary is more reliable than resuming with stale tool results
Skills in
- Using --resume with session names to continue named investigation sessions across work sessions
- Using fork_session to create parallel exploration branches (e.g., comparing two testing strategies or refactoring approaches from a shared codebase analysis)
- Choosing between session resumption (when prior context is mostly valid) and starting fresh with injected summaries (when prior tool results are stale)
- Informing a resumed session about specific file changes for targeted re-analysis rather than requiring full re-exploration