logo

Claude Tool Use (工具调用)

Tool Use 这页我按 Anthropic 官方 Tool use with ClaudeHow to implement tool use 核过了。当前官方把 tool access 直接称为构建 agent 时的高杠杆能力之一,这个判断我认同。

把它说得更实际一点:模型负责决定“什么时候该借工具”,你负责决定“工具到底能做什么、权限边界在哪里、结果怎么回传”。

什么是 Tool Use?

Tool Use 让 Claude 能够:

  1. 理解用户意图
  2. 决定使用哪个工具
  3. 提取工具参数
  4. 等待工具结果并生成回复
用户: "北京今天天气怎么样?"
     ↓
Claude: 需要使用 get_weather 工具,参数 city="北京"
     ↓
你的代码: 调用天气 API,返回结果
     ↓
Claude: "北京今天晴朗,气温 25°C,适合户外活动。"

读者导向:建议实践顺序

  1. 先做单工具闭环(请求 -> tool_use -> tool_result -> 最终回复)。
  2. 再做多工具路由和并行调用。
  3. 最后补权限、审计、失败重试与幂等策略。

官方现在怎么划分工具

Anthropic 官方现在把工具分成两类:

  1. Client tools
  2. Server tools

其中:

  • Client tools 由你自己实现和执行
  • Server tools 由 Anthropic 服务器执行,比如 web search、web fetch 这类

这点比早期“所有工具都自己实现”的心智更完整,所以现在写工具链路时,最好先分清你到底在接哪一类工具。

基础用法

定义工具

tools = [
    {
        "name": "get_weather",
        "description": "获取指定城市的当前天气信息",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市名称,如:北京、上海、深圳"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "温度单位,默认摄氏度"
                }
            },
            "required": ["city"]
        }
    }
]

调用 API

import anthropic
import json

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "北京天气怎么样?"}
    ]
)

# 检查响应类型
for block in response.content:
    if block.type == "tool_use":
        print(f"工具: {block.name}")
        print(f"参数: {block.input}")
        print(f"ID: {block.id}")

执行工具并返回结果

def get_weather(city: str, unit: str = "celsius") -> str:
    """模拟天气 API"""
    return f"{city}今天晴,气温 25°C"

# 1. 第一次调用 - 获取工具调用请求
response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "北京天气怎么样?"}]
)

# 2. 检查并执行工具
messages = [{"role": "user", "content": "北京天气怎么样?"}]
messages.append({"role": "assistant", "content": response.content})

for block in response.content:
    if block.type == "tool_use":
        # 执行工具
        result = get_weather(**block.input)

        # 添加工具结果
        messages.append({
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": result
            }]
        })

# 3. 获取最终回复
final_response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=messages
)

print(final_response.content[0].text)

多工具定义

tools = [
    {
        "name": "get_weather",
        "description": "获取城市天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "城市名"}
            },
            "required": ["city"]
        }
    },
    {
        "name": "search_web",
        "description": "搜索网络信息",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "搜索关键词"}
            },
            "required": ["query"]
        }
    },
    {
        "name": "send_email",
        "description": "发送邮件",
        "input_schema": {
            "type": "object",
            "properties": {
                "to": {"type": "string", "description": "收件人邮箱"},
                "subject": {"type": "string", "description": "邮件主题"},
                "body": {"type": "string", "description": "邮件内容"}
            },
            "required": ["to", "subject", "body"]
        }
    }
]

控制工具使用

tool_choice 参数

# 自动决定(默认)
tool_choice = {"type": "auto"}

# 强制使用特定工具
tool_choice = {"type": "tool", "name": "get_weather"}

# 强制使用任意一个工具
tool_choice = {"type": "any"}

# 禁止使用工具
tool_choice = {"type": "none"}  # 或不传 tools 参数

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

Anthropic 官方当前的一个重要更新

官方现在还专门增加了 strict: true 的 strict tool use 说明,用来保证工具输入严格符合 schema。这对生产环境很重要,因为很多错误不是模型不会调工具,而是参数格式稍微漂掉一点,后端就挂了。

常见误区

  • 把工具 schema 写得过于宽松,导致参数不稳定
  • 工具执行失败只返回“失败”,不返回结构化错误信息
  • 忽略权限边界,让模型可触达不该调用的高风险接口

一句轻松提醒:
Tool Use 像给 AI 发工作证,权限开太大,出事概率会同步放大。

并行工具调用

Claude 可以同时请求多个工具:

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "北京和上海的天气分别怎么样?"}
    ]
)

