What you need to know
The Messages API is stateless. Claude never runs a tool itself and never remembers the last call. An agentic loop is the code you write around the API that makes repeated calls look like one autonomous piece of work.
Each pass through the loop does four things:
- Send the full conversation so far, with the tool definitions, to Claude.
- Inspect
stop_reasonon the response. - If it is
"tool_use", execute every tool Claude requested, in your code. - Append Claude's response and a
tool_resultfor each tool call to the history, then go back to step 1.
When stop_reason is "end_turn", Claude has finished and the loop stops.
messages = [{"role": "user", "content": request}]
while True:
response = client.messages.create(model=MODEL, max_tokens=4096,
tools=TOOLS, messages=messages)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
break # end_turn, or a case handled below
results = []
for block in response.content:
if block.type == "tool_use":
output = run_tool(block.name, block.input)
results.append({"type": "tool_result",
"tool_use_id": block.id, "content": output})
messages.append({"role": "user", "content": results})
Two details carry marks in the exam. Each tool_result must carry the tool_use_id of the call it answers, and the results go back in a user message. That is the only way the model sees what a tool returned.
Other stop reasons
"tool_use" and "end_turn" are the two that drive the loop, but a robust harness handles the others explicitly rather than treating them as success.
| stop_reason | Meaning | Typical handling |
|---|---|---|
end_turn | Claude finished its turn | Stop; use the final response |
tool_use | Claude wants one or more tools run | Run them, append results, continue |
max_tokens | Output hit the token limit mid-response | Treat as incomplete: continue or raise the limit, never present it as done |
stop_sequence | A configured stop sequence was emitted | Treat like an end of turn unless that sequence has a special meaning for you |
The Agent SDK runs this loop for you. You still need to understand it, because the SDK's turn limits, budgets and hooks all attach to these same steps.
Model-driven, not scripted
In an agentic loop Claude decides which tool to call next, based on what earlier results showed. That is different from a pre-configured decision tree or a fixed sequence of tool calls written in your code. The model-driven loop handles cases nobody scripted; a fixed sequence is cheaper and more predictable when the steps never change (lesson 1.6 covers that choice).
In the exam
Expect a harness with one flaw. Common ones: the loop stops on text content; it stops after a fixed number of iterations; tool results are not appended, so Claude repeats the same call; a max_tokens response is shown to the customer as a finished answer. Pick the option that makes stop_reason the control signal and keeps the history complete.
Check your understanding
Your harness stops the loop whenever Claude's response contains a text block. Some sessions end before the refund is issued. Why?
Show answer
Answer: B. A single response can hold a text block ("Let me check that order") and a tool_use block. Stopping on text throws away the tool call. Only stop_reason tells you whether Claude is done.
After running lookup_order, how does the model see the order data?
Show answer
Answer: D. The API is stateless. The result reaches the model only when your code appends a tool_result block, tied to the call by tool_use_id, and sends the conversation again.
A response arrives with stop_reason "max_tokens". What should the harness do?
Show answer
Answer: A. max_tokens means the output was cut off mid-response. Showing it as a finished answer is a classic way for sessions to end in an undefined state.
Apply it: Write Cedar Ridge's loop contract
Cedar Ridge's platform engineer wants a one-page "loop contract" before writing the support agent's harness. Write it.
- Define the continue and stop rules. State exactly which
stop_reasonvalues continue the loop, which end it, and what happens on each of the others. - Describe how a tool result returns to Claude. Name the block type, the field that links it to the call, and the role of the message it goes in.
- Add one safety net and say why it is not the stopping rule. For example a turn limit or a budget.
Why: the exam treats caps as safeguards, never as the main stop. - List three anti-patterns the code review must reject.
Show model answer
1. Continue and stop rules
| stop_reason | Action |
|---|---|
tool_use | Run every requested tool, append results, call Claude again |
end_turn | Stop; the last response is the reply to the customer |
max_tokens | Incomplete: call again asking Claude to continue; if it repeats, escalate with context |
stop_sequence | Treat as end of turn (we configure none today) |
| anything else, or an API error | Do not reply as if resolved; escalate with the case so far |
2. Returning results. For each tool_use block, run the tool and add a tool_result block whose tool_use_id equals the block's id. All results for one response go together in a single user message appended after Claude's assistant message.
3. Safety net. A limit of 25 turns per session. Real sessions use 4 to 10, so hitting 25 means something is looping; the harness then escalates with a summary instead of answering. It is a guard against runaway cost, not the way a normal session ends.
4. Reject in review
- Stopping when the response contains text.
- Searching Claude's text for "resolved" or "anything else?" to decide the session is over.
- Stopping after a fixed number of tool calls as the normal end of a session.