Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Anthropics Anthropic sdk python ToolUseBlock Detection

From Leeroopedia
Knowledge Sources
Domains Tool_Use, LLM, Function_Calling
Last Updated 2026-02-15 00:00 GMT

Overview

The ToolUseBlock is a Pydantic model representing a tool invocation request within a Claude API response. Detection involves checking the Message.stop_reason field and filtering the Message.content array for blocks with type == "tool_use".

API: ToolUseBlock

class ToolUseBlock(BaseModel):
    id: str
    input: Dict[str, object]
    name: str
    type: Literal["tool_use"]

Source Location

File: src/anthropic/types/tool_use_block.py, lines 11-18

Import

from anthropic.types import ToolUseBlock

Fields

Field Type Description
id str Unique identifier for this tool call (e.g., "toolu_01A09q90qw90lq917835lq9"). Used to correlate with ToolResultBlockParam.tool_use_id.
input Dict[str, object] The arguments the model generated for the tool call, conforming to the tool's input_schema.
name str The name of the tool the model wants to invoke. Matches the name field from the tool definition.
type Literal["tool_use"] Discriminator field, always "tool_use". Used to distinguish from other content block types.

StopReason Type

The Message.stop_reason field uses the StopReason type alias, defined in src/anthropic/types/stop_reason.py:

StopReason: TypeAlias = Literal[
    "end_turn", "max_tokens", "stop_sequence", "tool_use", "pause_turn", "refusal"
]

When stop_reason == "tool_use", the response contains at least one ToolUseBlock in its content array.

Detection Pattern

The standard pattern for detecting and extracting tool calls from a response:

import anthropic
from anthropic.types import ToolUseBlock

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=[get_weather.to_dict()],
    messages=[{"role": "user", "content": "What's the weather in London?"}]
)

# Step 1: Quick check via stop_reason
if message.stop_reason == "tool_use":
    # Step 2: Filter content blocks
    tool_use_blocks = [
        block for block in message.content
        if block.type == "tool_use"
    ]

    # Step 3: Process each tool call
    for block in tool_use_blocks:
        print(f"Tool: {block.name}")
        print(f"ID: {block.id}")
        print(f"Input: {block.input}")

Type-Safe Detection with isinstance

For type-narrowing in strict type-checking environments, use isinstance:

from anthropic.types import ToolUseBlock, TextBlock

for block in message.content:
    if isinstance(block, ToolUseBlock):
        # block is narrowed to ToolUseBlock
        result = dispatch_tool(block.name, block.input)
    elif isinstance(block, TextBlock):
        # block is narrowed to TextBlock
        print(block.text)

Content Block Union

The message.content array can contain multiple block types. The full union (from src/anthropic/types/content_block.py) includes:

  • TextBlock -- type: "text"
  • ToolUseBlock -- type: "tool_use"
  • ThinkingBlock -- type: "thinking"
  • RedactedThinkingBlock -- type: "redacted_thinking"

A single response can contain a mix of these types. For example, the model may emit a TextBlock with reasoning text followed by one or more ToolUseBlock entries.

Handling Multiple Tool Calls

When the model requests parallel tool use, the content array contains multiple ToolUseBlock entries:

# Example response content with parallel tool calls:
# message.content = [
#     TextBlock(type="text", text="I'll check both for you."),
#     ToolUseBlock(type="tool_use", id="toolu_abc", name="get_weather", input={"city": "London"}),
#     ToolUseBlock(type="tool_use", id="toolu_def", name="get_weather", input={"city": "Paris"}),
# ]

tool_results = []
for block in message.content:
    if block.type == "tool_use":
        result = execute_tool(block.name, block.input)
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": block.id,  # Must match each block's unique ID
            "content": str(result),
        })

Complete Detection Loop Example

import anthropic
from anthropic import beta_tool

@beta_tool
def get_weather(city: str, unit: str = "celsius") -> str:
    """Get the current weather for a city.

    Args:
        city: The city name
        unit: Temperature unit (celsius or fahrenheit)
    """
    return f"The weather in {city} is 22 degrees {unit}"

client = anthropic.Anthropic()
messages = [{"role": "user", "content": "What's the weather in London?"}]

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=[get_weather.to_dict()],
    messages=messages,
)

while response.stop_reason == "tool_use":
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = get_weather.call(block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": str(result),
            })
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        tools=[get_weather.to_dict()],
        messages=messages,
    )

# Final text response
for block in response.content:
    if block.type == "text":
        print(block.text)

Dependencies

  • pydantic: ToolUseBlock inherits from BaseModel

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment