Domain 1 is worth 27% of the score — roughly 16 questions out of 60. It's the heaviest of the five, and it's also where experienced candidates fail most: they know agents, but the exam doesn't test "can you build an agent". It tests whether you pick the right mechanism in a given production situation — and nine times out of ten, the trap is proposing a prompt instruction where the exam expects a programmatic mechanism.
This lesson follows the 7 task statements of the official exam guide v1.0 (July 2026) exactly. Each section gives the concept, the diagram, what you need to know, the reflex the exam expects, and the associated trap. At the end: the night-before checklist, five original corrected scenario questions, a quiz and the domain glossary. The two exam scenarios that lean most on this domain are the Customer Support Resolution Agent (scenario 1) and the Multi-Agent Research System (scenario 3) — keep them in mind, most questions are anchored there.
tool_use, tool_result).The domain map
Before the detail, the big picture. The seven task statements aren't independent: they form three layers. Base mechanics (loop, sessions), coordination (hub-and-spoke, subagents, decomposition), and guardrails (enforcement, hooks). The exam mixes layers within a single scenario; you must instantly know which layer a question belongs to.
1.1 — The agentic loop: the stop_reason contract
An agent is nothing more than a loop: you send Claude a request with tools, you look at why it stopped, you execute what it asks for, you send back the result, and you go again. The whole domain rests on this mechanism, and the exam tests it with surgical precision.
What you need to know
The cycle. Request → inspect stop_reason → execute requested tools → append tool_result blocks to history → new request. The thing that separates an agent from a plain call: the tool result is fed back into the conversation, which lets the model decide the next action in light of what it just learned.
The two values that matter. "tool_use" means "I need you to execute this": the loop continues. "end_turn" means "I'm done": the loop stops and you present the answer. Other values exist ("max_tokens", "stop_sequence", "refusal"), but the exam focuses on these two; treat "max_tokens" as an anomaly (truncated output), never as a normal end.
Model-driven decisions vs decision trees. An agent in the exam's sense is Claude choosing which tool to call next, based on context. A pre-wired decision tree ("first get_customer, then lookup_order, then…") is a workflow, not an agent. The exam will sometimes ask which of the two fits: the answer depends on how predictable the task is (see 1.6).
from anthropic import Anthropic
client = Anthropic()
def run_agent(system: str, tools: list, user_msg: str, max_turns: int = 40) -> str:
messages = [{"role": "user", "content": user_msg}]
for _ in range(max_turns): # safety net, NOT the stop condition
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=2048,
system=system, tools=tools, messages=messages,
)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn": # ← the ONLY normal end
return "".join(b.text for b in resp.content if b.type == "text")
if resp.stop_reason != "tool_use": # max_tokens, refusal… → anomaly
raise RuntimeError(f"unexpected stop_reason: {resp.stop_reason}")
results = []
for block in resp.content:
if block.type == "tool_use":
try:
out = execute_tool(block.name, block.input)
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": out})
except Exception as e: # return the error, don't break the loop
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": str(e), "is_error": True})
messages.append({"role": "user", "content": results}) # ← feed back
raise RuntimeError("Turn cap reached — treat as an incident")The three anti-patterns the exam loves
The official guide lists them explicitly. If you see one of them in an answer option, it's a distractor.
- Parsing natural language to detect the end. Looking for "I have completed" or "Here is the final result" in the text. Claude's phrasing varies; it's fragile by construction.
- An iteration cap as the primary stopping mechanism.
for i in range(10)without looking atstop_reason. The cap is a safety net against infinite loops, not a functional stop condition. - Checking for text content in the response. "If there's a text block, it's done." Wrong: a response can contain text and a
tool_use("Let me check the order…" followed by the call).
stop_reason. Same logic for "cap at N turns" presented as the fix for an agent that won't stop — the real question is why it isn't returning end_turn.stop_reason == "tool_use", stop on "end_turn", feed every tool result back into history with its tool_use_id. Everything else is a distractor.1.2 — Hub-and-spoke: the coordinator at the center
As soon as a system has several specialized agents, the question becomes: who talks to whom? The exam has a single answer and applies it everywhere: the coordinator at the center, subagents as spokes, never direct communication between spokes.
What you need to know
The coordinator's role. It decomposes the task, delegates, aggregates results, handles errors, and — importantly — decides which subagents to invoke based on query complexity. A coordinator that systematically pushes every request through all four subagents in the same order is a pipeline in disguise; the exam expects dynamic selection.
Isolated context. A subagent doesn't see the coordinator's history. It sees only what's put in its prompt. Corollary: if the synthesis subagent needs the search results, it's up to the coordinator to pass them, in full, in the prompt.
The overly narrow decomposition risk. This is question 7 of the official guide, and it's emblematic: a research system on "the impact of AI on creative industries" only produces results about visual arts. All subagents did their job. The culprit is the coordinator, which split the topic into "digital art, graphic design, photography" — forgetting music, writing, film. Exam reflex: when subagents succeeded but coverage is incomplete, look at the decomposition, not the execution.
Partitioning scope. To keep two subagents from doing the same work, you assign them distinct subtopics or distinct source types (academic / press / data). That's partitioning, not redundancy.
The iterative refinement loop. The coordinator evaluates the synthesis, spots gaps, re-delegates targeted queries to the search and analysis subagents, then re-runs synthesis — until coverage is sufficient. It's not a single-pass pipeline.
1.3 — Subagents: Task, allowedTools, explicit context
This section is about the configuration details of the Claude Agent SDK. It's quick to learn and pays off a lot: the questions are factual.
What you need to know
The Task tool. It's the mechanism for spawning a subagent in the Claude Agent SDK. For a coordinator to invoke subagents, its allowedTools must include "Task". If a coordinator "never delegates" despite a prompt telling it to, the first thing to check is this configuration.
Context is explicit, always. The subagent doesn't inherit parent context and has no memory between invocations. If the synthesis subagent must work on the web search and document analysis results, those results must be included in full in its prompt. Not a pointer, not "as seen earlier": the content.
AgentDefinition. Each subagent type is configured with a description (which the coordinator uses to choose), a system prompt, and tool restrictions. A synthesis subagent doesn't need web search; giving it every tool degrades selection reliability (also a Domain 2 theme).
Content vs metadata. When passing context between agents, separate the two in a structured format: the finding's text on one side, the source URL, document name, page on the other. Otherwise attribution is lost at synthesis (picked up again in Domain 5).
Parallelism in a single turn. To launch three subagents in parallel, the coordinator emits three Task calls in the same response, not one per turn. One call per turn = sequential execution = triple latency.
Goals, not procedures. A coordinator's prompt to a subagent specifies the goal and quality criteria ("cover the five sectors, cite sources less than two years old, flag contradictory statistics"), not a step-by-step procedure. The subagent must be able to adapt to what it discovers.
Fork. fork_session creates several independent branches from a shared analysis, to explore divergent approaches without redoing the baseline (detailed in 1.7).
# Conceptual sketch (Claude Agent SDK) — parallel launch of two subagents
# The coordinator emits TWO Task calls in a single response.
coordinator = AgentDefinition(
description="Coordinates research, aggregates, checks coverage",
prompt=COORD_SYSTEM,
tools=["Task"], # without "Task", no delegation is possible
)
web_search = AgentDefinition(
description="Searches recent web sources on a precise subtopic",
prompt=WEB_SYSTEM, tools=["WebSearch", "WebFetch"], # minimal scope
)
doc_analysis = AgentDefinition(
description="Analyzes provided documents and extracts sourced facts",
prompt=DOC_SYSTEM, tools=["Read"],
)
# Context passed EXPLICITLY to the synthesis subagent (no inheritance):
synthesis_prompt = f"""
Goal: report on {topic}. Criteria: cover {sectors}, cite dated sources.
== Web search findings (JSON, claim/source/date) ==
{json.dumps(web_findings, ensure_ascii=False)}
== Document analysis findings ==
{json.dumps(doc_findings, ensure_ascii=False)}
"""1.4 — Enforcement and handoff: when the prompt isn't enough
This is the philosophical core of the domain, and question 1 of the official guide is its archetype: in 12% of cases, the agent skips get_customer and calls lookup_order with only the name the customer stated. Result: misidentified accounts, wrong refunds. What do you do?
What you need to know
Two regimes. Prompt guidance (instructions, few-shot) is probabilistic: it improves rates, it guarantees nothing. Programmatic enforcement (prerequisite gates, hooks) is deterministic: the non-compliant action is physically impossible. The choice hinges on a single question: what happens if it fails one time in a hundred? A slightly curt tone, you'll survive. A refund to the wrong account, no.
The prerequisite gate. You block downstream calls (lookup_order, process_refund) until an upstream call (get_customer) has returned a verified identifier. The block returns an explicit error tool_result; the agent corrects itself and continues. Note that the option "classify the request and enable only the relevant tools" (option D of question 1) solves a tool availability problem, not an ordering one — it's the subtlest distractor.
The structured handoff. When the agent escalates to a human mid-process, the human has no access to the transcript. The handoff summary must therefore be structured and self-contained: customer ID, identified root cause, amount at stake, recommended action, what was already attempted. "The customer is unhappy, see the conversation" is not a handoff.
Multi-concern requests. "My parcel arrived broken, AND I see two charges, AND I want to change my address." The expected pattern: decompose into distinct items, investigate each in parallel using shared context (same customer, same session), then synthesize a unified answer. Not handle the first item and forget the other two, not handle them in series with three customer round-trips.
# Prerequisite gate — programmatic enforcement inside the tool loop
REQUIRES_VERIFIED_CUSTOMER = {"lookup_order", "process_refund", "update_address"}
def execute_tool(name: str, args: dict, state: dict):
if name in REQUIRES_VERIFIED_CUSTOMER and not state.get("verified_customer_id"):
# The call is not executed. The agent gets an actionable error.
return {"error": "PREREQUISITE_MISSING",
"message": "Call get_customer and obtain a verified ID before this operation.",
"retryable": True}
if name == "get_customer":
result = backend.get_customer(**args)
if result.get("verified"):
state["verified_customer_id"] = result["customer_id"]
return result
return backend.call(name, args)
# Structured handoff to a human — self-contained, not a pointer to the transcript
def build_handoff(state, analysis) -> dict:
return {
"customer_id": state["verified_customer_id"],
"root_cause": analysis["root_cause"],
"amount_at_stake_eur": analysis["amount"],
"recommended_action": analysis["recommendation"],
"already_attempted": state["actions_log"],
"policy_gap": analysis.get("policy_gap"), # why the agent couldn't conclude
}1.5 — SDK hooks: intercept before and after
Hooks are the concrete tooling for enforcement. The Claude Agent SDK exposes interception points around every tool call; the exam tests two precise uses.
What you need to know
The call interception hook (before). It examines the call the model wants to make and can block it according to a business rule — the guide's canonical example is block any process_refund above $500 and redirect to human escalation. It's deterministic: the $800 refund never goes out, whatever the model decided.
The PostToolUse hook (after). It transforms a tool's result before the model reads it. Typical case: three MCP servers return dates as Unix timestamps, ISO 8601, and "12/03/2026", and statuses sometimes numeric, sometimes textual. Rather than asking the model to juggle (and get it wrong), you normalize in the hook. The model always sees the same format.
Hooks vs prompt. Same logic as in 1.4: hooks provide guarantees, the prompt provides probabilities. When a business rule "must" be respected, it's a hook.
# Conceptual hooks (Claude Agent SDK) — simplified names and signatures
from datetime import datetime, timezone
def pre_tool_use(tool_name: str, tool_input: dict, ctx):
"""Interception BEFORE execution: enforcing a business rule."""
if tool_name == "process_refund" and tool_input.get("amount_eur", 0) > 500:
ctx.escalate(reason="refund_over_threshold", payload=tool_input)
return {"block": True,
"message": "Refund > €500: transferred to a human agent."}
return {"block": False}
STATUS_MAP = {1: "pending", 2: "processing", 3: "shipped", 4: "delivered"}
def post_tool_use(tool_name: str, result: dict, ctx) -> dict:
"""Interception AFTER execution: normalization before the model reads it."""
if isinstance(result.get("created_at"), int): # Unix ts → ISO
result["created_at"] = datetime.fromtimestamp(
result["created_at"], tz=timezone.utc).isoformat()
if isinstance(result.get("status"), int): # code → label
result["status"] = STATUS_MAP.get(result["status"], "unknown")
return resultPostToolUse case. And mind the direction: PostToolUse acts on the result (after), blocking a call acts on the request (before). Confusing the two is a classic error.1.6 — Task decomposition: fixed chain or adaptive plan
Here the exam doesn't test "can you split a task" but "can you choose between two splitting strategies depending on the nature of the work".
What you need to know
Prompt chaining. A fixed sequence of steps, each feeding the next. Ideal for predictable multi-aspect work: a code review passes security, then performance, then readability — always in that order, always the same passes.
Dynamic decomposition. The plan is built as you go. "Add comprehensive tests to a legacy codebase" can't be planned upfront: you first map the structure, identify high-impact areas, produce a prioritized plan, and that plan adapts when you discover an unexpected dependency.
The large-review case. This is question 12 of the official guide: a 14-file PR, a single-pass review, and inconsistent results (detailed feedback on some files, superficial on others, a pattern flagged here and approved there). Cause: attention dilution. Expected solution: per-file passes for local issues, then a separate integration pass for cross-file flow. The distractors: "a model with more context" (context size doesn't fix attention quality), "require smaller PRs" (shifts the problem), "three passes and majority vote" (suppresses detection of real intermittent bugs).
Which decomposition strategy?
| Prompt chaining | Dynamic decomposition | |
|---|---|---|
| Steps known in advance | Yes, identical on every run | No, generated by discoveries |
| Typical case | Multi-aspect review, staged extraction | Legacy code exploration, open investigation |
| Predictability / cost | High, bounded cost | Variable, cap needed |
| Coverage of the unknown | Blind to surprises | Adapts to what is found |
| Large multi-file review | Per file + integration pass | Unnecessary if files are known |
| Exam signal | "predictable", "same aspects", "each file" | "open-ended", "legacy", "unknown", "based on what's found" |
1.7 — Sessions: resume, fork, or start over
Last task statement, oriented toward Claude Code and the Agent SDK. Three mechanisms, and above all: knowing when not to resume.
What you need to know
Named resumption. --resume <session-name> continues a specific conversation. You name your investigation sessions (payments-audit, orm-migration) so you can come back to them from one workday to the next.
Flag changes. If you resume a session after modifying code, tell the agent: "files X and Y changed since your analysis". It re-analyzes in a targeted way instead of re-exploring everything — or worse, reasoning on a stale version without knowing.
Stale results → fresh session. If most of the old session's tool results are no longer valid (large refactor, changed dependencies), resuming means reasoning on falsehoods. The right answer is to start a fresh session with a structured summary of the still-valid conclusions, injected as initial context. More reliable, and fewer tokens.
fork_session. From a shared baseline analysis (for instance, a codebase map), you create two independent branches to explore two approaches (two testing strategies, two refactoring plans) without redoing the analysis and without the branches contaminating each other.
--resume while informing the agent of the modified files is the answer — not a fresh session that redoes everything.Cross-cutting traps of Domain 1
Beyond the per-section traps, four reading reflexes that hold for every question in the domain.
- Proportion. The exam favors the "proportionate" answer: the low-effort first step that addresses the root cause. A separate ML classifier, a routing layer, a bigger model are almost always oversized when a configuration fix or a gate is enough.
- Root cause, not symptom. When logs are given in the prompt, they point at the culprit. Read them before the options.
- Guarantee vs probability. If the scenario mentions a real consequence (money, data, compliance), a probabilistic solution is eliminated outright.
- Separation of roles. Any option that gives an agent tools outside its role, or has two subagents communicate directly, violates the expected pattern.
Night-before checklist
stop_reason == "tool_use", stop on "end_turn"; never text parsing or a counter as the primary condition.
- Every tool_use gets a tool_result with its tool_use_id, fed back into history — even on error.
- Hub-and-spoke: everything goes through the coordinator; no direct communication between subagents.
- Subagents = isolated context, no inheritance, no memory between invocations → pass the complete findings in the prompt.
- The coordinator's allowedTools must contain "Task".
- Parallelism = several Task calls in one response.
- Incomplete coverage + correct subagents = coordinator's decomposition too narrow.
- Refinement loop: evaluate → targeted re-delegation → re-synthesize.
- Business rule with consequences = gate or hook, never prompt alone.
- Interception hook = before (block, redirect); PostToolUse = after (normalize).
- Human handoff = self-contained structured summary (customer ID, root cause, amount, action, attempts).
- Multi-concern = decompose, investigate in parallel, synthesize.
- Prompt chaining if steps are known; dynamic decomposition if open-ended exploration.
- Large review = per-file passes + integration pass (attention dilution).
- --resume if context valid (and flag modified files); fresh session + summary if stale; fork_session to compare.Five original scenario questions, corrected
These questions are written by nAIvigate in the spirit of the exam. They reproduce no real item (exam content is confidential). Hide the corrections, answer, then compare.
Question 1 — Support scenario. Your support agent uses a loop that stops as soon as a text block appears in the response. In production, 8% of sessions end with a reply like "Let me check your order…" without the check ever happening. What's the most correct fix?
A. Add to the prompt: "Never produce text before calling all necessary tools." B. Continue the loop while stop_reason == "tool_use" and only stop on "end_turn", regardless of text content. C. Raise the iteration cap from 5 to 15. D. Detect the phrase "Let me check" and force an extra turn.
📚Answer Q1
B. A response can contain text and a tool_use; checking for text is one of the three explicitly listed anti-patterns. A is probabilistic. C doesn't address the stop condition. D is natural-language parsing — the anti-pattern par excellence.
Question 2 — Research scenario. Your coordinator launches the web search, document analysis, synthesis and report subagents, in that order, on every request — including "what's the publication date of report X?". Average latency is 4 minutes. What should you change first?
A. Parallelize the four subagents. B. Have the coordinator analyze the request's complexity and invoke only the necessary subagents. C. Replace the synthesis subagent with a direct API call. D. Reduce the number of results returned by web search.
📚Answer Q2
B. The expected pattern is dynamic subagent selection based on complexity, not a systematic pipeline. A parallelizes unnecessary work. C and D optimize steps that shouldn't have happened.
Question 3 — Support scenario. Policy forbids any refund above €300 without human validation. The prompt states it in bold. An audit finds 4 refunds of €350 to €600 processed without validation in one month. Which measure guarantees compliance?
A. Rewrite the instruction in capitals and repeat it at the end of the system prompt. B. Add five few-shot examples of escalation for high amounts. C. An interception hook that blocks process_refund when amount > 300 and triggers human escalation. D. Ask the agent to self-assess on a confidence scale before every refund.
📚Answer Q3
C. Financial consequence + the word "guarantees" = deterministic enforcement. A and B remain probabilistic. D relies on self-assessment, which is poorly calibrated (a Domain 5 theme).
Question 4 — Research scenario. The synthesis subagent produces reports that ignore the internal documents that the analysis subagent did analyze. Logs show the analysis ran correctly and returned 14 sourced facts to the coordinator. Most likely cause?
A. The synthesis subagent's system prompt is too short. B. The coordinator didn't include the 14 facts in the prompt sent to the synthesis subagent. C. The analysis subagent should call the synthesis subagent directly. D. The synthesis subagent needs the Read tool to re-read the documents.
📚Answer Q4
B. Subagents only see their prompt; the coordinator's results aren't inherited. C violates hub-and-spoke. D gives an out-of-role tool and redoes the work. A can't make absent data appear.
Question 5 — Developer productivity scenario. You have a named session auth-audit where the agent mapped the authentication module. Since then, the team has refactored 70% of that module. You now want to generate tests. Best approach?
A. --resume auth-audit and request test generation. B. --resume auth-audit noting that "a few files changed". C. Start a fresh session injecting a structured summary of the still-valid conclusions (module boundaries, external dependencies, conventions). D. fork_session from auth-audit to test two strategies.
📚Answer Q5
C. 70% refactored = stale tool results; resuming would mean reasoning on falsehoods. B would be right if changes were limited. D would fork a stale baseline.
Validation quiz
What is the only legitimate end-of-loop signal for an agentic loop?
📚Domain 1 glossary (expand)
Agentic loop — Cycle request → inspect stop_reason → execute tools → feed results back → new request, until end_turn.
stop_reason — API response field indicating why the model stopped: tool_use (continue), end_turn (done), max_tokens (truncated, anomaly), among others.
tool_use / tool_result — Block emitted by the model to request a tool / block returned by the application with the result, linked by tool_use_id.
Model-driven decision — The model itself picks the next tool based on context, as opposed to a pre-wired decision tree.
Hub-and-spoke — Multi-agent architecture where a central coordinator handles all communication, routing and errors; subagents don't talk to each other.
Coordinator — Agent that decomposes, delegates, aggregates, handles errors and dynamically selects which subagents to invoke.
Subagent — Specialized agent with isolated context, spawned by the coordinator via the Task tool, with no parent history inheritance and no memory between invocations.
Task (tool) — Subagent spawning mechanism in the Claude Agent SDK; must be in the coordinator's allowedTools.
allowedTools — List of tools an agent may use; used to restrict each subagent to its role.
AgentDefinition — Configuration of a subagent type: description, system prompt, tool restrictions.
Overly narrow decomposition — Coordinator error of splitting a broad topic into subtasks covering only part of the scope.
Partitioning — Splitting scope between subagents (distinct subtopics or source types) to avoid duplication.
Refinement loop — The coordinator evaluates the synthesis, re-delegates targeted queries on the gaps, then re-runs synthesis.
Programmatic enforcement — Rule imposed by code (gate, hook) with a deterministic guarantee, as opposed to prompt guidance (probabilistic).
Prerequisite gate — Blocking downstream tool calls until an upstream call has produced the required result (e.g. verified customer ID).
Structured handoff — Self-contained transfer summary to a human: customer ID, root cause, amount, recommended action, attempts.
Hook — SDK interception point around a tool call; before (block, redirect) or after (PostToolUse: transform the result).
PostToolUse — Hook run after a tool, before the model reads the result; used to normalize heterogeneous formats.
Prompt chaining — Decomposition into a fixed sequence of steps known in advance, each feeding the next.
Dynamic decomposition — Plan built and updated as discoveries are made, for open-ended tasks.
Attention dilution — Degradation of analysis quality when too many elements are processed in a single pass; fixed by local passes + an integration pass.
--resume — Resuming a named session in Claude Code; use when the prior context is still mostly valid.
fork_session — Creating independent branches from a shared session, to explore divergent approaches.
Stale results — Tool results that no longer reflect the real state (modified code); require a fresh session with a structured summary.
Going further
The logical next step is Domain 2 — Tool Design & MCP (18%), which picks up the questions of per-subagent tools, descriptions and structured errors. Isolated context and source attribution questions return in Domain 5. For the complete mechanics of Claude agents in production, our course on agentic systems architecture and the guide on setting up communicating Claude agents give the full code.
If you want to certify a whole team — or move from theoretical preparation to a really deployed multi-agent system, with its gates, hooks and observability — that's precisely what nAIvigate Studio does in a Sprint.