Agentic Loop
PatternsDefinition
The core pattern for AI agents: call Claude, check `stop_reason`, if `"tool_use"` execute the requested tools and append results, then call Claude again. Repeat until `stop_reason` is `"end_turn"`. The number of loop iterations is determined dynamically by task complexity.
Example Usage
while response.stop_reason == 'tool_use': execute tools, append tool_result blocks, call Claude again.
Why It Matters for the CCA-F Exam
The agentic loop is the single most-tested pattern in Domain 1 (Agentic Architecture) of the CCA-F exam. Expect scenario questions that present a broken loop implementation and ask you to identify which `stop_reason` branch is being mishandled or which tool-result format is incorrect. Memorise the full `stop_reason` value set — see [stop_reason](/glossary/stop-reason) — including `pause_turn`, `refusal`, and `model_context_window_exceeded`; partial lists are a common exam trap.
In Depth
The Heartbeat of Every Agent
Every Claude-based agent, no matter how complex, reduces to one repeating cycle: call Claude → inspect stop_reason → if tool use was requested, execute tools and return results → repeat. This loop runs until the model signals it has finished by returning stop_reason: "end_turn".
Understanding the loop is not optional for the CCA-F exam — virtually every agent architecture question builds on it.
Loop Control: The stop_reason Branch Table
After each API call, the stop_reason value dictates what the loop does next. This branch table is the loop's decision engine:
| Value | Meaning | Loop action |
|---|---|---|
end_turn | Model is done | Extract content, exit loop |
tool_use | Model wants a tool | Execute all tool blocks, append tool_result blocks, continue |
max_tokens | Hit output cap | Increase max_tokens or summarise context, retry or abort |
stop_sequence | Hit a configured stop string | Decision point — handle as done or re-prompt |
pause_turn | Server-side tool loop paused | Re-send the messages array as-is to resume |
refusal | Model declined (safety) | Surface to user; do not blindly retry |
model_context_window_exceeded | Input context window full | Compact or split; distinct from max_tokens |
For definitions of each value, see stop_reason.
Appending Tool Results Correctly
All tool_result blocks for a given turn must be collected into one user message. Sending them as separate messages breaks the loop because the model does not receive a properly paired response.
Why the Loop Count Is Dynamic
You cannot predict how many iterations an agent will take before it starts. The model decides how many tools to call, and each call may produce information that triggers further tool calls. This is fundamentally different from a fixed pipeline with a known number of steps. The practical implication: always set a max-iterations guard to prevent runaway loops from exhausting your context window or budget.
MAX_ITERATIONS = 20
iterations = 0
while response.stop_reason == "tool_use":
if iterations >= MAX_ITERATIONS:
raise RuntimeError("Agent exceeded max iterations — aborting")
# execute tools, collect results, call Claude again
iterations += 1What Makes the Loop Fail Silently
The most common bugs that corrupt the loop without raising an exception:
- Ignoring
stop_reasonand always reading content: Whenstop_reasonistool_use, the content block contains a tool call, not a final answer. Reading it as a final answer produces garbled output. - Sending tool results as separate messages: The model expects all results for a turn in one user message.
- Not handling
refusal: The model may decline mid-loop for safety reasons. Code that only handlesend_turnwill spin forever. - Forgetting
pause_turn: Introduced for server-side tool loops; if your code does not handle it, the agent silently stalls.
For a deep dive on execution mechanics see the Agentic Loop Lifecycle concept page. The tool_use glossary entry covers parallel tool call mechanics.
Frequently Asked Questions
When `stop_reason` is `tool_use`, can there be multiple tool calls in one response?
Yes. Claude can return multiple `tool_use` content blocks in a single response (parallel tool calls). Your code must execute all of them and return all the corresponding `tool_result` blocks in a single user message. Sending them one at a time across multiple messages will cause the model to receive incomplete context and produce incorrect follow-up calls.
What is the difference between `max_tokens` and `model_context_window_exceeded` as stop reasons?
`max_tokens` fires when the *output* reaches the `max_tokens` limit you set in the request — the response was cut off mid-generation. `model_context_window_exceeded` fires when the *input* context (messages + tools + system prompt) is too large for the model to accept — the request was rejected before generation started. The fix for `max_tokens` is raising the output cap or splitting the task; the fix for `model_context_window_exceeded` is compressing or summarising the conversation history.
How do I prevent an agentic loop from running indefinitely?
Wrap the loop in a counter: track iterations and break (or raise an error) after a reasonable maximum — commonly 10–20 steps for most tasks. You can also implement a `task_budget` (beta) on newer models for a hard cap on total reasoning cost across the entire loop. Never rely on the model naturally terminating — adversarial inputs or tool errors can push models into repetitive cycles.