Claude学院

Claude 函数调用示例:让模型调用你的 API

所谓「Claude 函数调用」,就是用 Messages API 的 tools 参数把你的函数(通常是对你自己 API 的封装)描述给模型。模型不会替你执行代码,它只会在需要时返回一个 tool_use 请求,告诉你要调哪个工具、传什么参数;你的程序执行后把结果用 tool_result 回传,模型再据此生成最终回答。这套机制官方称为 Tool Use(工具调用),是把 Claude 接入查库、下单、查天气等真实接口的标准做法。

函数调用的完整流程

一次完整的工具调用是「四步一循环」,理解它你就掌握了全部要点:

  1. 你在请求里通过 tools 声明可用工具(名称、描述、JSON Schema 入参)。
  2. 模型判断需要调用工具,返回 stop_reason: "tool_use"content 中含一个 tool_use 块(带 idnameinput)。
  3. 你的代码执行对应函数,把返回值包装成 tool_result(用同一个 tool_use_id 关联),作为一条 user 消息发回去。
  4. 模型读到结果,生成自然语言回答;若还需要更多数据,会再次返回 tool_use,重复上述循环直到 stop_reason 变为 end_turn

整个过程都走同一个接口 POST /v1/messages,鉴权头是 x-api-keyanthropic-version: 2023-06-01。如果你还没跑通基础请求,建议先看 Claude API 怎么调用?从注册到第一次请求完整教程

定义一个工具:JSON Schema 是关键

工具定义包含三部分:namedescriptioninput_schemadescription 直接决定模型「什么时候调、怎么调」,要写清楚用途和触发条件,不要只写一个词。

{
  "name": "get_weather",
  "description": "查询指定城市的实时天气。当用户询问某地天气、温度或是否下雨时调用。",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": { "type": "string", "description": "城市名,如 北京、上海" },
      "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位" }
    },
    "required": ["city"]
  }
}

Python 完整示例(anthropic 官方 SDK)

pip install anthropic,并设置环境变量 ANTHROPIC_API_KEY。下面这段代码声明 get_weather,手动处理一轮工具调用循环,可直接运行:

from anthropic import Anthropic

client = Anthropic()

tools = [{
    "name": "get_weather",
    "description": "查询指定城市的实时天气。用户问天气、温度时调用。",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string", "description": "城市名"}},
        "required": ["city"],
    },
}]

def get_weather(city: str) -> str:
    # 这里换成你真实的 API 调用,例如 requests.get(...)
    return f"{city}:晴,26 摄氏度"

messages = [{"role": "user", "content": "北京今天天气怎么样?"}]

while True:
    resp = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )
    # 把模型本轮回复(含 tool_use 块)原样追加进历史
    messages.append({"role": "assistant", "content": resp.content})

    if resp.stop_reason != "tool_use":
        # 没有再请求工具,输出最终文本
        print("".join(b.text for b in resp.content if b.type == "text"))
        break

    # 执行所有被请求的工具,结果一次性回传
    tool_results = []
    for block in resp.content:
        if block.type == "tool_use":
            output = get_weather(**block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,   # 必须与 tool_use 的 id 对应
                "content": output,
            })
    messages.append({"role": "user", "content": tool_results})

几个易踩的坑:必须把含 tool_useassistant 回复完整追加进 messages,否则下一轮模型会找不到上下文;tool_use_id 必须精确匹配;如果一次返回多个 tool_use(并行调用),要把所有 tool_result 放进同一条 user 消息里再发。关于 Tool Use 的更多细节和错误处理,可参考 Claude Tool Use 工具调用怎么用?完整代码实战

Node.js 完整示例(@anthropic-ai/sdk)

安装 npm install @anthropic-ai/sdk,逻辑与 Python 一致:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const tools = [{
  name: "get_weather",
  description: "查询指定城市的实时天气。用户问天气、温度时调用。",
  input_schema: {
    type: "object",
    properties: { city: { type: "string", description: "城市名" } },
    required: ["city"],
  },
}];

function getWeather(city) {
  return `${city}:晴,26 摄氏度`; // 替换为真实 API 调用
}

let messages = [{ role: "user", content: "上海现在多少度?" }];

while (true) {
  const resp = await client.messages.create({
    model: "claude-opus-4-8",
    max_tokens: 1024,
    tools,
    messages,
  });
  messages.push({ role: "assistant", content: resp.content });

  if (resp.stop_reason !== "tool_use") {
    console.log(resp.content.filter(b => b.type === "text").map(b => b.text).join(""));
    break;
  }

  const toolResults = resp.content
    .filter(b => b.type === "tool_use")
    .map(b => ({
      type: "tool_result",
      tool_use_id: b.id,
      content: getWeather(b.input.city),
    }));
  messages.push({ role: "user", content: toolResults });
}

更系统的 Node 调用与流式输出写法,见 Claude API Node.js 调用示例:从安装到流式输出

控制调用行为:tool_choice 与错误回传

通过 tool_choice 可以控制模型是否、以及如何使用工具:

取值行为
{"type": "auto"}由模型决定是否调用(默认)
{"type": "any"}必须至少调用一个工具
{"type": "tool", "name": "get_weather"}强制调用指定工具
{"type": "none"}禁止调用工具

当你的 API 执行失败时,不要静默吞掉错误。把 tool_result 标记为 "is_error": true 并附上错误信息,模型会理解并换一种方式处理或向用户说明:

{
  "type": "tool_result",
  "tool_use_id": "toolu_xxx",
  "content": "查询失败:城市名无法识别",
  "is_error": true
}

从函数调用到 Agent 与 MCP

上面的手写循环就是一个最小 Agent:模型决策、你执行工具、结果回流。当工具数量变多、逻辑变复杂时,可以考虑用 MCP(模型上下文协议)把工具标准化为可复用的服务,让 Claude 桌面版、Claude Code 乃至 API 都能连。想先理解概念,看 MCP 是什么?一篇讲清 Claude 模型上下文协议;想动手搭一个服务器,看 MCP Server 怎么搭建?Python 从零开发一个服务器

常见问题

Claude 函数调用支持哪些模型?

当前主力模型 Claude Opus 4.8、Claude Sonnet 4.6、Claude Haiku 4.5 都支持 Tool Use。模型字符串分别为 claude-opus-4-8claude-sonnet-4-6claude-haiku-4-5。一般推荐 Opus 4.8 处理复杂工具编排,Haiku 4.5 处理简单高频调用以控制成本。

工具调用会额外收费吗?

工具定义和模型返回的 tool_use、你回传的 tool_result 都按普通输入/输出 Token 计费,没有单独的「函数调用费」。多轮循环会累加 Token,工具描述写得越长、轮次越多消耗越大,具体价格以 Anthropic 官网为准。想省钱可参考 Claude API 怎么省钱?5 个降低 Token 成本的方法

为什么我解析 input 时报错?

不要对 tool_useinput 做原始字符串匹配。新版模型在工具入参里可能使用不同的 JSON 转义(如 Unicode 或斜杠转义),务必用 SDK 已解析好的对象(Python 里 block.input 已是 dict)或 json.loads()/JSON.parse() 处理,而不是手动切字符串。

Claude API 开发