The tool-use loop
Claude never executes anything — it requests, you execute, you return the result.
Tool use is a structured negotiation. You send message history plus tool definitions. If Claude decides a tool is needed, it returns a tool_use content block with a name, an input object, and an id, and stop_reason is tool_use. Your application executes the tool. You then append the assistant message and a tool_result block referencing the same id, and call the API again. The loop repeats until the model returns a normal end_turn.
The model never runs code, never touches your database, and never calls an API. It only ever *asks*. Every authorisation, validation and rate-limit decision lives in your executor — which is precisely where it belongs.
Tool definitions are re-sent on every request (they are part of the stateless payload) and should therefore sit in the cacheable prefix. Tool results must be returned for every tool_use id in a turn — omitting one produces an API error.
- stop_reason 'tool_use' means the model is waiting on you; the turn is not finished.
- Every tool_use id needs a matching tool_result in the next user message.
- All security enforcement happens in your executor, never in the prompt.