# 可能返回多个 tool_use blocks
tool_calls = [block for block in response.content if block.type == "tool_use"]
print(f"需要调用 {len(tool_calls)} 个工具")

for tc in tool_calls:
    print(f"- {tc.name}: {tc.input}")

处理并行调用

def process_tool_calls(response, available_functions):
    """处理所有工具调用"""
    tool_results = []

    for block in response.content:
        if block.type == "tool_use":
            func = available_functions.get(block.name)
            if func:
                result = func(**block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": str(result)
                })

    return tool_results

# 使用
available_functions = {
    "get_weather": get_weather,
    "search_web": search_web,
    "send_email": send_email
}

tool_results = process_tool_calls(response, available_functions)

完整示例:AI 助手

import anthropic
import json

client = anthropic.Anthropic()

# 工具定义
tools = [
    {
        "name": "get_weather",
        "description": "获取城市天气信息",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "城市名"}
            },
            "required": ["city"]
        }
    },
    {
        "name": "calculate",
        "description": "数学计算",
        "input_schema": {
            "type": "object",
            "properties": {
                "expression": {"type": "string", "description": "数学表达式"}
            },
            "required": ["expression"]
        }
    }
]

# 工具实现
def get_weather(city: str) -> str:
    weather_data = {
        "北京": "晴,25°C",
        "上海": "多云,28°C",
    }
    return weather_data.get(city, f"{city}天气数据暂不可用")

def calculate(expression: str) -> str:
    try:
        return str(eval(expression))
    except:
        return "计算错误"

available_functions = {
    "get_weather": get_weather,
    "calculate": calculate
}

def chat(user_message: str):
    messages = [{"role": "user", "content": user_message}]

    while True:
        response = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=1024,
            tools=tools,
            messages=messages
        )

        # 检查是否有工具调用
        tool_uses = [b for b in response.content if b.type == "tool_use"]

        if not tool_uses:
            # 没有工具调用,返回文本响应
            text_blocks = [b for b in response.content if b.type == "text"]
            return text_blocks[0].text if text_blocks else ""

        # 处理工具调用
        messages.append({"role": "assistant", "content": response.content})

        tool_results = []
        for tool_use in tool_uses:
            func = available_functions.get(tool_use.name)
            if func:
                result = func(**tool_use.input)
                print(f"[调用] {tool_use.name}({tool_use.input}) -> {result}")
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": tool_use.id,
                    "content": result
                })

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

# 测试
print(chat("北京天气怎么样?"))
print(chat("123 * 456 等于多少?"))
print(chat("北京天气如何?另外帮我算一下 15 的平方"))

工具结果格式

成功结果

{
    "type": "tool_result",
    "tool_use_id": "toolu_xxx",
    "content": "北京今天晴,25°C"
}

错误结果

{
    "type": "tool_result",
    "tool_use_id": "toolu_xxx",
    "content": "错误:无法获取天气数据",
    "is_error": True
}

图片结果

{
    "type": "tool_result",
    "tool_use_id": "toolu_xxx",
    "content": [
        {
            "type": "image",
            "source": {
                "type": "base64",
                "media_type": "image/png",
                "data": "base64_encoded_data"
            }
        },
        {
            "type": "text",
            "text": "生成的图表"
        }
    ]
}

最佳实践

1. 清晰的工具描述

# ❌ 不够清晰
"description": "获取数据"

# ✅ 清晰明确
"description": "获取指定城市的实时天气信息,包括温度、湿度和天气状况。支持中国主要城市。"

2. 详细的参数说明

"properties": {
    "date": {
        "type": "string",
        "description": "查询日期,格式为 YYYY-MM-DD,如 2024-01-15。不填则查询今天。"
    }
}

3. 使用枚举限制选项

"status": {
    "type": "string",
    "enum": ["pending", "approved", "rejected"],
    "description": "订单状态"
}

4. 错误处理

def safe_tool_call(func, **kwargs):
    try:
        return func(**kwargs)
    except Exception as e:
        return f"工具执行错误: {str(e)}"

与 OpenAI Function Calling 的区别

特性Claude Tool UseOpenAI Function Calling
参数名input_schemaparameters
工具类型直接定义type: "function" 包装
结果格式tool_resultfunction role
控制参数tool_choicetool_choice

下一步


提示:Tool Use 是构建 AI Agent 的基础,结合多个工具可以实现复杂的自动化任务。

Claude API 开发指南
AI Engineer

Claude API 开发指南

Anthropic Claude API 提供了强大的 AI 模型访问,以安全性和准确性著称,适合企业级应用。

