Agent loop stop_reason: when to loop and when to stop
Keep looping only while stop_reason is tool_use: run the tools, send back the tool_result blocks, and call the API again. Every other value (end_turn, max_tokens, stop_sequence, refusal, model_context_window_exceeded) leaves the loop and gets its own handling, and pause_turn means a server-tool loop paused and you resend the assistant content to continue.
How the loop works
When Claude wants one of your client tools, the response comes back with stop_reason: "tool_use" and one or more tool_use blocks. Your code runs each tool, then sends a new request with the earlier messages, the assistant response, and a user message holding the tool_result blocks. You repeat while stop_reason is tool_use.
Any other value exits the loop. end_turn means Claude finished, so you use the response. The others mean Claude stopped for a reason your application has to handle, not that it owes you another turn.
What each stop reason means
max_tokens: the response hit your max_tokens limit. It is valid but truncated. Raise max_tokens or continue the response. If it ends in an incomplete tool_use block, retry with a higher max_tokens to get the full call.
stop_sequence: Claude emitted one of your stop_sequences; read stop_sequence to see which. refusal: Claude declined. It arrives as a normal HTTP 200, and stop_details names the policy category; stop_details is null for every other stop reason. model_context_window_exceeded: the response filled the model's context window, so treat it as truncated.
pause_turn and server tools
Server tools such as web_search and code_execution run their own loop on Anthropic's side. If that loop hits its iteration limit (10 iterations per request by default), the response returns pause_turn. Send the assistant content back as-is and Claude continues.
A response waiting on one of your client tools never uses pause_turn; it uses tool_use. A tool_use response can also hold a server_tool_use block with no matching result block yet. There is no other marker for that state, so check each server_tool_use or mcp_tool_use id for a matching result before you treat the turn as finished.
Where the exam catches people
Looping until stop_reason is end_turn is wrong: a max_tokens or refusal response would then be re-sent forever, so loop only while it is tool_use.
max_tokens is not a malformed response: the content is valid but truncated, and re-sending the same request with the same limit truncates again.
pause_turn is not the signal to run your client tools; it belongs to server-tool loops, and client tool calls always arrive with tool_use.
A refusal is not an HTTP error: it comes back as a 200 response, with the reason in stop_details.