TodayAI

GuidesAgents

用 Claude API Tool Use 调用外部工具

在 Messages API 里声明客户工具,处理 tool_use,再回传 tool_result,跑通 Claude 的外部工具闭环。

基于 Anthropic Docs 整理 · 官方资料 ↗

Claude 的 tool use 让模型在对话中调用你定义的函数,或使用 Anthropic 托管的 server tools。客户工具在你的应用里执行;server tools(如 web_search)在 Anthropic 侧执行,你直接在同一响应里看到结果。

这篇聚焦客户工具闭环:声明带 input_schema 的工具 → 读取 tool_use → 本地执行 → 用 tool_result 回传 → 再请求一次拿到最终文本。示例沿用官方 get_weather。

先把这一轮 round trip 跑稳,再扩展并行工具、server tools 或更复杂的编排。

客户工具和 server tools 差在哪

客户工具(含你自定义的工具,以及 bash、text_editor 这类由你执行的工具)会让 Claude 以 stop_reason: "tool_use" 结束,并返回一个或多个 tool_use 块。你负责执行,再发 tool_result。

Server tools(如 web_search、web_fetch、code_execution)在 Anthropic 基础设施上执行。你通常在同一次响应里看到结果,不必自己跑检索。例外是它与客户工具出现在同一批并行调用里时,仍要按 stop reason 处理。

最小学习路径先走客户工具:协议完整,也最接近你把内部 API 接到 Claude 的真实做法。

声明一个带 input_schema 的工具

每个客户工具需要 name、description 和 input_schema(JSON Schema)。description 决定 Claude 何时调用;schema 决定它能填哪些参数。

安装 Anthropic Python SDK

bash
pip install -U anthropic
export ANTHROPIC_API_KEY=...

官方 get_weather 工具定义

python
import json
import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_weather",
        "description": "Get the current weather for a given location.",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "City and state, e.g. San Francisco, CA",
                }
            },
            "required": ["location"],
        },
    }
]

第一次请求:拿到 tool_use

调用 messages.create,传入 tools 与用户问题。官方示例用 tool_choice 限制为每轮最多一个工具调用,便于把闭环看清楚。

官方:触发 get_weather

python
messages = [{"role": "user", "content": "What's the weather in San Francisco?"}]

response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=messages,
)

tool_use = next(block for block in response.content if block.type == "tool_use")
print(f"Claude called {tool_use.name} with {json.dumps(tool_use.input)}")
print(response.stop_reason)

官方文档示例模型为 claude-opus-5。若不可用,换成当前支持 tool use 的 Claude 模型。成功时你应看到 name 为 get_weather,input 含 location。

执行工具并回传 tool_result

把助手 content(含 tool_use)追加为 assistant 消息。再发一条 user 消息,content 里放 type: "tool_result",tool_use_id 对齐刚才的 id,content 为工具输出字符串。

官方:回传 tool_result 并取最终文本

python
weather = "15 degrees Celsius, partly cloudy"  # 换成你的真实查询结果
messages += [
    {"role": "assistant", "content": response.content},
    {
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": tool_use.id, "content": weather}
        ],
    },
]

followup = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=messages,
)

final_text = next(block for block in followup.content if block.type == "text")
print(final_text.text)

示例里的 weather 字符串只是占位。接到真实系统时,在这里调用你的 API,并把原始结果或摘要放进 tool_result。

对照:server tool 长什么样

若只需 Anthropic 托管的联网搜索,可声明 server tool,不必自己执行。官方最小示例如下:

官方 web_search server tool 示例

python
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=[{"type": "web_search_20260209", "name": "web_search"}],
    messages=[{"role": "user", "content": "What's the latest on the Mars rover?"}],
)
print(response.content)

客户工具与 server tools 可以组合,但排障时先单独验证一种,避免并行调用把 stop reason 搅在一起。

闭环验收清单

  • 第一次响应出现 type=tool_use 的块
  • stop_reason 为 tool_use(客户工具路径)
  • tool_result.tool_use_id 与 tool_use.id 一致
  • 第二次响应出现 text,并基于工具结果作答

生产代码还应处理多个 tool_use、工具失败(向 Claude 返回错误信息让它改策略),以及权限与超时。先把单工具同步闭环做对,再加这些分支。

最容易踩的坑

找不到 tool_use 块

打印 response.content 与 stop_reason;确认 tools 已传入,问题确实需要该工具;检查模型是否支持 tool use。

第二次请求报 tool_use_id 相关错误

必须先 append 完整的 assistant content;tool_result.tool_use_id 必须等于对应 tool_use.id。

工具执行失败后模型行为怪异

仍返回 tool_result,在 content 里说明错误,让 Claude 决定重试或换策略;不要静默吞掉失败。

模型名不可用

官方示例使用 claude-opus-5。换成账号可用且支持 tool use 的 Claude 模型。

官方资料

Anthropic Docs

Tool use with Claude