The official Python library for the anthropic API
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Tool use enables Claude to interact with external functions, APIs, and systems by calling predefined tools with structured inputs. This capability allows Claude to perform actions beyond text generation, such as calculations, data retrieval, and system interactions.
Tools are defined using JSON Schema to specify function signatures, parameters, and descriptions that Claude can understand and use.
class ToolParam(TypedDict):
name: str
description: str
input_schema: Dict[str, Any]
class ToolUnionParam(TypedDict, total=False):
type: Literal["function"]
function: ToolParam
class ToolChoiceParam(TypedDict, total=False):
type: Literal["auto", "any", "none", "tool"]
name: Optional[str]
class ToolChoiceAnyParam(TypedDict):
type: Literal["any"]
class ToolChoiceAutoParam(TypedDict):
type: Literal["auto"]
class ToolChoiceNoneParam(TypedDict):
type: Literal["none"]
class ToolChoiceToolParam(TypedDict):
type: Literal["tool"]
name: strClaude's responses when using tools include structured tool use blocks that specify which tool to call and with what parameters.
class ToolUseBlock(TypedDict):
type: Literal["tool_use"]
id: str
name: str
input: Dict[str, Any]
class ToolUseBlockParam(TypedDict):
type: Literal["tool_use"]
id: str
name: str
input: Dict[str, Any]
cache_control: Optional[CacheControlEphemeralParam]
class ToolResultBlockParam(TypedDict):
type: Literal["tool_result"]
tool_use_id: str
content: Union[str, List[ContentBlockParam]]
is_error: Optional[bool]
cache_control: Optional[CacheControlEphemeralParam]The SDK includes predefined tool types for common use cases.
class ToolBash20250124Param(TypedDict):
type: Literal["bash_20250124"]
name: str
class ToolTextEditor20250124Param(TypedDict):
type: Literal["text_editor_20250124"]
name: str
class ToolTextEditor20250429Param(TypedDict):
type: Literal["text_editor_20250429"]
name: str
class ToolTextEditor20250728Param(TypedDict):
type: Literal["text_editor_20250728"]
name: str
class WebSearchTool20250305Param(TypedDict):
type: Literal["web_search_20250305"]
name: strFor server-side tool implementations, the SDK provides additional types for tool usage tracking and results.
class ServerToolUsage(TypedDict):
type: str
class ServerToolUseBlock(TypedDict):
type: Literal["tool_use"]
id: str
name: str
input: Dict[str, Any]
class ServerToolUseBlockParam(TypedDict):
type: Literal["tool_use"]
id: str
name: str
input: Dict[str, Any]from anthropic import Anthropic
client = Anthropic()
# Define a simple calculator tool
calculator_tool = {
"name": "calculate",
"description": "Perform basic arithmetic calculations",
"input_schema": {
"type": "object",
"properties": {
"operation": {
"type": "string",
"enum": ["add", "subtract", "multiply", "divide"],
"description": "The arithmetic operation to perform"
},
"a": {
"type": "number",
"description": "First number"
},
"b": {
"type": "number",
"description": "Second number"
}
},
"required": ["operation", "a", "b"]
}
}
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "What is 15 * 7?"}
]
)
# Claude will respond with a tool use block
for content in message.content:
if content.type == "tool_use":
print(f"Tool: {content.name}")
print(f"Input: {content.input}")
# Output: Tool: calculate, Input: {"operation": "multiply", "a": 15, "b": 7}def execute_tool(tool_name: str, tool_input: dict) -> str:
"""Execute a tool and return the result"""
if tool_name == "calculate":
operation = tool_input["operation"]
a = tool_input["a"]
b = tool_input["b"]
if operation == "add":
result = a + b
elif operation == "subtract":
result = a - b
elif operation == "multiply":
result = a * b
elif operation == "divide":
if b == 0:
return "Error: Division by zero"
result = a / b
else:
return f"Error: Unknown operation {operation}"
return str(result)
return f"Error: Unknown tool {tool_name}"
# First message with tool use
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "Calculate 25 + 17"}
]
)
# Process tool use and prepare response
tool_results = []
for content in message.content:
if content.type == "tool_use":
result = execute_tool(content.name, content.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": content.id,
"content": result
})
# Send tool results back to Claude
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "Calculate 25 + 17"},
{"role": "assistant", "content": message.content},
{"role": "user", "content": tool_results}
]
)
print(response.content[0].text)
# Output: "25 + 17 = 42"# Define multiple tools
weather_tool = {
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or coordinates"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["location"]
}
}
time_tool = {
"name": "get_time",
"description": "Get current time for a timezone",
"input_schema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "Timezone (e.g., 'America/New_York', 'UTC')"
}
},
"required": ["timezone"]
}
}
tools = [calculator_tool, weather_tool, time_tool]
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "What's the weather in London and what time is it there?"}
]
)
# Claude may use multiple tools in one response
for content in message.content:
if content.type == "tool_use":
print(f"Using tool: {content.name} with {content.input}")# Force Claude to use a specific tool
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool, weather_tool],
tool_choice={"type": "tool", "name": "calculate"},
messages=[
{"role": "user", "content": "It's sunny today and 2 + 2 equals what?"}
]
)
# Claude will use the calculator tool even though weather was mentioned
# Allow any tool
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool, weather_tool],
tool_choice={"type": "any"},
messages=[
{"role": "user", "content": "Hello"}
]
)
# Claude must use one of the available tools
# Disable tool use
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool, weather_tool],
tool_choice={"type": "none"},
messages=[
{"role": "user", "content": "What is 5 + 3?"}
]
)
# Claude will respond in text without using toolsdatabase_tool = {
"name": "query_database",
"description": "Query a database with filters and options",
"input_schema": {
"type": "object",
"properties": {
"table": {
"type": "string",
"description": "Table name to query"
},
"filters": {
"type": "object",
"properties": {
"column": {"type": "string"},
"operator": {"type": "string", "enum": ["=", "!=", ">", "<", ">=", "<=", "LIKE"]},
"value": {"type": ["string", "number", "boolean"]}
},
"required": ["column", "operator", "value"]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"default": 10
},
"order_by": {
"type": "object",
"properties": {
"column": {"type": "string"},
"direction": {"type": "string", "enum": ["ASC", "DESC"]}
}
}
},
"required": ["table"]
}
}
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[database_tool],
messages=[
{"role": "user", "content": "Find all users with age greater than 25, ordered by name, limit 5"}
]
)
for content in message.content:
if content.type == "tool_use":
print(f"Query: {content.input}")
# Expected: {
# "table": "users",
# "filters": {"column": "age", "operator": ">", "value": 25},
# "limit": 5,
# "order_by": {"column": "name", "direction": "ASC"}
# }def safe_execute_tool(tool_name: str, tool_input: dict) -> tuple[str, bool]:
"""Execute tool and return (result, is_error)"""
try:
if tool_name == "divide":
a = tool_input["a"]
b = tool_input["b"]
if b == 0:
return "Cannot divide by zero", True
return str(a / b), False
else:
return f"Unknown tool: {tool_name}", True
except Exception as e:
return f"Tool execution error: {str(e)}", True
# Process with error handling
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "What is 10 divided by 0?"}
]
)
tool_results = []
for content in message.content:
if content.type == "tool_use":
result, is_error = safe_execute_tool(content.name, content.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": content.id,
"content": result,
"is_error": is_error
})
# Claude will handle the error appropriately
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "What is 10 divided by 0?"},
{"role": "assistant", "content": message.content},
{"role": "user", "content": tool_results}
]
)with client.messages.stream(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "Calculate 15 * 23 and explain the process"}
]
) as stream:
for event in stream:
if event.type == "content_block_start":
if event.content_block.type == "tool_use":
print(f"Starting tool: {event.content_block.name}")
elif event.type == "content_block_delta":
if hasattr(event.delta, 'partial_json'):
print(f"Tool input building: {event.delta.partial_json}")
elif event.type == "content_block_stop":
print("Tool definition complete")import asyncio
from anthropic import AsyncAnthropic
async def async_tool_example():
client = AsyncAnthropic()
message = await client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "What's 42 * 1.5?"}
]
)
# Process tool use
for content in message.content:
if content.type == "tool_use":
result = execute_tool(content.name, content.input)
response = await client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[calculator_tool],
messages=[
{"role": "user", "content": "What's 42 * 1.5?"},
{"role": "assistant", "content": message.content},
{"role": "user", "content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result
}
]}
]
)
return response.content[0].text
result = asyncio.run(async_tool_example())