This is the heaviest domain, and the one that quietly decides pass or fail. What it's really checking is whether you can choose and justify an architecture โ not just recite the name of one.
๐ New here? The story of why this domain exists
You've already run an agent. Every time Claude Code fixed a bug for you โ grep, read, edit, retest โ you watched an agent loop execute. This domain is that loop, formalized: what starts it, what feeds it, and above all what stops it.
The problem it solves: a model that can act is a model that can act wrongly, expensively, and repeatedly. The first time a team ships an agent, it works in the demo. The second week, it refunds someone twice (no idempotency), spends $40 on one runaway task (no budget), and confidently emails a customer something untrue (no gate). None of that is the model's fault โ it's missing architecture.
The solution shape: keep the model as the decision-maker and wrap it in deterministic machinery โ the harness โ that executes tools, enforces limits, requires human sign-off where stakes are high, and logs everything. Then choose the lightest pattern that fits: a fixed pipeline (workflow) when you know the steps; a looping agent only when you genuinely can't predict the path.
So what for the exam: nearly every scenario question here reduces to two choices โ which pattern fits this task? and where does the deterministic leash go? Learn those two instincts and 27% of the exam becomes readable.
At a glance
Concept
One-liner
Agent loop
gather context โ model decides โ execute tools โ append results โ repeat until done
Workflow vs agent
predefined code path with LLM steps vs model-directed looping โ prefer workflows when the path is known
Orchestratorโworkers
a coordinator model plans and delegates to parallel specialized subagents
Evaluatorโoptimizer
one model generates, another critiques in a loop until quality passes
Stop reason
the Claude API's signal for why generation ended โ the harness branches on it
Human-in-the-loop
deterministic approval gates for high-risk actions
Guardrails
deterministic checks the model cannot talk its way past
The agentic loop โ the exam's core object
๐งญ Your seat at the table: the loop runs Claude's thinking, but everything it thinks with is your construction. Before any model call, you assembled the context (the messages array and its roles), chose the objective (the system prompt), curated what it can do (the tool catalog, from your tool registry), and set the rules (gates, budgets, guardrails). The exam calls this "architecture"; day to day, it's just being a good host to a brilliant guest.
flowchart TD
S[Start: task + context] --> B[Build prompt: system + messages + tool definitions]
B --> M[๐ง Claude call]
M --> SR{stop_reason?}
SR -->|tool_use| X[Harness executes the tool]
X --> A[Append tool_result to messages]
A --> G{Gates: budgets ยท guardrails ยท HITL}
G -->|ok| B
G -->|violation| E[Escalate / halt]
SR -->|end_turn| R[Final response]
SR -->|max_tokens| T[Truncated โ handle!]
R --> V[Verify: evals, schema checks]
Every Anthropic doc keeps coming back to the same three phases: gather context โ take action โ verify results. Here's the part worth internalizing โ the model never actually does anything. It only requests actions, by emitting tool_use blocks; your deterministic harness is what runs them and hands back the tool_result blocks.
๐ See it run โ a support agent handles "my order never arrived", turn by turn
Entry point: a customer message arrives via the support webhook: "My order #4531 never arrived. Can you send a replacement?" The harness looks up the customer record and starts a run.
{
"system": "You are a support agent for Acme Store. Resolve delivery issues. Never promise refunds โ replacements only, per policy P-12.",
"tools": [
{
"name": "get_order",
"description": "Fetch one order by id. Read-only. Returns status, value, and replacement eligibility. Use when the customer references a specific order.",
"input_schema": {
"type": "object",
"required": ["order_id"],
"properties": { "order_id": { "type": "string" } },
"additionalProperties": false
}
},
{
"name": "create_replacement",
"description": "Ship a replacement for a lost or damaged order. SIDE EFFECT: creates a real shipment.",
"input_schema": { "โฆ": "same three-part shape as get_order โ elided here for brevity" }
}
],
"messages": [{ "role": "user", "content": "My order #4531 never arrived. Can you send a replacement?" }]
}
(Every tool entry always carries the same three fields โ name, description, input_schema (a JSON Schema for the arguments). Where you see โฆ in this guide it means "elided for brevity", never real syntax. Tool-definition craft โ why the description matters most โ is Domain 4's subject.)
Turn 1 โ [๐ง Claude call] returns (abridged):
JSON
{
"stop_reason": "tool_use",
"content": [
{"type": "text", "text": "Let me look up that order first."},
{"type": "tool_use", "id": "toolu_01A", "name": "get_order", "input": {"order_id": "4531"}}
]
}
Where did "id": "toolu_01A" come from? Not from you โ your tool list has no id field. The Claude API generates a fresh id for every tool_use block (the Claude API meaning Anthropic's Messages endpoint that carried this model call โ not the store's order system, and not the webhook that delivered the customer message). Its one job is correlation: the tool_result you send back echoes it as tool_use_id, so the Claude API knows which request each result answers (this matters when one response carries several tool requests). Definition vs. call, in one line: you name the tool; the Claude API names each use of it.
[stop_reason? โ tool_use] โ the left branch. Note what did NOT happen: the model didn't query any database. It emitted a request as data.
[Harness executes the tool] โ validates order_id against the schema, queries the DB:
[Append tool_result to messages] โ the harness sends that back as a tool_result block with tool_use_id: "toolu_01A", then hits [Gates]: turn 1 of max 6 โ, no side effect yet โ โ ok branch โ loops back to [Build prompt].
Turn 2 โ [๐ง Claude call] now sees the order data and returns:
[Gates] โ this one has a side effect. The HITL rule says: replacements under $100 auto-approve, over $100 need a human. $89 โ ok. (Had it been a $600 order, this is exactly where the violation โ [Escalate / halt] branch fires: the run parks, a human gets the packet, and nothing has executed.) The harness runs the tool with idempotency key replace-4531 โ so a retry can never ship two boxes โ and gets back {"replacement_id": "R-7821", "eta_days": 3}.
Turn 3 โ [๐ง Claude call] returns:
JSON
{
"stop_reason": "end_turn",
"content": [{"type": "text", "text": "I'm sorry your order was lost in transit. I've created replacement R-7821 โ it should arrive within 3 days."}]
}
[stop_reason? โ end_turn] โ [Final response] โ [Verify] โ deterministic checks before delivery: response contains a replacement id โ, contains no refund promise (policy P-12) โ โ send to customer. Run log: 3 turns, 2 tool calls, 1 gate check, terminal state resolved.
The third branch: had turn 3 come back with "stop_reason": "max_tokens" mid-sentence, the [Truncated โ handle!] node applies โ the harness must never deliver or parse it as complete; it raises the limit and continues, or fails loudly.
The messages array โ how the loop physically grows
The messages field puzzles everyone at first: why an array of objects? And when the loop runs, does the new stuff get prepended or appended โ and where does the tool result go?
Why an array: here's the thing that reframes everything โ the Claude API is stateless. It remembers no conversation between calls (the same fact sitting behind the tool registry: nothing lives on Anthropic's side). So if you want it to know what happened earlier, the entire conversation history has to ride along inside every request โ and messages is that history: an ordered array, oldest first, each element one turn carrying a role (user or assistant, alternating) and its content. The model doesn't "remember" turn 1. It re-reads it, every single call, because you re-sent it.
The growth rule: every new turn gets appended at the end โ never prepended. That's two appends per loop iteration, and here's the bit nobody tells you up front: the model's own response goes right back into the array too. Watch it grow across the support-agent run from above:
PYTHON
# โโ Call 1: one element
messages = [
{"role": "user", "content": "My order #4531 never arrived. Can you send a replacement?"}
]
resp = client.messages.create(model=MODEL, system=SYSTEM, tools=TOOLS, messages=messages)
# โ stop_reason "tool_use": wants get_order
# โโ Append #1: the assistant's response โ VERBATIM, tool_use block and all
messages.append({"role": "assistant", "content": resp.content})
# โโ Append #2: your tool result โ inside a USER-role message
messages.append({"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_01A",
"content": '{"status": "lost_in_transit", "value_cents": 8900}'}
]})
# โโ Call 2: the SAME array, now 3 elements, resent IN FULL
resp = client.messages.create(model=MODEL, system=SYSTEM, tools=TOOLS, messages=messages)
# โ another tool_use โ two more appends โ Call 3 sends 5 elements โ end_turn
So here's how the array looks across the three calls of the walkthrough:
Call
The array (roles, oldest โ newest)
Elements
1
user (the complaint)
1
2
user ยท assistant (tool_use: get_order) ยท user (tool_result)
3
3
user ยท assistant (tool_use: create_replacement) ยท user (tool_result) ยท โฆ
5
Three details that quietly make or break a real harness:
The assistant turn must be echoed back exactly โ if you append only the tool_result without the assistant's tool_use message before it, the Claude API rejects the request: a tool_result must answer a tool_use that exists in the history.
The tool_result rides in a user-role message. There is no "tool" role โ from the model's perspective, tool results are things the outside world (you) reports back, and everything from the outside world arrives as user.
system and tools are NOT in the array โ they're separate request fields, re-sent alongside it each call. That's what makes them a byte-identical stable prefix while messages grows โ exactly the split prompt caching exploits (Domain 5).
And now you can see why context management even exists: a 40-turn conversation means a 40-turn array resent on every single call, growing without any natural ceiling. The messages array is the context-window budget Domain 5 spends its time managing โ compaction swaps old elements out for a summary, but that append-at-the-end rule never changes underneath it.
๐งฎ Fundamentals: the Claude call explained in the loop โ what bounds the response, and the context math
Three natural worries, in order: what stops the model from returning a huge response? Is the response restricted to a schema? And if everything gets appended, don't we run out of context? Three different leashes answer them โ each bounds a different thing:
Leash
Bounds
Who enforces it
max_tokens
the output of one call โ a hard ceiling you set per request
the Claude API โ the model physically stops there
input_schema
the tool arguments inside a tool_use block
steers generation; your harness validates (Domain 3 has the guarantee ladder)
the context window
the total: input + reserved output
the Claude API โ an over-long request is rejected
1 โ The response cannot be huge, because you capped it.max_tokens is a mandatory request field: the model generates at most that many output tokens, full stop. If it genuinely needed more, generation cuts off and stop_reason: max_tokens tells you so โ that's the "Truncated โ handle!" branch, not a silent overflow. And there's a second, natural bound in agent loops: a tool_use turn isn't prose โ it's a name plus JSON arguments, typically 50โ300 tokens. The support-agent walkthrough's actual sizes: turn 1's response โ 90 tokens, turn 2's โ 60, and only turn 3's customer-facing text reaches โ 120.
2 โ The whole response is NOT schema-restricted โ only tool arguments are.input_schema shapes what goes inside a tool_use block's input; the model's free-text content is bounded only by max_tokens and the prompt. When you need the entire output to obey a schema, that's the Domain 3 move: force a tool whose schema IS your output shape.
3 โ The context math, per call. Everything must fit the window (200K tokens standard) โ and max_tokensreserves its allowance from that same window before generation starts:
The walkthrough's three calls, honestly accounted:
Call
system + tools
messages array
max_tokens
Total demand
1
5.5K
0.1K
4K
~9.6K
2
5.5K*
0.3K
4K
~9.8K
3
5.5K*
0.5K
4K
~10K
* The starred 5.5K still occupies the window every call โ but bills at ~10% price thanks to prompt caching: the Claude API keeps a server-side copy of the processed prefix for a few minutes, so a byte-identical resend skips reprocessing. (This doesn't contradict statelessness โ the Claude API remembers no conversation; it briefly caches the computation of a prefix you resend anyway. Cache lives at the Claude API, not in your harness's memory.)
Nowhere near trouble โ a short run never is. The thing that actually eats context in real loops isn't the model's responses โ it's the tool results you append: one naive "return the whole tool-backend payload" tool can add 20K tokens in a single append, dwarfing every model turn combined. That's why Domain 5's first commandments are trim tool results and compact old turns.
4 โ And when the budget IS exceeded? Two different failures, two different fixes: output side โ generation hits max_tokens โ stop_reason tells you โ raise the cap or continue; input side โ the array has grown past the window โ the Claude API rejects the request with an error before any generation โ compact/summarize the history (Domain 5) and retry. Different symptoms, never confuse them: one is a truncated response, the other is no response at all.
Stop reasons โ memorize this table
Where does this list come from?stop_reason is a field the Claude API sets on every response โ a closed, standard set defined by Anthropic, and that's the whole point. Your harness never invents these values and can't add to them; it plays the other side of the contract: read the value and branch on it. (The webhook that delivered the task and the tool backends the harness calls don't get a say in this field.)
stop_reason
Meaning
Correct harness behavior
end_turn
Model finished its turn
Deliver/parse the response
tool_use
Model wants a tool executed
Run tool(s), append tool_result, call again
max_tokens
Output hit the token limit
Treat as incomplete โ raise limit, continue, or fail loudly; never parse as complete
stop_sequence
A custom stop string matched
Handle per your protocol
refusal / safety stop
Model declined
Do not auto-retry the same prompt in a loop
๐ชค Trap: a question shows JSON parsing failures "sometimes." The hidden cause is often max_tokens truncation being parsed as if complete. The architect answer: check stop_reason before parsing, and set max_tokens generously for structured output.
Agent: the model dynamically directs its own process and tool usage. Flexible, expensive, harder to bound.
The rule the exam keeps rewarding: reach for the simplest thing that works โ workflows for well-defined tasks, and agents only for the open-ended problems where you genuinely can't hardcode the path in advance. Any time a scenario hands you a known, repeatable sequence, a workflow pattern beats "give it tools and let it figure it out."
The five workflow patterns (parallelization comes in two flavors)
Anthropic's Building Effective Agents names five patterns โ the two Parallelization rows below are the two flavors of one pattern (sectioning and voting), which is why five categories fill six rows. Count patterns as five; memorize both flavors.
Pattern
Shape
Use when
Prompt chaining
output of call A feeds call B (with optional programmatic checks between)
task decomposes into fixed sequential subtasks
Routing
classifier directs input to a specialized downstream prompt/model
distinct input categories need distinct handling
Parallelization โ sectioning(flavor 1 of 2)
independent subtasks fan out concurrently
subtasks don't depend on each other
Parallelization โ voting(flavor 2 of 2)
same task run N times, results aggregated
confidence via diverse attempts
Orchestratorโworkers
central model decomposes dynamically, delegates, synthesizes
subtasks can't be predicted upfront
Evaluatorโoptimizer
generator + critic loop
clear evaluation criteria; iteration adds value
flowchart LR
subgraph Orchestrator-workers
O[Coordinator: plans + decomposes] --> W1[Worker: search]
O --> W2[Worker: analyze]
O --> W3[Worker: code]
W1 --> SYN[Synthesize]
W2 --> SYN
W3 --> SYN
end
๐ See it run โ "compare our three competitors' pricing" with orchestratorโworkers
Entry point: a PM asks the research agent: "Compare Acme, Bolt, and Corel's pricing pages and summarize how we should position."
[Coordinator: plans + decomposes] โ the coordinator model fetches nothing itself. It emits a plan as data: three independent research subtasks, one per competitor. The harness spawns three workers, each with its own clean context window holding only the shared research instructions + its one assigned competitor.
[Worker: search] ร3, in parallel โ each worker runs its own mini agent-loop (fetch page โ extract tiers โ normalize). Worker 2's fetched pricing page alone is ~12,000 tokens of HTML โ and that's the whole point: those 12K tokens live and die inside worker 2's window. What returns to the coordinator is a compressed summary:
~150 tokens each โ a ~99% compression before anything touches the coordinator's context. Who owns this shape? The harness owner defines and validates the worker-result schema (these fields โ competitor, model, tiers, usd_mo, notable); each worker emits one object conforming to it; the coordinator consumes the validated objects in its next prompt, and the run trace stores them.
[Synthesize] โ the coordinator reasons over three 150-token summaries (not three 12K-token pages) and writes the positioning memo.
Why not one agent? A single loop doing all three would be carrying ~36K tokens of page dumps in one window by step 3, degrading every later decision. The fan-out costs more total tokens, but each decision happens in a small, relevant context โ that's the trade the exam wants you to articulate. And workers never talk to each other: hub-and-spoke, coordination through the coordinator only.
Context isolation is the main reason to spawn subagents: each worker gets a clean, scoped context instead of one bloated window. The coordinator holds the plan; workers hold details.
Parallelize reads, serialize writes: research/search/read subagents can fan out; anything mutating shared state needs sequencing or isolation (git worktrees โ separate working copies of the repo so parallel agents don't clobber each other's files โ or queues).
Subagent results should return compressed summaries, not full transcripts, to protect the coordinator's context budget.
Hub-and-spoke beats free-for-all agent-to-agent chatter: coordination flows through the coordinator; workers don't talk to each other.
Know when NOT to multi-agent: added latency, token cost multiplication, and coordination failure modes mean a single well-tooled loop wins for bounded tasks.
Model portability โ the "what if we swap models?" question
Companies ask this early: "if we build on one vendor's SDK, are we locked in?" The industry's answer has three layers, and knowing which layer solves which problem is the architect skill:
Layer
What it solves
The tools
A gateway in front of models
credentials, quotas, failover, audit, and config-level swapping โ your harness speaks one interface; the gateway routes to providers
enterprise LLM gateways (self-built or LiteLLM-style proxies); cloud catalogs (Amazon Bedrock, Vertex AI) serving many models behind one auth surface
Ports-and-adapters in your harness
keeps the loop, gates, tools, and state PROVIDER-NEUTRAL; a thin adapter per provider translates message/tool formats
~200 lines you own โ the deterministic 80% of your agent never changes when the model does
Orchestration frameworks
buy the abstraction + ecosystem instead of building it
LangGraph (stateful agent graphs), and friends โ note LangSmith is observability/evals, not orchestration; you can use it with ANY harness
The trade nobody puts on the landing page: abstraction has a tax. A lowest-common-denominator model interface forfeits provider-native strengths โ prompt caching semantics, native structured outputs, extended thinking โ and frameworks lag new provider features. Anthropic's own guidance in Building Effective Agents is to use frameworks judiciously and keep the calling layer simple enough to understand. The Claude Agent SDK sits at the opposite pole: maximum harness quality, Claude-shaped by design (it does run against Bedrock/Vertex-served Claude โ cloud portability without model portability).
What the adapter actually translates โ the dialect problem. Every major provider converged on the same concepts: a model id, an ordered conversation, optional tool definitions, a token budget. That convergence is why gateways and adapters are feasible at all. But the dialects differ exactly where a hand-rolled integration breaks:
Concept
The Claude API
Typical other dialects
System instruction
top-level system field, NOT a message
a system/developer role inside messages, or a separate instruction field
Roles
user / assistant only
some add a dedicated tool role; one major provider says model instead of assistant
Tool definitions
input_schema (JSON Schema)
function.parameters, functionDeclarations โ same schema idea, different wrapping
Tool results
tool_result block inside a user message, matched by id
finish_reason: stop ยท tool_calls ยท lengthโฆ โ same idea, different names
Output budget
max_tokensrequired
usually optional with defaults
Same music, different notation โ an adapter is ~200 lines because it's transposing these six rows, not reinventing anything.
And the Agent SDK doesn't take this input shape at all โ by design. You don't hand it messages + tools; you hand it a prompt and options (allowed tools, max turns, system additions, MCP servers), and it owns building and growing the messages array internally. That's the abstraction level shift in one sentence: the Claude API's input is a conversation you manage; the Agent SDK's input is an intent plus a policy.
And the truth that makes this whole table honest: model-agnostic is NOT prompt-agnostic. Swapping frontier models is never a config flip in practice โ prompts are tuned to a model's behaviors, tool-selection patterns differ, guardrail phrasings land differently. The gateway makes a swap possible; only your eval suite (golden set + negative controls, run side-by-side) makes it safe. Teams that "swapped in an afternoon" had evals; teams that swapped by config discovered their refund agent's tone and tool habits changed in production.
๐ฏ Exam lens: portability questions reward the layered answer โ deterministic controls in the harness (they survive any swap), tools behind MCP (capability investments outlive model choices), model access behind a gateway, and an eval gate on every model change. "Rewrite on the other vendor's SDK" and "the framework handles it" are both trap answers.
Harness controls โ what makes an agent production-grade
Control
Mechanism
Budgets
max turns / max tokens / max cost / wall-clock time (real elapsed seconds) โ exceeded โ terminal state, not silent continuation
Guardrails
deterministic validation of model output (schemas, allowlists, arithmetic bounds) โ unpromptable
HITL gates
high-risk tools require human approval before execution; silence โ approval
Idempotency
retried actions must not double-execute (idempotency keys, effects ledgers โ a durable record of side effects already performed, checked before any retry)
Audit trail
every decision, tool call, and gate verdict logged and replayable
Checkpointing
long-running agents persist state so restarts resume, not restart
Where these controls physically live โ the container, the queue, the approval UI โ is the Deployment & Operations page's subject.
๐ฏ Exam lens: when a scenario asks "how do you prevent the agent from X," the correct answer is almost always a deterministic harness control, not "add instructions to the prompt." Prompts steer; harnesses enforce.
The harness as real files โ annotated, clickable
๐ก Budgets, gates and ledgers stop being vocabulary when you see them as config and code. Cookbook chips are public; the local chips open the tracecraft harness that runs on this machine.
JSONC
// usecase config โ BUDGETS: hard ceilings whose breach is a TERMINAL state, not a warning
{
"budgets": { "max_model_calls": 6, "max_tool_calls": 8, "max_turns": 3 },
"confidence_floor": 0.75 // below this, the classify gate routes to review
}
PYTHON
# a GATE โ plain arithmetic the model cannot talk its way past
def action_allowed(category, action, cfg):
allowed = cfg["actions"].get(category, [])
if action not in allowed: # allowlist: absence IS the policy
return False, f"{action} not allowed for {category}"
return True, None
JSONC
// EFFECTS LEDGER entry โ a retry replays the RECORD, never the side effect
{
"idempotency_key": "refund:A-1042:2026-08-30", // same key โ same outcome, no double refund
"effect": "refund_issued", "amount_cents": 2500,
"status": "applied", "at": "2026-08-30T17:12:03Z"
}
Specimens in the wild: cookbook:patterns/agents/basic_workflows.ipynb โ the workflow patterns ยท cookbook:patterns/agents/orchestrator_workers.ipynb ยท cookbook:patterns/agents/evaluator_optimizer.ipynb ยท cookbook:tool_use/memory_demo/demo_helpers.py โ a real loop with tool dispatch.
Escalation design (scenario 1 territory)
A support agent needs to escalate the moment any of these shows up: confidence drops below a floor, the category falls outside its charter, a tool dependency goes down, the user flat-out asks for a human, or a gate blocks the action it wanted to take. Treat escalation as a first-class terminal path โ ticket + context handoff + an honest message to the user โ not some afterthought exception. And design the handoff packet (conversation summary, evidence gathered, actions attempted) as part of the architecture from the start, not bolted on later.
Evaluation of agents (bleeds into Domain 5)
Golden sets: fixed scenario suites with deterministic assertions on behavior (tools called, gates fired, terminal state) โ not on prose wording.
Negative controls: a config change that must flip a passing test red; green that can't be made red proves nothing.
Trajectory evaluation: judge the path (did it follow the runbook โ the documented step-by-step procedure it's supposed to follow โ avoid forbidden tools) not just the final answer.
LLM-as-judge: for higher independence, prefer a separately validated judge (often a different model/family); calibrate against human-labeled examples โ judge agreement is a signal, not proof.
Drill-down: choosing an architecture โ a worked decision tree
Is the task path known and repeatable? โ Workflow (chain/route/parallelize). Done.
Open-ended but single-focus (one context can hold it)? โ Single agent loop with a tight tool set.
Requires breadth (research many independent threads) or context exceeds one window? โ Orchestratorโworkers.
Quality-critical output with objective criteria? โ add evaluatorโoptimizer on the output stage.
Any step with real-world side effects (money, access, data mutation)? โ add HITL gate + idempotency regardless of pattern.
Drill-down: cost & latency levers in agentic systems
Model tiering per role: cheap/fast model for classification & routing; a frontier model (the most capable, most expensive tier) for reasoning; different family for judging.
Prompt caching for the static prefix (system prompt + tool definitions) โ the single biggest cost lever in loops, since every iteration resends the prefix.
Parallel tool execution when independent; batch API for offline/eval workloads.
Sessions, forking, and spawning โ the mechanics the exam names
The Task tool โ how subagents are actually born
Subagents are spawned through the Task tool โ and the exam tests the plumbing precisely:
A coordinator can only spawn subagents if its allowedTools includes "Task". No Task tool, no delegation โ a coordinator prompt that says "delegate to your research agents" with no Task tool silently becomes a monolith.
Subagents inherit nothing. A subagent starts with an isolated context โ it does not see the coordinator's conversation history or sibling results. Everything it needs (prior findings, web results, document extracts) must be passed explicitly in its prompt.
Parallel spawning = multiple Task calls in a single response. A coordinator that emits three Task tool calls in one turn runs three subagents concurrently; emitting them across separate turns serializes them. This one line is the difference between a 3ร latency win and none.
Each subagent type is configured via an AgentDefinition โ description (how the coordinator decides when to use it), system prompt, and tool restrictions.
When passing context between agents, use structured data that separates content from metadata (source URLs, document names, page numbers) so attribution survives the handoff.
๐ชค Trap: "the coordinator should share its memory with subagents" โ it can't. Context passing is explicit, by prompt, every time. Questions that assume automatic context inheritance are describing the wrong system.
Session management โ --resume, fork_session, and when to start fresh
--resume <session-name> continues a named prior conversation โ the investigation you parked on Friday.
fork_session creates independent branches from a shared baseline: analyze the codebase once, then fork twice to compare two refactoring strategies without either polluting the other.
The staleness rule: resume when prior context is still mostly valid; start a fresh session with an injected structured summary when the old tool results have gone stale (files changed, data moved). Resuming into stale tool results is worse than starting over โ the model trusts them.
If you resume after code changes, tell the session which files changed so it re-reads only those, instead of trusting stale reads or re-exploring everything.
๐ฏ "Two testing strategies from one shared analysis" โ fork_session. "Continue yesterday's migration" โ --resume + a note about what changed. "Tool results are three days old" โ fresh session + summary injection.
Practice this domain
๐ฏ Done with Domain 1? Prove it: Agentic Architecture (Q1โQ8) โ commit to an answer before revealing. Locally, your picks are captured with timestamps and scored per section, so weak spots surface on the practice page's comfort tiles.