AnthropicClaude Certified Architect – Foundations2026-101.1 Design and implement agentic loops for autonomous task execution
Drive execution from the stop reason
Completed by the knowledge check
Learning objective
Drive the Messages API loop from stop_reason: continue on tool_use, finish on end_turn, and handle other stopping conditions explicitly.
Core idea
For an application-owned agent, the Messages API response is a control signal as well as content. Read stop_reason before deciding what the application does next. A response with tool_use requests work from your tool executor; end_turn ends the assistant’s turn. Other values describe different boundaries and need separate handling.
An HTTP success does not mean the user’s task succeeded. A truncated response, a refusal, and a completed answer can all arrive as successful API responses. Likewise, a completed assistant turn can ask the user for information rather than resolve the original request. Keep API control flow and business acceptance separate.
This lesson owns the response-state decision. See 1.1.2 for preserving messages and matching tool results, and 1.1.4 for why text and iteration counts cannot replace that decision.
How it works
Route the ordinary client-tool cycle
Send the conversation in messages and your tool definitions in tools. For client tools, Claude returns one or more tool_use blocks with stop_reason: "tool_use". Your application dispatches those calls, adds their results to the conversation, and sends another Messages API request. The next response can request more tools or finish the turn.
When stop_reason is end_turn, stop this automatic client-tool cycle. Deliver or validate the answer according to the application’s result contract. If the answer asks which order the customer means, the assistant turn is complete while the support case remains open. The application waits for a user reply rather than repeatedly asking Claude the same question.
Use an explicit branch for every documented response state. The ordinary state transition can be expressed without depending on response wording:
tool_use -> resolve client calls, append results, request again
pause_turn -> send the assistant content back unchanged (server tools only)
end_turn -> end the assistant turn, evaluate the business outcome
otherwise -> enter the handler for that specific stopping conditionOnly two values send the loop round again as a matter of routine: tool_use for client tools, and pause_turn when the request uses server tools. Only end_turn reports that Claude finished its response naturally; every other value is a boundary its handler decides, not a finish.
An unrecognized value should enter a controlled unsupported-state path, with the response retained for diagnosis. A catch-all that marks every non-tool response successful hides changes in response behavior and turns known failures into accepted answers.
Handle interruptions as their own states
These values require decisions beyond the ordinary client-tool cycle:
stop_reason | Meaning | Application decision |
|---|---|---|
max_tokens | Generation reached the request’s max_tokens limit | Treat output as incomplete; decide whether a higher allowance or a continuation fits the job budget. |
stop_sequence | Generation encountered a configured stop_sequences entry | Inspect stop_sequence and decide whether that delimiter satisfies the output contract. |
pause_turn | Server-tool execution reached its per-request iteration limit | Continue with the returned assistant content preserved as-is, within an application continuation budget. |
refusal | Claude declined to generate the requested response | Read stop_details for the policy category; record a refusal outcome, or retry on a supported fallback model if application policy permits. |
model_context_window_exceeded | Generation reached the model’s context limit | Treat output as truncated and repair the context or result plan before accepting it. |
For max_tokens, increasing the output allowance addresses an output limit; it does not repair a context-window limit. A cut-off explanation and a cut-off tool input are both incomplete. If the last content block is an incomplete tool_use, retry the request with a higher max_tokens to obtain the full call; do not continue from or execute the partial block.
The context-limit value has a support boundary. Anthropic documents it in the client SDKs’ beta namespace. The API returns it without a beta header on Sonnet 4.5 and subsequent models; Sonnet 4.5 itself is deprecated. Earlier models require the anthropic-beta: model-context-window-exceeded-2025-08-26 header to enable that value. Match response typing and header behavior to the deployed model rather than assuming the value is exposed identically everywhere.
Separate server tools and streaming
Server tools run on Anthropic’s infrastructure. A pause_turn response is not a request to execute those server tools locally. Anthropic documents a default server-side limit of 10 iterations per request; when reached, pass the response back as-is to continue. A waiting client tool_use instead produces tool_use, so it follows the client-result path.
A response can also mix client calls with an unresolved server_tool_use; see 1.1.2 for the message constraints on that mixed case.
For streaming, stop_reason is null in message_start and appears in message_delta. Receiving text is progress, not the terminal response-state decision. Accumulate the response and use its completed control information before scheduling the next loop step. Handle a transport failure separately if the stream fails before completion.
Key distinctions and trade-offs
Response boundary versus request error: stop_reason describes why generation stopped in a successful response. A failed request needs error handling, not a fabricated stop reason. Keep request retries outside the response-state switch.
Turn completion versus task completion: end_turn ends model generation for that turn. Application validation decides whether the result meets the customer’s goal. Neither outcome implies the other automatically.
Continuation versus restart: Continuing a paused server-tool turn preserves returned content. Restarting from the original user request can discard work already represented in the conversation. Choose deliberately when recovery really requires a fresh attempt.
Explicit routing adds branches, but gives each outcome an observable meaning. A generic retry loop is shorter and can still be wrong: it may repeat refusals, keep a finished turn running, or accept truncated text without noticing.
Architecture / decision scenario
A customer support agent checks an order and determines whether it can explain a missing delivery. Its first response has stop_reason: "tool_use"; the application resolves the requested lookup and returns the result. The next response requests a second lookup, so the application continues rather than assuming one tool round is enough.
If the explanation reaches max_tokens, the case records an incomplete answer and considers a bounded continuation. If a configured delimiter triggers stop_sequence, the handler checks that delimiter against the expected response format. If a server-tool search pauses with pause_turn, the handler resubmits the preserved assistant content instead of invoking a local search implementation.
For a refusal, the handler reads stop_details to identify the policy category and records a refusal outcome or attempts a supported fallback permitted by application policy. A context-window stop becomes incomplete work that needs a smaller context or revised response plan. Neither becomes a delivered resolution merely because the HTTP request succeeded.
When Claude returns end_turn, the loop ends. The application then checks whether the response explains the delivery status or requests missing information. In the latter case, it waits for the customer. Logs capture the actual stop reason and the separate case outcome, so a high rate of completed turns cannot conceal unresolved cases.
Common exam traps
- Treating every successful HTTP response as a successful task.
- Executing tools when
pause_turndescribes server-side work. - Treating
max_tokensas equivalent toend_turn. - Using a default branch that accepts every unfamiliar stop reason.
- Raising
max_tokensto solve a context-window limit. - Ending a streaming job after its first text block.
Where the exam guide differs
The exam guide frames the loop as binary: it “continues when stop_reason is “tool_use” and terminates when stop_reason is “end_turn”.” The Messages API documents five more values. One of them, pause_turn, also continues the loop when server tools are in use; the other four need their own handlers rather than either branch. In an exam item, choose the option that drives control flow from stop_reason, continuing on tool_use and finishing on end_turn. Read the guide’s two values as the ordinary client-tool cycle, not as the full list a production loop handles.
What to remember
Use stop_reason to route the next operation. Continue client execution on tool_use, end the assistant turn on end_turn, and assign explicit recovery or terminal outcomes to other states. Validate business success after the API turn ends.
Knowledge check
A support agent’s request includes Anthropic’s server-side web search tool alongside two client tools. A response arrives with stop_reason: "pause_turn" and a server_tool_use block that has no result yet. What should the application do next?
tool_resultmax_tokens value and wait for the complete searchpause_turn means a server-tool loop reached its per-request iteration limit on Anthropic’s side, and the documented continuation is to send the response back as-is. Server tools are not executed locally, so a locally produced tool_result answers a call that was never the application’s to run; the pause is neither a finished turn nor an output-length limit.A response stops with stop_reason: "max_tokens", and its last content block is a tool_use for update_ticket whose input is cut off partway through. What should the loop do?
update_ticket with the input fields that did arrive, then continue the looptool_result with is_error: true reporting that the call input was truncatedmax_tokens value to obtain the complete tool callmax_tokens is incomplete output, and Anthropic documents retrying with a higher max_tokens to get the full tool use. Executing a partial input risks a wrong change to the ticket, and an error result answers a call Claude never finished making.A loop is written as if stop_reason == "tool_use": run the tools; else: mark the case resolved. The dashboard reports nearly every case resolved, yet customers report answers that end mid-sentence. Which change addresses the cause?
max_tokens on every request to a value large enough for the longest expected answertool_use until a response arrives with end_turnmax_tokens truncation and refusals included — into an accepted answer, so the dashboard counts failures as successes. A larger max_tokens treats one symptom while the default branch keeps accepting the next unhandled state, and blind retries repeat refusals; an explicit branch per state gives each outcome its own meaning.A support customer has two open orders. Claude’s response has stop_reason: "end_turn" and asks which of the two orders the customer means. What should the application do?
end_turn ends the assistant turn, not the customer’s task: the application’s own validation decides that the case is still open and waiting for information only the customer has. Asking Claude again either repeats the question or replaces the customer’s answer with a guess.References
- Anthropic, Stop reasons and fallback
- Anthropic, Tool use with Claude
- Anthropic, Handle tool calls
- Anthropic, Claude Certified Architect – Foundations Exam Guide