Every agentic loop follows the same lifecycle: send a request with tool definitions, inspect stop_reason, and branch. "tool_use" means execute the requested tool, append both the assistant's message and the tool's result to conversation history, and iterate. "end_turn" means exit. That's it.
The loop repeats "model responds → check stop_reason" until it says
end_turn. The three items in the callout box are common substitutes that look like valid terminators but aren't.
stop_reason is the contract. Everything else is a heuristic. Three things people reach for instead, and why each fails:
- Parsing free text like "Done!" to decide the loop is finished — natural-language phrasing is not an API contract, and a model that says "I'll continue in a moment" or "Done for now" breaks a text-parsing terminator immediately.
- An iteration cap as the primary stopping mechanism — useful as a safety net against runaway loops, but as a terminator it truncates real, unfinished work.
- Treating the presence of a text block as completion — a single turn can legitimately contain both a text explanation and a
tool_useblock. An agent that writes a paragraph explaining what it's about to do, in the same turn it calls a tool, is not done.
Tool results belong in conversation history, not a freshly assembled prompt. The model chooses its next action because it can see what earlier tool calls actually returned — drop that history and the loop starts thrashing, re-requesting information it already has or acting on stale assumptions.
One more distinction worth holding onto: a model-driven loop (Claude decides the next tool call from accumulated context) and a pre-configured decision tree (your code decides) are both legitimate architectures. The exam's judgment call isn't "which is better" — it's recognizing which one a scenario is describing, and which one a given requirement actually needs.