CertSafari
    CLAUDE-CERTIFIED-ARCHITECT-FOUNDATIONS-CCAR-F · Lessons

    Domain 1 · Lesson 1/30

    Agentic Loop Lifecycle: stop_reason, Tool Results and Conversation History

    Design and implement agentic loops for autonomous task execution

    14 min read
    3.86% of exam
    6 sources
    Published 28 Sep 2026
    Docs as of 26 Sep 2026

    What you will be able to do

    • Trace one iteration of an agentic loop: request, stop_reason check, tool execution, results returned
    • Write loop control flow that continues on "tool_use" and terminates on "end_turn"
    • Append the assistant's tool_use blocks and the matching tool_result blocks to history so the next iteration can reason over them
    • Distinguish model-driven decision-making, where Claude reasons about which tool to call next from context, from a pre-configured decision tree or fixed tool sequence in your code
    • Recognise and avoid termination anti-patterns: parsing natural-language signals, using an arbitrary iteration cap as the primary stop, or treating assistant text as a completion indicator

    Key concept

    stop_reason-keyed agentic loop — A loop in your application that keeps sending the conversation back to Claude for as long as the response's stop_reason is "tool_use", executing the requested tools and returning their results each time. The model, not your code, decides when the work is done, and it signals that through stop_reason.

    1.The four moves of one loop iteration

    An agentic loop exists because the model cannot run anything itself. Tool use is a contract. Your application declares which operations exist and what shape their inputs take, and Claude decides when and how to call them. The model emits a structured request, your code (or Anthropic's servers) runs the operation, and the result flows back into the conversation.

    For client-executed tools, meaning your own user-defined tools and Anthropic-schema tools such as bash and text_editor, your application owns the loop. Every tool call is a round trip: the model asks, you execute, you report back, and the model continues. The documented canonical shape has four moves. (1) Send a request with your tools array and the user message. (2) Claude responds with stop_reason "tool_use" and one or more tool_use blocks. (3) Execute each tool and format the outputs as tool_result blocks. (4) Send a new request that contains the original messages, the assistant's response, and a user message holding the tool_result blocks. Then repeat from move 2.

    The Claude Agent SDK runs the same cycle for you and names its parts. Claude receives your prompt along with the system prompt, tool definitions and conversation history. It evaluates the current state and responds with text, tool calls, or both. The SDK executes the requested tools, and each set of results feeds back to Claude for the next decision. One full cycle is one turn. The SDK docs walk through a bug fix. Turn 1 runs npm test and sees three failures. Turn 2 reads auth.ts and auth.test.ts. Turn 3 edits auth.ts and re-runs the tests, which now pass. The final turn is a text-only reply with no tool calls, followed by a result message with cost and usage.

    Look at what your code did not do in that walkthrough. Nothing in the loop says "after running the tests, read the failing files, then edit, then re-run". There is no decision tree, no pre-configured tool sequence, no branch keyed on the test output. Claude read the three failures in the tool result, reasoned about which tool to call next based on that context, and chose Read. On the next turn it chose Edit and then Bash for the same reason. The tool definitions constrain what is callable; they never fix the order. This is model-driven decision-making: the loop supplies the mechanism (send, execute, append, repeat) and the model supplies every decision about what to do next.

    Anthropic's building-effective-agents post names the two designs. Workflows are systems where LLMs and tools are orchestrated through predefined code paths: your code decides the sequence, and the model fills in each step. Agents are systems where the LLM dynamically directs its own processes and tool usage, keeping control over how it accomplishes the task. Both are legitimate. Workflows offer predictability and consistency for well-defined tasks, whereas agents are the better option when flexibility and model-driven decision-making are needed at scale. The stop_reason loop in this lesson is the agent shape: if you find yourself hard-coding which tool runs after which, you have built a workflow and the model's reasoning about the next action is no longer in charge.

    Sources123

    2.Control flow keyed on stop_reason

    Every Messages API response carries a stop_reason field, and that field is what the loop branches on. The stop-reasons guide describes it as the input to a decision: use the response as-is, continue the conversation, retry, or fall back to another model. For an agentic loop the rule fits on one line: while stop_reason is "tool_use", execute the tools and continue the conversation. Any other value exits the loop. "end_turn" means Claude has produced its final answer. The other values mean it stopped for a reason your application still has to handle.

    stop_reason values and what an agentic loop does with each
    stop_reasonWhen it occursLoop action
    tool_useClaude is calling a tool.Continue: run the tool, return the result, send the conversation again.
    end_turnClaude finished its response naturally.Terminate: use the response.
    max_tokensThe response reached your max_tokens limit.Exit the tool loop; raise max_tokens or continue the response.
    pause_turnA server-tool loop reached its iteration limit.Send the assistant content back to continue.
    refusalClaude declined to respond.Exit; read stop_details and retry on a fallback model.
    stop_sequenceClaude emitted one of your stop_sequences.Exit; read stop_sequence to see which one fired.

    Notice what the loop does not require: a tool call. With the default tool_choice of auto, Claude decides on each turn whether to call a tool or respond directly. It calls a tool when the request maps to that tool's described capability and the answer isn't already in context. For stable knowledge and conversational turns it answers directly. So if the very first response has stop_reason "end_turn" and contains only a text block, that is a complete, correct run of the loop: zero tool iterations, then exit. If a design genuinely needs a tool call, the documented levers are tool_choice and system-prompt wording, not a loop that refuses to accept "end_turn".

    An architect is building a client-side agent loop against the Messages API for a data-cleanup task. The first response has stop_reason set to "tool_use" and contains a tool_use block requesting a file-listing tool. What should the loop do next to correctly continue the agentic execution?

    Sources415

    3.Appending tool results to conversation history

    Claude reasons only from what is in the request. What it knows on iteration three is whatever you sent on iteration three. That makes building the history the loop's other essential job, alongside the stop_reason check. Each iteration appends two messages: the assistant's full response content, and a user message carrying the results. The tool-use overview shows it:

    Appending the assistant turn (including its tool_use block) and a tool_result message before the next requestpython
    # Run the tool, then send the result back in a tool_result block.
    weather = "15 degrees Celsius, partly cloudy"  # your weather lookup goes here
    messages += [
        {"role": "assistant", "content": response.content},
        {
            "role": "user",
            "content": [
                {"type": "tool_result", "tool_use_id": tool_use.id, "content": weather}
            ],
        },
    ]

    Two details in that snippet do the real work. First, the assistant message is response.content, the whole list with the tool_use blocks included, not just the text. Each tool_use block carries an id that is used to match up the tool results later, and each tool_result carries a tool_use_id naming the request it answers. Save only the assistant's text and every tool_use_id points at a call that no longer exists in the conversation. Second, the tool_result goes in a user-role message with nothing after it. The stop-reasons guide warns never to add text blocks right after tool results. Doing so teaches Claude to expect user input after every tool use, and it is a common cause of empty "end_turn" responses.

    Failures belong in the history too. If a tool throws, say a network error, return the error message as the result content with is_error set to true. Claude then incorporates the error into its reply. If Claude's call itself was invalid, for example a missing required parameter, an is_error result lets Claude try again with the gap filled. The docs say it retries 2-3 times with corrections before apologizing. In every case, the result you append is what Claude builds on: after receiving it, Claude uses that information to continue answering the original prompt.

    A junior engineer proposes capping an autonomous research agent at exactly 5 tool-call iterations and treating that cap as the loop's primary stopping mechanism, regardless of stop_reason. What is the main architectural problem with relying on a fixed iteration cap this way?

    Sources64

    4.Termination anti-patterns: text signals, iteration caps and assistant text

    The loop has exactly one documented exit condition: stop_reason is no longer "tool_use". Three substitutes show up repeatedly in real code, and each one breaks for a reason the docs spell out. The first is parsing natural language signals to decide termination: scanning the assistant's text for "Done", "Task complete" or "I have finished" and breaking the loop when a phrase matches. The tool-use docs call this out directly. If you're writing a regex to extract a decision from model output, that decision should have been a tool call. Parsing free-form text to recover structured intent means the structure belongs in the schema, and the loop's own termination decision is already structured for you in stop_reason. A phrase check terminates too early when Claude narrates progress mid-task, and never terminates when it phrases the finish differently.

    The second anti-pattern is an arbitrary iteration cap as the primary stopping mechanism: a for-loop over ten turns that treats the tenth as the answer. Nothing in the client-side contract stops after N turns. Claude continues calling tools and processing results until it produces a response with no tool calls, and the loop exits on any other stop reason, which means Claude has either produced a final answer or stopped for another reason your application should handle. The only iteration limit the docs describe belongs to the server-side tool loop, and hitting it produces "pause_turn", not "end_turn". A paused turn means the work isn't finished, and the documented response is to re-send the conversation so Claude can continue. So even where a cap exists, the platform treats reaching it as the opposite of completion. A hard ceiling is a legitimate safety net against runaway cost, but it is a guard rail beside the loop, not the loop's stop condition, and a run that hits it should be reported as incomplete rather than returned as a result.

    The third is checking for assistant text content as a completion indicator: breaking as soon as the response contains a text block, or continuing as long as it does not. Text is neither necessary nor sufficient. On the way in, Claude may respond with text, request one or more tool calls, or both, and the handle-tool-calls example shows exactly that: a response with stop_reason "tool_use" whose content opens with the text "I'll check the current weather in San Francisco for you." followed by a get_weather tool_use block. A loop that stops on text stops there, with the tool never run. On the way out, the stop-reasons guide notes that Claude sometimes returns an empty response with stop_reason "end_turn" and no content at all, particularly after tool results. A loop that waits for text never sees the finish. The only reliable signal is the field designed to carry it.

    Sources1264

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.A loop that ends with "end_turn" on the first response, without ever calling a tool, is broken, because every task has to go through at least one tool call.Why is that wrong?

      With tool_choice auto, Claude decides each turn whether a tool is needed. A text-only "end_turn" on the first request is a valid finish when the answer needs no tool.

      Covered in Control flow keyed on stop_reason

    2. 2.It is enough to append the assistant's text, or just the tool output, to history between iterations.Why is that wrong?

      The next request must carry the original messages, the full assistant response including its tool_use blocks, and a user message with tool_result blocks whose ids match those calls.

      Covered in Appending tool results to conversation history

    3. 3.If the response contains a text block, Claude has finished, so the loop can stop without checking stop_reason.Why is that wrong?

      A single response can carry text and tool_use blocks together with stop_reason "tool_use". Stopping on text leaves the requested tool unexecuted; only stop_reason says whether to continue.

      Covered in Termination anti-patterns: text signals, iteration caps and assistant text

    4. 4.Reaching an iteration limit is a normal way for an agentic run to complete, so the last response can be returned as the answer.Why is that wrong?

      The one documented iteration limit is the server tool loop's, and hitting it yields "pause_turn", which the docs define as unfinished work to be continued, not a result.

      Covered in Termination anti-patterns: text signals, iteration caps and assistant text

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Claude determines when and how to call them.”
      ↩︎ The four moves of one loop iteration
      “Client-executed tools (both user-defined and Anthropic-schema) require your application to drive a loop.”
      ↩︎ The four moves of one loop iteration
      “The difference is that the caller on the other side is a language model choosing which function to call based on the conversation.”
      ↩︎ The four moves of one loop iteration
      “In practice this reads as: while stop_reason == "tool_use", execute the tools and continue the conversation.”
      ↩︎ Control flow keyed on stop_reason
      “if you're writing a regex to extract a decision from model output, that decision should have been a tool call.”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
      “Parsing free-form text to recover structured intent is a sign the structure belongs in the schema.”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
      “The loop exits on any other stop reason ("end_turn", "max_tokens", "stop_sequence", or "refusal"), which means Claude has either produced a final answer”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
      “A paused turn means the work isn't finished; re-send the conversation (including the paused response) to let the model continue where it left off.”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
      “In practice this reads as: while stop_reason == "tool_use", execute the tools and continue the conversation.”
      ↩︎ Key concept
      “Send a new request containing the original messages, the assistant's response, and a user message with the tool_result blocks.”
      ↩︎ Exam trap 2
      “A paused turn means the work isn't finished; re-send the conversation (including the paused response) to let the model continue where it left off.”
      ↩︎ Exam trap 4
    2. 2.
      “Each set of tool results feeds back to Claude for the next decision.”
      ↩︎ The four moves of one loop iteration
      “Claude continues calling tools and processing results until it produces a response with no tool calls.”
      ↩︎ The four moves of one loop iteration
      “It may respond with text, request one or more tool calls, or both.”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
      “It may respond with text, request one or more tool calls, or both.”
      ↩︎ Exam trap 3
    3. 3.
      “Workflows are systems where LLMs and tools are orchestrated through predefined code paths.”
      ↩︎ The four moves of one loop iteration
      “Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks.”
      ↩︎ The four moves of one loop iteration
      “workflows offer predictability and consistency for well-defined tasks, whereas agents are the better option when flexibility and model-driven decision-making are needed at scale.”
      ↩︎ The four moves of one loop iteration
    4. 4.
      “Check this field to decide whether to use the response as-is, continue the conversation, retry, or fall back to another model.”
      ↩︎ Control flow keyed on stop_reason
      “Never add text blocks immediately after tool results: This teaches Claude to expect user input after every tool use.”
      ↩︎ Appending tool results to conversation history
      “Sometimes Claude returns an empty response (exactly 2–3 tokens with no content) with stop_reason: "end_turn".”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text
    5. 5.
      “It calls a tool when the request maps to that tool's described capability and the answer isn't already in context.”
      ↩︎ Control flow keyed on stop_reason
      “With the default tool_choice of {"type": "auto"}, Claude determines on each turn whether to call a tool or respond directly.”
      ↩︎ Exam trap 1
    6. 6.
      “This will be used to match up the tool results later.”
      ↩︎ Appending tool results to conversation history
      “Claude will then incorporate this error into its response to the user.”
      ↩︎ Appending tool results to conversation history
      “After receiving the tool result, Claude will use that information to continue generating a response to the original user prompt.”
      ↩︎ Appending tool results to conversation history
      “I'll check the current weather in San Francisco for you.”
      ↩︎ Termination anti-patterns: text signals, iteration caps and assistant text