Extracting tool name and input
Why this matters
When Claude decides to use a tool, the API returns a structured content block with the tool name and input. Extracting and routing these correctly is how you build functional AI agents: misparse this and your tool execution fails silently or crashes.
Explanation
When you pass a tools parameter to messages.create(), Claude can decide to invoke one of those tools by returning a tool_use content block instead of plain text. Each tool_use block contains three fields: id (unique identifier for that invocation), name (the tool name you defined), and input (a JSON object matching your tool's input_schema).
Under the hood, Claude's reasoning engine evaluates whether a tool call makes sense given your prompt and available tools. If it does, the API stops generating text and instead returns structured JSON in the content block. Your code must iterate through the response.content list, check the type of each block, and when you find type='tool_use', extract the name and input fields. The input field is already parsed as a Python dict: you don't parse it yourself.
This pattern is essential for agentic workflows: Claude thinks → Claude calls tool → you execute function → you send result back to Claude → Claude continues reasoning. Extracting tool name and input correctly is the foundation of that loop. Most teams store the tool_id to ensure you send back results linked to the correct invocation.
Request code
from anthropic import Anthropic
import json
client = Anthropic()
tools = [
{
"name": "get_weather",
"description": "Get the current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. San Francisco"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
},
{
"name": "calculate",
"description": "Perform a mathematical calculation",
"input_schema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Math expression to evaluate, e.g. 2+2 or sqrt(16)"
}
},
"required": ["expression"]
}
}
]
messages = [
{
"role": "user",
"content": "What's the weather in Paris and what is 15 times 8?"
}
]
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
tools=tools,
messages=messages
)
print("Full response:")
print(f"Stop reason: {response.stop_reason}")
print(f"Content blocks: {len(response.content)}")
print()
for block in response.content:
if block.type == "tool_use":
print(f"Tool invoked: {block.name}")
print(f"Tool ID: {block.id}")
print(f"Tool input: {json.dumps(block.input, indent=2)}")
print()
elif block.type == "text":
print(f"Text response: {block.text}")
print() Authentication
Set the ANTHROPIC_API_KEY environment variable before running this code. Export ANTHROPIC_API_KEY='sk-ant-...' in your terminal or add it to your .env file and load with python-dotenv.
Response shape
| Field | Description |
|---|---|
stop_reason | string: either 'tool_use' or 'end_turn' depending on why Claude stopped |
content | list of content blocks |
content[].type | string: either 'text' or 'tool_use' |
content[].text | string: plain text response (only if type='text') |
content[].name | string: the tool name Claude wants to invoke (only if type='tool_use') |
content[].id | string: unique identifier for this tool invocation (only if type='tool_use') |
content[].input | dict: the parsed input parameters for the tool (only if type='tool_use') |
usage.input_tokens | integer: tokens consumed by your message |
usage.output_tokens | integer: tokens generated by Claude |
Field guide
stop_reason Always check this first. If it's 'tool_use', you have tool_use blocks to process. If it's 'end_turn', Claude is done and won't call more tools this turn.
content[].id Store this value. When you execute the tool and send the result back, you must include this id in your tool_result block so Claude knows which invocation this result belongs to.
content[].input This is already a Python dict: no JSON parsing needed. Validate the keys match your input_schema before passing to your function.
content[].type The hidden field many miss: iterating without checking type causes AttributeError when you try to access .text on a tool_use block (it has .name instead).
Setup trap
The most common mistake is not including tools in the messages.create() call. If you pass tool definitions but forget the tools= parameter, Claude will never invoke them and you'll just get text responses. Also, if your input_schema doesn't match Claude's reasoning about what fields are needed, Claude might refuse to call the tool or pass incomplete input.
Cost
Tool-use doesn't incur extra token costs, but each tool invocation still counts toward your input tokens (the tool definition) and output tokens (the tool_use block). A single message with 10 tools defined costs more than a message with 1 tool. Consider removing unused tools from the tools list to keep costs down.
Rate limits
Tool calls don't have special rate limits, but if you're building an agentic loop that calls get_messages → extract tools → execute → send results back, you're making multiple API calls per user interaction. For high-volume agents, monitor your requests-per-minute quota.
Common gotcha
Developers often forget to check block.type before accessing fields. If you do `block.name` on a text block, you get AttributeError: 'TextBlock' object has no attribute 'name'. Always branch on block.type first.
Error recovery
AttributeError: 'TextBlock' object has no attribute 'name'KeyError when accessing block.input[some_field]ValueError: Tool 'my_tool' not recognizedTool is never invokedExperienced dev note
Store the tool_id before executing the tool and always send it back in your tool_result message: this is how Claude tracks which result corresponds to which invocation, especially when Claude calls multiple tools in one turn. Forgetting the id causes Claude to misattribute results and make reasoning errors. Also, precompute your tools list once and reuse it across requests instead of rebuilding it every message; that saves token budget.
Check your understanding
If Claude returns a response with stop_reason='tool_use' and two tool_use blocks (one calling get_weather and one calling calculate), what information must you preserve before you execute those tools, and why?
Show answer hint
You need the tool_id for each invocation. When you execute the tools and send results back, you'll need to match each result to its original invocation using the id, otherwise Claude won't know which result corresponds to which tool call and will hallucinate or make logical errors.