toMedia
Claude API

Tool Use(函数调用)

让 Claude 调用外部函数 — 工具定义、调用流程、并行工具与最佳实践

概述

Tool Use 允许 Claude 请求和使用外部函数,是构建与数据库、API 等外部系统交互的 Agent 的关键能力。

定义工具

每个工具需要 namedescriptioninput_schema(JSON Schema):

tools = [
    {
        "name": "get_weather",
        "description": "获取指定位置的当前天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市名称,如 北京、上海"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "温度单位(默认: celsius)"
                }
            },
            "required": ["location"]
        }
    },
    {
        "name": "calculate",
        "description": "执行数学计算",
        "input_schema": {
            "type": "object",
            "properties": {
                "operation": {
                    "type": "string",
                    "enum": ["add", "subtract", "multiply", "divide"]
                },
                "a": {"type": "number"},
                "b": {"type": "number"}
            },
            "required": ["operation", "a", "b"]
        }
    }
]

完整调用流程

Tool Use 是一个 4 步流程:

import anthropic
import json

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_weather",
        "description": "获取当前天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {"type": "string"}
            },
            "required": ["location"]
        }
    }
]

# 第 1 步:发送带工具的消息
response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "巴黎现在天气怎么样?"}
    ]
)

# 第 2 步:检查 Claude 是否要调用工具
for block in response.content:
    if block.type == "tool_use":
        tool_name = block.name
        tool_input = block.input
        tool_use_id = block.id

        # 第 3 步:执行工具(这里模拟)
        tool_result = f"{tool_input['location']}天气:22°C,晴"

        # 第 4 步:将工具结果返回给 Claude
        response = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=1024,
            tools=tools,
            messages=[
                {"role": "user", "content": "巴黎现在天气怎么样?"},
                {"role": "assistant", "content": response.content},
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use_id,
                            "content": tool_result
                        }
                    ]
                }
            ]
        )
        print(response.content[0].text)

自动工具循环

处理多步工具调用的完整循环:

import anthropic
import json

client = anthropic.Anthropic()

def execute_tool(name: str, input: dict):
    """根据工具名执行对应函数"""
    if name == "get_weather":
        return {"temperature": 22, "condition": "晴"}
    elif name == "calculate":
        ops = {"add": lambda a, b: a + b, "subtract": lambda a, b: a - b,
               "multiply": lambda a, b: a * b, "divide": lambda a, b: a / b}
        return ops[input["operation"]](input["a"], input["b"])
    return f"未知工具: {name}"

messages = [
    {"role": "user", "content": "旧金山天气怎样?另外算一下 5 + 3"}
]

response = client.messages.create(
    model="claude-opus-4-6", max_tokens=1024,
    tools=tools, messages=messages
)

# 循环处理,直到 Claude 不再调用工具
while response.stop_reason == "tool_use":
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = execute_tool(block.name, block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": json.dumps(result)
            })

    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

    response = client.messages.create(
        model="claude-opus-4-6", max_tokens=1024,
        tools=tools, messages=messages
    )

# 输出最终回复
for block in response.content:
    if hasattr(block, 'text'):
        print(block.text)

并行工具调用

Claude 可以在单次响应中同时调用多个工具:

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "查一下巴黎和纽约的天气,以及那里现在几点?"}
    ]
)

# Claude 可能在一次响应中调用多个工具
tool_calls = [b for b in response.content if b.type == "tool_use"]
print(f"Claude 并行调用了 {len(tool_calls)} 个工具")
for tc in tool_calls:
    print(f"  - {tc.name}: {tc.input}")

tool_choice 控制

通过 tool_choice 参数控制 Claude 的工具使用行为:

行为
"auto"Claude 自行决定(默认)
"any"强制使用某个工具
{"type": "tool", "name": "xxx"}强制使用指定工具
"none"禁止使用工具

最佳实践

  1. 详细描述:清楚说明工具的功能、适用场景和限制
  2. 清晰的 Schema:使用描述性属性名,包含默认值
  3. 错误处理:工具失败时返回有意义的错误信息
  4. Streaming 保持:使用流式输出时,将 thinking blocks 原样传回
  5. Strict 模式:关键工作流使用 "strict": true 保证输入合规

On this page