"Tool use" (also called function calling) is a contract between your code and the model. You describe the tools your application offers — name, purpose, input schema. When Claude decides a tool would help answer the user, it does not run anything itself; it responds with a tool_use content block naming the tool and the arguments it wants. Your code executes the real function, sends the result back as a new message, and Claude continues — possibly requesting another tool, possibly producing the final answer. The back-and-forth is called the agentic loop, and the model never touches your systems directly: every action passes through code you wrote and can audit.
The shape of the loop
Conceptually there are four steps, repeated until done:
1. Call the model with the conversation so far plus your tool definitions. 2. Inspect the response for tool_use blocks. If there are none, the model has answered — exit the loop. 3. Execute each requested tool in your own code, with your own validation and permissions. 4. Append the assistant's turn and a user turn carrying the tool results to the conversation, and go back to step 1.
In Python with the official anthropic package, the skeleton looks like this (structure abbreviated — see the Messages API documentation for the exact tool-definition and tool-result shapes):
from anthropic import Anthropic
client = Anthropic()
messages = [{"role": "user", "content": "What's the weather in Berlin?"}]
while True:
response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024,
tools=tools, messages=messages)
tool_calls = [b for b in response.content if b.type == "tool_use"]
if not tool_calls:
break # final answer reached
messages.append({"role": "assistant", "content": response.content})
results = [run_tool(c) for c in tool_calls] # your code, your rules
messages.append({"role": "user", "content": results})
Two structural points matter more than the syntax. First, append the assistant's content unmodified. On models with reasoning enabled, the turn that requests a tool can include a thinking block, and the API requires you to return that block exactly as received — thinking blocks carry a cryptographic signature, and modified ones are rejected. Passing response.content through untouched satisfies this automatically. Second, tool results go back as a user-role message containing tool-result blocks matched to each request — that is how the model knows which result answers which call.
Guardrails every production loop needs
An iteration cap. A model that keeps requesting tools — because a tool errors repeatedly, or the task is genuinely open-ended — will loop as long as you let it, and every iteration bills tokens. Replace while True with a bounded counter and treat hitting the cap as a distinct outcome you log and surface.
Error results, not exceptions. When a tool fails, catch the exception and send the failure back as the tool result. Claude is often able to recover — retry with different arguments, or explain the limitation to the user. Crashing the loop turns a recoverable hiccup into an outage.
Validation at the boundary. Treat tool arguments like any untrusted input: validate against your schema, enforce authorization in the tool implementation, and never let a tool do something the calling user could not do directly.
auto tool choice, and each tool's schema adds its own tokens on every iteration of the loop). Keep schemas lean, and consider prompt caching for stable tool sets.Does this work on third-party platforms?
Yes — tool use is core Messages API functionality, available on Claude Platform on AWS, Amazon Bedrock, Google Vertex AI, and Microsoft Foundry alike. The loop above is unchanged; only the client construction differs, for example AnthropicBedrockMantle(aws_region="us-east-1") for Bedrock (with the Bedrock-prefixed model ID anthropic.claude-opus-4-8) or AnthropicVertex(project_id="...", region="global") for Vertex AI. Note that server-side tools that Anthropic executes for you (web search, code execution) have narrower platform availability than client-implemented tools — check the feature matrix.
Where to go next
Defining tool schemas covers the contract half of this pattern; orchestrating multiple tools extends the loop to many tools and parallel calls; the TypeScript version shows the same loop with static types.