Skip to lesson

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 condition

Only 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_reasonMeaningApplication decision
max_tokensGeneration reached the request’s max_tokens limitTreat output as incomplete; decide whether a higher allowance or a continuation fits the job budget.
stop_sequenceGeneration encountered a configured stop_sequences entryInspect stop_sequence and decide whether that delimiter satisfies the output contract.
pause_turnServer-tool execution reached its per-request iteration limitContinue with the returned assistant content preserved as-is, within an application continuation budget.
refusalClaude declined to generate the requested responseRead stop_details for the policy category; record a refusal outcome, or retry on a supported fallback model if application policy permits.
model_context_window_exceededGeneration reached the model’s context limitTreat 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_turn describes server-side work.
  • Treating max_tokens as equivalent to end_turn.
  • Using a default branch that accepts every unfamiliar stop reason.
  • Raising max_tokens to solve a context-window limit.
  • Ending a streaming job after its first text block.

Where the exam guide differs

Note:

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

References