Claude Agentic Loop: stop_reason, Tool Results and Anti-Patterns

Every Claude agent — whether you write it yourself or use the Agent SDK — is built on one loop: ask Claude, run the tools it requests, give it the results, repeat. Get the stop condition wrong and your agent either quits mid-task or never finishes. This is Task Statement 1.1 of the exam.

Advertisement
📖 What You’ll Learn: You will be able to write a Claude agentic loop that continues on tool_use, stops on end_turn and returns tool results correctly.

🔁 The loop, step by step

  1. Send the conversation (and tool definitions) to the Messages API.
  2. Inspect stop_reason on the response.
  3. If it is "tool_use": run each requested tool and append one user message containing every tool_result block, matched by tool_use_id.
  4. Call Claude again with the updated history.
  5. Stop when stop_reason is "end_turn".
messages = [{"role": "user", "content": user_question}]
while True:
    resp = client.messages.create(model=MODEL, max_tokens=4096,
                                  tools=TOOLS, messages=messages)
    messages.append({"role": "assistant", "content": resp.content})
    if resp.stop_reason != "tool_use":       # "end_turn" (also handle max_tokens, refusal)
        break
    results = []
    for block in resp.content:
        if block.type == "tool_use":
            results.append(run_tool(block))      # returns a tool_result dict
    messages.append({"role": "user", "content": results})   # ALL results, ONE message
Claude agentic loop flow1. Your codesends messages+ tool definitions2. Clauderesponds via theMessages APICheckstop_reasonReturn thefinal answer3. Run every tool_useappend ALL tool_resultblocks in ONE user messageend_turntool_usenext iteration✗ Never stop on assistant text, phrases like “DONE”, or a bare iteration cap
Figure: the agentic loop — keep looping while stop_reason is tool_use, stop on end_turn.
Advertisement

📘 Why the model chooses the next step

In an agent, Claude reasons about which tool to call next from the context, including the results it has just seen. That is the difference from a pre-configured decision tree, where code fixes the sequence. Tool results must be appended to the history, otherwise the model cannot use them and will often request the same tool again.

⚠️ Termination anti-patterns (exam favourites)

⚠️ Watch out: All of these are wrong as the primary stop mechanism:
  • Stopping when the response “contains text” — Claude often writes a sentence and a tool call in the same turn.
  • Parsing phrases such as “DONE” or “Is there anything else?” — natural-language signals are brittle.
  • A fixed iteration cap — fine as a safety backstop, never as the loop logic.

🛑 Other stop reasons you should know

stop_reasonMeaningWhat to do
end_turnClaude finishedReturn the answer
tool_useClaude wants tools runRun them, append results, loop
max_tokensOutput was cut offRaise the limit or continue
stop_sequenceA custom stop sequence was hitHandle per your design
pause_turnLong server-tool turn pausedSend the response back to continue
refusalClaude declinedHandle gracefully
Advertisement

🧪 Exam-Style Practice Questions

Try these before opening the answers. They use the same scenario style as the real exam.

Question 1. Which loop condition is correct for a manual Claude agentic loop?

  • A. Loop until the assistant message contains no text
  • B. Loop until the model says "DONE"
  • C. Loop while `stop_reason == "tool_use"`, stop on `"end_turn"`
  • D. Loop exactly 5 times
Show answer

Answer: C. `stop_reason` is the structured signal for whether the model wants a tool run. A: Claude often sends text *and* tool_use in the same turn. B: parsing natural language is brittle. D: a fixed cap can be a safety backstop, but it's never the primary stop condition.

Question 2. After executing the three tool calls Claude requested in one turn, how should you return the results?

  • A. Three separate user messages, one per result
  • B. Put the results in the system prompt
  • C. One assistant message with the results
  • D. One user message containing three `tool_result` blocks, each with its `tool_use_id`
Show answer

Answer: D. All results for a turn go back in one user message, matched by ID. A: splitting them breaks the turn structure and discourages parallel calls. B and C: results are user-role content, not system or assistant content.

Question 3. What best distinguishes an *agent* from a *workflow*?

  • A. In an agent the model decides the next action from context; in a workflow, code defines the path
  • B. Workflows can't use tools
  • C. Agents never need a system prompt
  • D. Agents use bigger models
Show answer

Answer: A. Model-driven decision-making is what makes it an agent. D: model size doesn't matter here. B: workflows use tools all the time. C: agents need system prompts too.

Advertisement

📝 Assignment

Do these tasks in order. Each one has a Done when check, so you know when it is complete. The stretch task is optional but close to what the exam expects from an architect. Keep your answers in one notes file or Git repository, and revisit them in your final week of revision together with the cheat sheet in the last lesson of this course.

  1. Task 1: Implement the loop from this lesson with one tool (get_weather returning fixed data) and print stop_reason on every iteration.
    ✅ Done when: Your script prints tool_use and then end_turn, and the final answer uses the tool's data.
  2. Task 2: Deliberately break it by stopping on 'response contains text'. Find a prompt where Claude writes a sentence and a tool call together and observe the failure.
    ✅ Done when: You can show a transcript where the broken loop stops early, and explain in one sentence why stop_reason fixes it.
  3. Stretch: add handling for max_tokens and refusal stop reasons with a clear message to the user.
    ✅ Done when: A response cut off by max_tokens or a refusal produces a clear message instead of a crash or a silent empty answer.
Advertisement

❓ Frequently Asked Questions

🤔 What stop_reason means Claude wants a tool run?

tool_use. Run every tool_use block in the response and send all results back in one user message.

🤔 Why not stop when the response contains text?

Claude often writes a short sentence and a tool call in the same turn, so text alone does not mean the task is finished.

🤔 Is an iteration cap wrong?

A cap is a good safety backstop, but it should never be the main way the loop decides it is done.

🤔 What happens if I forget to append tool results?

Claude cannot see the results, so it usually asks for the same tool again and the loop repeats.

🏁 Summary

  • Loop on stop_reason == "tool_use"; stop on "end_turn".
  • Return every tool result for a turn in a single user message.
  • Never terminate on text content, phrases or a bare iteration count.
📝 Test yourself: Mock Test 1 · Mock Test 2 (30 scenario-based questions in 60 minutes, with explanations).

Next, continue with Multi-Agent Orchestration with Claude: Coordinators and Subagents.

🎬 Prefer video? Watch QA, automation and AI testing tutorials on the SQA Tools YouTube channel.

Independent study material by SQA Tools. Not affiliated with, endorsed by or sponsored by Anthropic. Claude is a trademark of Anthropic. Mock questions are original practice items, not real exam content. Exam facts checked against Anthropic's official exam guides and certification FAQ on 11 November 2026.