Loading...
Loading...
Loading...
Tool use (formerly called function calling) allows Claude to interact with external tools, APIs, and functions. Released on April 4, 2024, and made generally available on May 30, 2024, this feature enables Claude to perform actions beyond text generation.
# Claude Tool Use (Function Calling) Documentation
## Overview
Tool use (formerly called function calling) allows Claude to interact with external tools, APIs, and functions. Released on April 4, 2024, and made generally available on May 30, 2024, this feature enables Claude to perform actions beyond text generation.
## Current Model Support
### Claude Sonnet 4
- Model ID: `claude-sonnet-4-5-20250929`
- Input: $3 per million tokens
- Output: $15 per million tokens
- Max output: 8192 tokens
- Excellent tool use performance with 72.7% on SWE-bench
## Basic Tool Definition Structure
Tools must follow this JSON schema format:
```json
{
"name": "tool_name",
"description": "Detailed description of what the tool does",
"input_schema": {
"type": "object",
"properties": {
"parameter1": {
"type": "string",
"description": "Description of parameter1"
},
"parameter2": {
"type": "integer",
"description": "Description of parameter2"
}
},
"required": ["parameter1"]
}
}
```
### Important Schema Rules
- **No `$schema` property** - Don't include JSON Schema version references
- **No `additionalProperties`** - This is not supported
- **Simple types only** - Use `string`, `integer`, `boolean`, `number`, `array`, `object`
- **Tool names** - Must match regex `^[a-zA-Z0-9_-]{1,64}$`
- **Clear descriptions** - Critical for Claude to understand when and how to use tools
## Python Implementation
### Basic Setup
```python
import anthropic
import json
client = anthropic.Anthropic(api_key="your-api-key")
# Define your tool
tools = [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"description": "Temperature unit: 'celsius' or 'fahrenheit'"
}
},
"required": ["location"]
}
}
]
# Send message with tools
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
tools=tools,
messages=[
{"role": "user", "content": "What's the weather in New York?"}
]
)
```
### Handling Tool Calls
```python
def handle_tool_use(response):
for content in response.content:
if content.type == "tool_use":
tool_name = content.name
tool_input = content.input
tool_use_id = content.id
# Execute your tool
if tool_name == "get_weather":
result = get_weather(**tool_input)
# Return result to Claude
return {
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_use_id,
"content": json.dumps(result)
}
]
}
```
### Complete Conversation Flow
```python
import anthropic
import json
client = anthropic.Anthropic()
def get_weather(location, unit="fahrenheit"):
"""Simulated weather function"""
# Your actual implementation here
return {
"location": location,
"temperature": 72,
"unit": unit,
"conditions": "partly cloudy"
}
def run_conversation(user_message):
messages = [{"role": "user", "content": user_message}]
tools = [
{
"name": "get_weather",
"description": "Get current weather in a location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and state"
}
},
"required": ["location"]
}
}
]
while True:
# Get Claude's response
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
tools=tools,
messages=messages
)
# Check for tool use
tool_use = None
final_text = ""
for content in response.content:
if content.type == "text":
final_text += content.text
elif content.type == "tool_use":
tool_use = content
# If no tool use, we're done
if not tool_use:
return final_text
# Execute tool
if tool_use.name == "get_weather":
tool_result = get_weather(**tool_use.input)
# Add Claude's message with tool use to history
messages.append({
"role": "assistant",
"content": response.content
})
# Add tool result
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": json.dumps(tool_result)
}
]
})
# Continue conversation
```
## Advanced Tool Patterns
### Multiple Tools
```python
tools = [
{
"name": "search_database",
"description": "Search the company database for information",
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SQL query to execute"
},
"database": {
"type": "string",
"description": "Database name"
}
},
"required": ["query", "database"]
}
},
{
"name": "send_email",
"description": "Send an email to a recipient",
"input_schema": {
"type": "object",
"properties": {
"to": {
"type": "string",
"description": "Recipient email"
},
"subject": {
"type": "string",
"description": "Email subject"
},
"body": {
"type": "string",
"description": "Email body"
}
},
"required": ["to", "subject", "body"]
}
}
]
```
### Complex Input Schemas
```python
{
"name": "create_chart",
"description": "Create a data visualization chart",
"input_schema": {
"type": "object",
"properties": {
"chart_type": {
"type": "string",
"description": "Type: 'bar', 'line', 'pie', 'scatter'"
},
"data": {
"type": "array",
"description": "Array of data points"
},
"options": {
"type": "object",
"description": "Chart configuration options"
}
},
"required": ["chart_type", "data"]
}
}
```
### Nested Objects (Simplified)
```python
{
"name": "process_order",
"description": "Process a customer order",
"input_schema": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Customer identifier"
},
"items": {
"type": "array",
"description": "Array of order items with 'product_id', 'quantity', 'price'"
},
"shipping_address": {
"type": "object",
"description": "Address object with 'street', 'city', 'state', 'zip'"
}
},
"required": ["customer_id", "items"]
}
}
```
## Tool Execution Service Pattern
```python
class ToolExecutor:
def __init__(self):
self.tools = {
"get_weather": self.get_weather,
"search_database": self.search_database,
"calculate": self.calculate
}
def execute(self, tool_name: str, tool_input: dict):
"""Execute a tool by name with given input"""
if tool_name not in self.tools:
return {"error": f"Unknown tool: {tool_name}"}
try:
return self.tools[tool_name](**tool_input)
except Exception as e:
return {"error": f"Tool execution failed: {str(e)}"}
def get_weather(self, location: str, unit: str = "fahrenheit"):
# Implementation
pass
def search_database(self, query: str, database: str):
# Implementation
pass
def calculate(self, expression: str):
# Implementation
pass
```
## Streaming Tool Use
```python
from anthropic import Anthropic
client = Anthropic()
with client.messages.stream(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
tools=tools,
messages=messages
) as stream:
for event in stream:
if event.type == "content_block_start":
if event.content_block.type == "tool_use":
print(f"Using tool: {event.content_block.name}")
elif event.type == "content_block_delta":
if event.delta.type == "text_delta":
print(event.delta.text, end="")
```
## Async Tool Use
```python
import asyncio
from anthropic import AsyncAnthropic
async def async_tool_conversation():
client = AsyncAnthropic()
response = await client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
tools=tools,
messages=messages
)
for content in response.content:
if content.type == "tool_use":
# Async tool execution
result = await execute_tool_async(content.name, content.input)
# Process result
```
## Best Practices
### 1. Clear Tool Descriptions
```python
# Good
"description": "Search for products in the inventory database by name, category, or SKU. Returns matching products with details including price, stock level, and description."
# Bad
"description": "Search products"
```
### 2. Validate Tool Input
```python
def execute_tool(tool_name: str, tool_input: dict):
# Validate required parameters
if tool_name == "send_email":
required = ["to", "subject", "body"]
missing = [field for field in required if field not in tool_input]
if missing:
return {"error": f"Missing required fields: {missing}"}
# Execute tool
return tool_functions[tool_name](**tool_input)
```
### 3. Error Handling
```python
def safe_tool_execution(tool_name: str, tool_input: dict):
try:
result = execute_tool(tool_name, tool_input)
return {"success": True, "data": result}
except ValueError as e:
return {"success": False, "error": f"Invalid input: {str(e)}"}
except Exception as e:
return {"success": False, "error": f"Execution failed: {str(e)}"}
```
### 4. Tool Result Formatting
```python
# Always return structured data
def get_user_info(user_id: str):
user = database.get_user(user_id)
if not user:
return {
"found": False,
"error": "User not found"
}
return {
"found": True,
"user": {
"id": user.id,
"name": user.name,
"email": user.email,
"created_at": user.created_at.isoformat()
}
}
```
## Sequential vs Parallel Tool Use
### Sequential (Default Behavior)
Claude typically uses tools one at a time:
```python
# User: "Get weather in NYC and send it to [email protected]"
# Claude will:
# 1. Call get_weather("New York, NY")
# 2. Get result
# 3. Call send_email(...) with weather info
```
### Encouraging Parallel Tool Use
```python
system_prompt = """When multiple independent pieces of information are needed,
use multiple tools in a single response rather than sequentially. For example,
if asked for weather in multiple cities, call the weather tool multiple times
in one response."""
```
## Tool Use with System Prompts
```python
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
system="""You are a helpful assistant with access to tools.
When using tools:
1. Explain what you're about to do before using a tool
2. Use tools when they would provide helpful information
3. Interpret tool results for the user
4. Chain tools together when needed
5. Handle errors gracefully
Always provide a natural language response along with tool results.""",
tools=tools,
messages=messages
)
```
## Common Patterns
### Database Query Tool
```python
{
"name": "query_database",
"description": "Execute a read-only SQL query on the specified database",
"input_schema": {
"type": "object",
"properties": {
"database": {
"type": "string",
"description": "Database name: 'users', 'products', 'orders'"
},
"query": {
"type": "string",
"description": "SQL SELECT query (read-only)"
}
},
"required": ["database", "query"]
}
}
```
### API Integration Tool
```python
{
"name": "call_api",
"description": "Make an HTTP request to an external API",
"input_schema": {
"type": "object",
"properties": {
"method": {
"type": "string",
"description": "HTTP method: GET, POST, PUT, DELETE"
},
"endpoint": {
"type": "string",
"description": "API endpoint URL"
},
"headers": {
"type": "object",
"description": "Request headers as key-value pairs"
},
"body": {
"type": "object",
"description": "Request body for POST/PUT requests"
}
},
"required": ["method", "endpoint"]
}
}
```
### File Operation Tool
```python
{
"name": "file_operation",
"description": "Read, write, or manipulate files",
"input_schema": {
"type": "object",
"properties": {
"operation": {
"type": "string",
"description": "Operation: 'read', 'write', 'append', 'delete'"
},
"path": {
"type": "string",
"description": "File path"
},
"content": {
"type": "string",
"description": "Content for write/append operations"
}
},
"required": ["operation", "path"]
}
}
```
## Debugging Tool Use
### Logging Tool Calls
```python
def debug_tool_use(response):
for i, content in enumerate(response.content):
if content.type == "tool_use":
print(f"Tool Call #{i+1}")
print(f" Name: {content.name}")
print(f" ID: {content.id}")
print(f" Input: {json.dumps(content.input, indent=2)}")
elif content.type == "text":
print(f"Text: {content.text}")
```
### Testing Tools
```python
def test_tool_definition(tool_def, test_cases):
"""Test a tool definition with various inputs"""
for test in test_cases:
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1000,
tools=[tool_def],
messages=[{"role": "user", "content": test["query"]}]
)
# Check if tool was called
tool_called = any(c.type == "tool_use" for c in response.content)
print(f"Query: {test['query']}")
print(f"Expected tool call: {test['should_call_tool']}")
print(f"Actual tool call: {tool_called}")
print(f"Match: {'✓' if tool_called == test['should_call_tool'] else '✗'}\n")
```
## Performance Optimization
### 1. Minimize Tool Schema Complexity
- Keep input schemas flat when possible
- Avoid deeply nested objects
- Use simple types
### 2. Tool Description Optimization
- Front-load important information in descriptions
- Include examples in descriptions when helpful
- Specify units, formats, and constraints
### 3. Batch Operations
```python
{
"name": "batch_operation",
"description": "Process multiple items in a single call",
"input_schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"description": "Array of items to process"
}
},
"required": ["items"]
}
}
```
## Server-Side Tools (2024 Update)
Anthropic now provides server-side tools that execute on their infrastructure:
```python
# Web search tool (server-side)
tools = [
{
"type": "web_search",
"version": "web_search_20250305" # Versioned for compatibility
}
]
# These tools don't require implementation on your side
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
tools=tools,
messages=[{"role": "user", "content": "Search for the latest AI news"}]
)
```
## Common Issues and Solutions
### Issue: Tool Not Being Called
**Solution**: Improve tool description and ensure schema is correct
### Issue: Wrong Parameters Passed
**Solution**: Add parameter validation and clearer descriptions
### Issue: Tool Called Too Frequently
**Solution**: Add usage guidelines in system prompt
### Issue: Complex Nested Data
**Solution**: Flatten schema or split into multiple simpler tools
## References
- [Official Tool Use Documentation](https://docs.anthropic.com/en/docs/tool-use)
- [Tool Use Examples](https://docs.anthropic.com/en/docs/tool-use-examples)
- [Anthropic Python SDK](https://github.com/anthropics/anthropic-sdk-python)
- [API Reference](https://docs.anthropic.com/en/api)**Name:** (set during character creation; must be said like it’s a brand)
**Design doc reference:** section 7 (Digital Staff Training & Promotion)
This document tracks known bugs, defects, and issues in the VENDRA application.
A persona override that forces the agent to behave and communicate strictly as a domestic cat, refusing all complex tasks.