Claude API 开发指南Tool Use

Claude Tool Use (工具调用)

Tool Use 这页我按 Anthropic 官方 Tool use with ClaudeHow to implement tool use 核过了。当前官方把 tool access 直接称为构建 agent 时的高杠杆能力之一,这个判断我认同。

把它说得更实际一点:模型负责决定“什么时候该借工具”,你负责决定“工具到底能做什么、权限边界在哪里、结果怎么回传”。

#什么是 Tool Use?

Tool Use 让 Claude 能够:

  1. 理解用户意图
  2. 决定使用哪个工具
  3. 提取工具参数
  4. 等待工具结果并生成回复
用户: "北京今天天气怎么样?"
     ↓
Claude: 需要使用 get_weather 工具,参数 city="北京"
     ↓
你的代码: 调用天气 API,返回结果
     ↓
Claude: "北京今天晴朗,气温 25°C,适合户外活动。"

#读者导向:建议实践顺序

  1. 先做单工具闭环(请求 -> tool_use -> tool_result -> 最终回复)。
  2. 再做多工具路由和并行调用。
  3. 最后补权限、审计、失败重试与幂等策略。

#官方现在怎么划分工具

Anthropic 官方现在把工具分成两类:

  1. Client tools
  2. Server tools

其中:

  • Client tools 由你自己实现和执行
  • Server tools 由 Anthropic 服务器执行,比如 web search、web fetch 这类

这点比早期“所有工具都自己实现”的心智更完整,所以现在写工具链路时,最好先分清你到底在接哪一类工具。

#基础用法

#定义工具

python
tools = [ { "name": "get_weather", "description": "获取指定城市的当前天气信息", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,如:北京、上海、深圳" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位,默认摄氏度" } }, "required": ["city"] } } ]

#调用 API

python
import anthropic import json client = anthropic.Anthropic() response = client.messages.create( model="claude-opus-4-6", max_tokens=1024, tools=tools, messages=[ {"role": "user", "content": "北京天气怎么样?"} ] ) # 检查响应类型 for block in response.content: if block.type == "tool_use": print(f"工具: {block.name}") print(f"参数: {block.input}") print(f"ID: {block.id}")

#执行工具并返回结果

python
def get_weather(city: str, unit: str = "celsius") -> str: """模拟天气 API""" return f"{city}今天晴,气温 25°C" # 1. 第一次调用 - 获取工具调用请求 response = client.messages.create( model="claude-opus-4-6", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "北京天气怎么样?"}] ) # 2. 检查并执行工具 messages = [{"role": "user", "content": "北京天气怎么样?"}] messages.append({"role": "assistant", "content": response.content}) for block in response.content: if block.type == "tool_use": # 执行工具 result = get_weather(**block.input) # 添加工具结果 messages.append({ "role": "user", "content": [{ "type": "tool_result", "tool_use_id": block.id, "content": result }] }) # 3. 获取最终回复 final_response = client.messages.create( model="claude-opus-4-6", max_tokens=1024, tools=tools, messages=messages ) print(final_response.content[0].text)

#多工具定义

