Domain 1 is the largest slice of the exam (27%), and this chapter is its floor: every later topic — subagents, workflows, hooks, session state — is a variation on the loop defined here. The exam tests whether you can read the loop’s control flow, not whether you can recite an SDK signature. We build the loop from the definition of an agent, trace it end to end with a worked example, name the stop_reason values that branch it, handle the error and parallel result cases, and fix the termination contract an architect owns.

What an agent is

Start with the definition, because the loop falls out of it. Anthropic’s Building Effective Agents draws the line that organizes this entire domain: “Workflows are systems where LLMs and tools are orchestrated through predefined code paths. Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks.” [Official] Building effective agents · Erik Schluntz and Barry Zhang (2024)T1-official original A workflow runs on rails you laid down in code; an agent decides its own next step at runtime.

Operationally, that autonomy has a simple shape: “Agents are typically just LLMs using tools based on environmental feedback in a loop.” [Official] Building effective agents · Erik Schluntz and Barry Zhang (2024)T1-official original The model proposes an action, your code runs it, the result of running it becomes the model’s next input, and the model decides again. That feedback cycle — act, observe, decide — is the agent. Everything else in Domain 1 is a way of shaping, bounding, or distributing it.

The loop is a control structure

Because the agent is the loop, the loop is the thing you reason about — and it has exactly one branch condition. At the Messages API level, Claude returns stop_reason: "tool_use" together with one or more tool_use blocks; your application executes each call and returns tool_result blocks on the next user turn. [Official] Tool use with Claude · AnthropicT1-official original The loop repeats that exchange until Claude responds without a tool call.

The architectural point is that the model decides what happens next, but your code decides whether it gets to. Tool access is “one of the highest-leverage primitives you can give an agent,” [Official] Tool use with Claude · AnthropicT1-official original and the loop is where that leverage is either contained or left unbounded. Owning the loop — not authoring any single tool — is the orchestration discipline the rest of Domain 1 elaborates.

A turn is one tool-use round-trip

The word turn has a precise meaning, and the exam leans on it. A turn is “one round trip inside the loop: Claude produces output that includes tool calls, the SDK executes those tools, and the results feed back to Claude automatically … Turns continue until Claude produces output with no tool calls.” [Official] How the agent loop works · AnthropicT1-official original The Agent SDK embeds this loop for you — it ships “the same tools, agent loop, and context management that power Claude Code” [Official] Agent SDK overview · AnthropicT1-official original — so at the SDK level you observe messages, not the raw branch.

The consequence that trips candidates: a text-only final response is not a turn. A four-message session is three tool-use turns plus one final text answer, so max_turns=2 would stop before that final step. [Official] How the agent loop works · AnthropicT1-official original Size a turn budget to the tool calls a task needs, not to the messages you expect to see.

Handling tool results: errors and parallel calls

Step 4 of the round-trip hides two cases the exam specifically tests, because both are where a hand-written loop goes wrong.

A failed tool does not raise — it reports. When your handler hits an error (the file is missing, the command exits non-zero, the API times out), you do not throw out of the loop. You return a normal tool_result block with is_error: true and the error text as its content. [Official] Tool use with Claude · AnthropicT1-official original The model sees the failure and adapts — retries with a corrected argument, tries a different tool, or explains the blocker — exactly as it would read any other result. Raising an exception instead severs the loop and throws away the model’s ability to recover.

Parallel calls must be answered together. When a single response contains more than one tool_use block, the API requires every corresponding tool_result in the next user message — you cannot answer one tool now and defer the other to a later turn. Execute them (concurrently when they are read-only and independent; serially when one mutates state another reads), collect all results, and send them as one batch. The mechanics of when to parallelize live in D2.3 — for the loop, the rule to hold is: all of a turn’s results return together, keyed by tool_use_id.

stop_reason is the branch

Because stop_reason is the loop’s branch condition, recognizing each value — and its loop consequence — is core exam material. On a ResultMessage, stop_reason carries the value from the model’s last response. [Official] How the agent loop works · AnthropicT1-official original

stop_reasonWhat it meansLoop consequence
tool_useThe response contains tool callsContinue — execute tools, return tool_result, request again
end_turnThe model finished naturally, no tool callsStop — deliver the final result
max_tokensOutput hit the token budget mid-responseStop, but the answer is truncated — you may need to continue
refusalThe model declined to generateStop — handle as a non-answer, not a result

Termination is the architect’s safety contract

A model-driven loop that can run forever is a production incident waiting to happen, so the architect supplies the stop conditions the model cannot. The SDK exposes two budgets: max_turns (a turn count) and max_budget_usd (a client-side cost estimate). Hitting either ends the loop and sets ResultMessage.subtype to error_max_turns or error_max_budget_usd. [Official] How the agent loop works · AnthropicT1-official original

The subtype is the termination indicator, and it gates whether .result is even populated:

subtypeMeaning.result?
successNormal finishyes
error_max_turnsHit max_turnsno
error_max_budget_usdHit max_budget_usdno
error_during_executionAPI / cancellation errorno
error_max_structured_output_retriesJSON-Schema validation failed past the retry limitno

Where Claude Code’s loop sits

Claude Code is one concrete harness around this loop. Its documentation states the architecture plainly: “The agentic loop is powered by two components: models that reason and tools that act.” [Official] How Claude Code works · AnthropicT1-official original The same source makes the dependency explicit — “Tools are what make Claude Code agentic. Without tools, Claude can only respond with text” [Official] How Claude Code works · AnthropicT1-official original — and the SDK’s account agrees that “Tools are the primary building blocks of execution for your agent.” [Official] Building agents with the Claude Agent SDK · Thariq Shihipar et al. (2025)T1-official original

For the exam, treat the loop in this chapter as the inner cycle. A long-running harness wraps it in an outer cycle that carries state across many context windows — but the branch condition, the turn model, and the termination contract are identical at every scale. Master the inner loop and the rest of Domain 1 is composition.

Practice

Exercise solutions

Solution ↑ Exercise

Three turns. Turns count tool-use round-trips: Read, Grep, Edit are turns 1–3; the final text summary is not a turn. The final response’s stop_reason is end_turn (no tool call). The smallest budget that still finishes is max_turns = 3 — it permits the three tool-use turns, and the free final text answer follows. max_turns = 2 would stop before the Edit.

Solution ↑ Exercise

B — end_turn. It means the model finished naturally with no tool calls, so the text response is the deliverable. A (tool_use) is the continue branch — there is more loop to run, not a final answer. C (max_tokens) stops the response but the answer is truncated mid-output, so it usually needs a continuation before it is usable. D (refusal) is a non-answer to be handled as a declined request, not delivered as a result. The discriminating idea: only end_turn is both terminal and complete.

Solution ↑ Exercise

A defensible policy: “Set max_turns to the tool calls a normal fix needs plus headroom (say 15), and max_budget_usd as a hard cost ceiling, because the re-reading loop fails by count and by spend and either bound should stop it. My handler checks ResultMessage.subtype first: on success I read .result; on any error_* subtype I surface the exhaustion (and the partial transcript) rather than printing an empty .result.” The exact field checked first is subtype — never .result before it.

Exam essentials

Further reading

The design rationale for the inner/outer split — why owning the loop boundary is what turns a model into a harness — is developed at length in the Agentic Systems Design book, Chapter 1, Agent = Model + Harness. It is optional depth, not required for the exam; this chapter is self-contained.