What you will be able to do
- Tell a model-driven agentic loop apart from a pre-configured workflow or fixed tool sequence
- Explain why parsing natural-language phrases, or checking whether text is present, is an unreliable way to end a loop
- Treat iteration caps such as max_iterations and maxTurns as safety limits, not as the loop's main stopping signal
1.Claude chooses the next tool
In an agentic loop, the model decides what happens next. Anthropic's engineering guidance draws the line between two kinds of system. In workflows, LLMs and tools are orchestrated through predefined code paths. In agents, the LLM dynamically directs its own processes and tool usage. A fixed decision tree such as "always search, then fetch, then summarise" is a workflow. The loop in this lesson is an agent: your code runs whatever Claude asks for and returns the result, and Claude decides what to ask for next.
The Agent SDK documentation describes the same split. On each turn, Claude evaluates the current state and decides what to do next, and each set of tool results goes back to Claude for its next decision. Its worked example starts with a request to fix failing tests. Claude runs npm test through Bash and sees three failures. It reads auth.ts and auth.test.ts, edits auth.ts, and runs the tests again. When they pass, it replies with text only. No application code chose to call Read after Bash. The test output led to that choice.
Neither approach is better in every case. The guidance recommends the simplest solution that works and warns that agentic systems often trade latency and cost for better task performance.
| Aspect | Workflow | Agent |
|---|---|---|
| Who picks the next step | Predefined code paths | The LLM dynamically directs its own processes and tool usage |
| What it offers | Predictability and consistency | Flexibility and model-driven decision-making |
| Best fit | Well-defined tasks | Flexibility needed at scale |
Checkpoint 1 of 4· Check yourself
A team writes code that always calls lookup_order, then check_refund_policy, then issue_refund, whatever the earlier results were. How should this design be classified?
What makes something an agent is who decides the next action. Here the application code fixes the order of tools, so it is a workflow. Claude filling in the arguments doesn't change that.
“Workflows are systems where LLMs and tools are orchestrated through predefined code paths.”Source: www.anthropic.com
2.Why text and phrases are bad stop signals
The API already gives you a structured stop signal, so a stop condition built on Claude's wording takes you backwards. The tool-use documentation gives a general rule: if you are writing a regex to extract a decision from model output, that decision should have been a structured signal. Whether the loop is finished is exactly that kind of decision, and stop_reason already carries it. A check for a phrase like "I have completed the task" relies on wording Claude never promised to use. It fails in both directions: the phrase can show up before the work is done, or be missing when the work is finished.
A related mistake treats any text in the response as the sign of completion. Claude can respond with text, with tool calls, or with both in one response. Here a response opens with a sentence of narration and also asks for a tool:
{
"id": "msg_01Aq9w938a90dw8q",
"model": "claude-opus-5-5",
"stop_reason": "tool_use",
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll check the current weather in San Francisco for you."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": { "location": "San Francisco, CA", "unit": "celsius" }
}
]
}A loop that stops when it sees text would quit here, before the weather was ever fetched. The opposite check fails as well. Claude sometimes returns an empty response with stop_reason "end_turn", typically when it judges that the assistant turn is complete, particularly after tool results. A loop that keeps going whenever it finds no text would send that empty response back. The documentation says this doesn't help, because Claude has already decided it is done. Text being present doesn't prove the task is finished, and text being absent doesn't prove it isn't.
Checkpoint 2 of 4· Check yourself
A loop ends as soon as a response contains any text block. In testing, it sometimes stops before a requested tool has run. What explains this?
A single response can hold text and tool calls together, as the stop_reason "tool_use" example shows. Only stop_reason reliably says whether Claude is waiting on a tool.
“It may respond with text, request one or more tool calls, or both.”Source: code.claude.com
Checkpoint 3 of 4· Exam question
A team is implementing termination logic for an autonomous refactoring agent. Loop A exits when `response.stop_reason == "end_turn"`. Loop B exits when the assistant's final text block is non-empty, on the assumption that any explanatory text means Claude is finished. Which loop correctly implements the standard termination pattern?
Correct answer: A — Loop A, because stop_reason directly reports whether Claude finished its turn without requesting a tool, which is the documented signal
- A. Correct. Claude can emit explanatory text alongside a tool_use block in the same turn, so checking for text presence stops the loop too early; stop_reason is the structured, authoritative field.
- B. Incorrect. A response can include commentary text while still requesting another tool, so non-empty text does not reliably mean the turn is finished.
- C. Incorrect. Text presence and stop_reason are not guaranteed to move together; a turn can carry both a tool_use block and accompanying text.
- D. Incorrect. Content block counts vary with output style and are not a documented completion signal in the Messages API.
3.Iteration caps are limits, not stop signals
Caps on loop length do exist. The SDK tool runner accepts max_iterations, and the Agent SDK accepts maxTurns. Look at how the documentation places them, though. The tool runner loops until Claude returns a message with no tool use, or until it reaches max_iterations if you set one. The main condition is a response with no tool calls. The cap is optional.
The Agent SDK spells out what a cap means when it fires. The final ResultMessage has a subtype you should check to see whether the task succeeded or hit a limit. A normal finish is success, described as "Claude finished the task normally". Running out of turns gives error_max_turns, described as "Hit the maxTurns limit before finishing", and in that case no result field is available. Server-side tool loops follow the same pattern. Their internal iteration limit returns pause_turn, and the documentation says a paused turn means the work isn't finished. In both cases a cap interrupts the work. It doesn't complete it.
Caps are still useful as a safety limit. If you take over the tool runner's message history, the documentation tells you to pass max_iterations so the loop stays bounded. You also become responsible for leaving the loop able to exit when there are no tool calls. The tool runner itself runs the loop for you: it executes tools, handles the request and response cycle, and manages conversation state. A hand-written loop is the better choice when you need human-in-the-loop approval, custom logging or conditional execution.
Checkpoint 4 of 4· Match them up
Match each loop outcome to what it tells you
Tap a term, then the definition that fits it.
Only "end_turn" with no tool calls, or a success result, means the task is complete. Hitting a cap, whether maxTurns or the server-side iteration limit, means the work stopped part-way.
“Hit the maxTurns limit before finishing”Source: code.claude.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.If the assistant's response contains text, the task is done and the loop can stop.Why is that wrong?
A response can hold text and tool calls together, and stop_reason "tool_use" means tools are still waiting. stop_reason is the completion signal, not the presence of text.
Covered in Why text and phrases are bad stop signals
2.Setting max_iterations or maxTurns is how an agentic loop should decide when the task is finished.Why is that wrong?
The main stop condition is a response with no tool use. A cap is an optional safety limit, and reaching it reports the task as unfinished.
Covered in Iteration caps are limits, not stop signals
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://code.claude.com/docs/en/agent-sdk/agent-loopOfficial docs
“Each set of tool results feeds back to Claude for the next decision.”
↩︎ Claude chooses the next tool“It may respond with text, request one or more tool calls, or both.”
↩︎ Why text and phrases are bad stop signals“Check the subtype field to determine whether the task succeeded or hit a limit.”
↩︎ Iteration caps are limits, not stop signals“Hit the maxTurns limit before finishing”
↩︎ Iteration caps are limits, not stop signals“It may respond with text, request one or more tool calls, or both.”
↩︎ Exam trap 1 - 2.
“Claude determines when and how to call them”
↩︎ Claude chooses the next tool“if you're writing a regex to extract a decision from model output, that decision should have been a tool call.”
↩︎ Why text and phrases are bad stop signals“A paused turn means the work isn't finished”
↩︎ Iteration caps are limits, not stop signals - 3.https://www.anthropic.com/engineering/building-effective-agentsSecondary source
“systems where LLMs dynamically direct their own processes and tool usage”
↩︎ Claude chooses the next tool“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.”
↩︎ Claude chooses the next tool“Agentic systems often trade latency and cost for better task performance”
↩︎ Claude chooses the next tool“Workflows are systems where LLMs and tools are orchestrated through predefined code paths.”
↩︎ Checkpoint - 4.
“This typically occurs when Claude interprets that the assistant turn is complete, particularly after tool results.”
↩︎ Why text and phrases are bad stop signals“Don't retry empty responses without modification: Sending the empty response back won't help.”
↩︎ Why text and phrases are bad stop signals - 5.
“The runner loops until Claude returns a message without a tool use, or until it reaches max_iterations if you set it.”
↩︎ Iteration caps are limits, not stop signals“modify state conditionally so the loop can still exit when there are no tool calls, and pass max_iterations to bound the loop”
↩︎ Iteration caps are limits, not stop signals“When you need human-in-the-loop approval, custom logging, or conditional execution, use the manual loop instead.”
↩︎ Iteration caps are limits, not stop signals“The runner loops until Claude returns a message without a tool use, or until it reaches max_iterations if you set it.”
↩︎ Exam trap 2