CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-anthropic

The official Python library for the anthropic API

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

tools.mddocs/

Tool Use (Function Calling)

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.

Capabilities

Tool Definition

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: str

Tool Use Blocks

Claude'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]

Built-in Tool Types

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: str

Server-side Tool Usage

For 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]

Usage Examples

Basic Tool Definition

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}

Tool Execution and Response

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"

Multiple Tools

# 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}")

Tool Choice Control

# 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 tools

Complex Tool with Nested Objects

database_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"}
        # }

Error Handling in Tools

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}
    ]
)

Streaming with Tools

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")

Async Tool Usage

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())

docs

batching.md

bedrock.md

beta.md

completions.md

configuration.md

errors.md

index.md

messages.md

models.md

streaming.md

tools.md

vertex.md

tile.json