python
tools = [ { "name": "get_weather", "description": "获取城市天气", "input_schema": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名"} }, "required": ["city"] } }, { "name": "search_web", "description": "搜索网络信息", "input_schema": { "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词"} }, "required": ["query"] } }, { "name": "send_email", "description": "发送邮件", "input_schema": { "type": "object", "properties": { "to": {"type": "string", "description": "收件人邮箱"}, "subject": {"type": "string", "description": "邮件主题"}, "body": {"type": "string", "description": "邮件内容"} }, "required": ["to", "subject", "body"] } } ]

#控制工具使用

#tool_choice 参数

python
# 自动决定(默认) tool_choice = {"type": "auto"} # 强制使用特定工具 tool_choice = {"type": "tool", "name": "get_weather"} # 强制使用任意一个工具 tool_choice = {"type": "any"} # 禁止使用工具 tool_choice = {"type": "none"} # 或不传 tools 参数 response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, tool_choice=tool_choice, messages=[...] )

#Anthropic 官方当前的一个重要更新

官方现在还专门增加了 strict: true 的 strict tool use 说明,用来保证工具输入严格符合 schema。这对生产环境很重要,因为很多错误不是模型不会调工具,而是参数格式稍微漂掉一点,后端就挂了。

#常见误区

  • 把工具 schema 写得过于宽松,导致参数不稳定
  • 工具执行失败只返回“失败”,不返回结构化错误信息
  • 忽略权限边界,让模型可触达不该调用的高风险接口

一句轻松提醒:
Tool Use 像给 AI 发工作证,权限开太大,出事概率会同步放大。

#并行工具调用

Claude 可以同时请求多个工具:

python
response = client.messages.create( model="claude-opus-4-6", max_tokens=1024, tools=tools, messages=[ {"role": "user", "content": "北京和上海的天气分别怎么样?"} ] ) # 可能返回多个 tool_use blocks tool_calls = [block for block in response.content if block.type == "tool_use"] print(f"需要调用 {len(tool_calls)} 个工具") for tc in tool_calls: print(f"- {tc.name}: {tc.input}")

#处理并行调用

python
def process_tool_calls(response, available_functions): """处理所有工具调用""" tool_results = [] for block in response.content: if block.type == "tool_use": func = available_functions.get(block.name) if func: result = func(**block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": str(result) }) return tool_results # 使用 available_functions = { "get_weather": get_weather, "search_web": search_web, "send_email": send_email } tool_results = process_tool_calls(response, available_functions)

#完整示例:AI 助手

python
import anthropic import json client = anthropic.Anthropic() # 工具定义 tools = [ { "name": "get_weather", "description": "获取城市天气信息", "input_schema": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名"} }, "required": ["city"] } }, { "name": "calculate", "description": "数学计算", "input_schema": { "type": "object", "properties": { "expression": {"type": "string", "description": "数学表达式"} }, "required": ["expression"] } } ] # 工具实现 def get_weather(city: str) -> str: weather_data = { "北京": "晴,25°C", "上海": "多云,28°C", } return weather_data.get(city, f"{city}天气数据暂不可用") def calculate(expression: str) -> str: try: return str(eval(expression)) except: return "计算错误" available_functions = { "get_weather": get_weather, "calculate": calculate } def chat(user_message: str): messages = [{"role": "user", "content": user_message}] while True: response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, messages=messages ) # 检查是否有工具调用 tool_uses = [b for b in response.content if b.type == "tool_use"] if not tool_uses: # 没有工具调用,返回文本响应 text_blocks = [b for b in response.content if b.type == "text"] return text_blocks[0].text if text_blocks else "" # 处理工具调用 messages.append({"role": "assistant", "content": response.content}) tool_results = [] for tool_use in tool_uses: func = available_functions.get(tool_use.name) if func: result = func(**tool_use.input) print(f"[调用] {tool_use.name}({tool_use.input}) -> {result}") tool_results.append({ "type": "tool_result", "tool_use_id": tool_use.id, "content": result }) messages.append({"role": "user", "content": tool_results}) # 测试 print(chat("北京天气怎么样?")) print(chat("123 * 456 等于多少?")) print(chat("北京天气如何?另外帮我算一下 15 的平方"))

#工具结果格式

#成功结果

python
{ "type": "tool_result", "tool_use_id": "toolu_xxx", "content": "北京今天晴,25°C" }

#错误结果

python
{ "type": "tool_result", "tool_use_id": "toolu_xxx", "content": "错误:无法获取天气数据", "is_error": True }

#图片结果

python
{ "type": "tool_result", "tool_use_id": "toolu_xxx", "content": [ { "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "base64_encoded_data" } }, { "type": "text", "text": "生成的图表" } ] }

#最佳实践

#1. 清晰的工具描述

python
# ❌ 不够清晰 "description": "获取数据" # ✅ 清晰明确 "description": "获取指定城市的实时天气信息,包括温度、湿度和天气状况。支持中国主要城市。"

#2. 详细的参数说明

python
"properties": { "date": { "type": "string", "description": "查询日期,格式为 YYYY-MM-DD,如 2024-01-15。不填则查询今天。" } }

#3. 使用枚举限制选项

python
"status": { "type": "string", "enum": ["pending", "approved", "rejected"], "description": "订单状态" }

#4. 错误处理

python
def safe_tool_call(func, **kwargs): try: return func(**kwargs) except Exception as e: return f"工具执行错误: {str(e)}"

#与 OpenAI Function Calling 的区别

特性Claude Tool UseOpenAI Function Calling
参数名input_schemaparameters
工具类型直接定义type: "function" 包装
结果格式tool_resultfunction role
控制参数tool_choicetool_choice

#下一步


提示:Tool Use 是构建 AI Agent 的基础,结合多个工具可以实现复杂的自动化任务。

System Design

系统设计必备:核心概念 + 经典案例

快速掌握取舍与设计套路,备战系统设计面试。

进入 System Design →

相关路线图