切换语言
切换主题

Agent 工具调用实战:让 AI 调用外部 API 和服务

你有没有遇到过这种情况:想让 AI 帮你查个天气、读个文件,或者调个 API,结果它只能回你一句”我无法访问外部数据”。

挺烦人的,对吧。

其实这不是 AI 不够聪明,而是它缺少了一项核心能力——工具调用。今天我们就来聊聊这个让 AI 从”只会聊天”变成”能干活”的技术。


什么是 AI 工具调用?

说白了,工具调用就是给 AI 配备了一双手。

传统的大模型只能基于训练数据回答问题。你问它”北京今天天气怎么样”,它只能告诉你”我无法获取实时数据”。但有了工具调用,AI 可以主动请求执行某个函数,比如调用天气 API,然后把结果返回给你。

这个能力有多重要?嗯,大概就是从”只会纸上谈兵的军师”到”能亲自带兵打仗的将军”的跨越。

三种主流方案

目前市面上主要有三种工具调用方案:

方案代表产品适用场景
Function CallingOpenAI GPT结构化输出、简单 API 调用
Tool UseClaude复杂工具链、多步骤任务
MCPClaude Code标准化工具生态

选哪个?看你需求。简单场景用 OpenAI Function Calling 就够了;复杂的 agent 系统,Claude Tool Use 更合适;想搭工具生态,MCP 是趋势。


OpenAI Function Calling:从入门到上手

先看 OpenAI 的方案。它的 Function Calling 设计得很简洁,核心就三步:

  1. 定义工具(告诉 AI 有哪些工具可用)
  2. AI 决定调用哪个工具(返回函数名和参数)
  3. 你执行工具,把结果喂回去

一个完整的例子

假设我们要做一个天气查询工具。首先定义工具 Schema:

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

注意那个 description 字段——千万别敷衍。AI 就是靠它判断什么时候该调这个工具的。我之前见过有人写 “获取天气”,结果 AI 根本不知道什么场景该用。改成 “获取指定城市的当前天气信息” 后,调用准确率直接从 60% 提到 95%。

接下来发送请求:

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "user", "content": "北京今天热不热?"}
    ],
    tools=tools
)

AI 会返回一个工具调用请求:

tool_call = response.choices[0].message.tool_calls[0]
# tool_call.function.name = "get_weather"
# tool_call.function.arguments = '{"city": "北京"}'

然后你执行真正的函数调用,把结果返回:

# 执行你的天气 API 调用
weather_result = get_weather_from_api("北京")

# 把结果喂回去
final_response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "user", "content": "北京今天热不热?"},
        response.choices[0].message,  # AI 的工具调用请求
        {
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(weather_result)
        }
    ]
)

AI 就会根据天气数据给你一个自然的回答:“北京今天 28 度,挺热的,出门记得防晒。“

Strict Mode:保证输出稳定性

2024 年 OpenAI 推出了 Strict Mode,这玩意儿解决了 JSON Schema 匹配不稳定的问题。启用方式很简单:

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "strict": True,  # 加这一行
        # ... 其他字段
    }
}]

开启后,AI 返回的参数保证 100% 符合你定义的 Schema。生产环境强烈建议打开,不然你可能会遇到各种奇怪的解析错误。


Claude Tool Use:更强大的工具链

Claude 的 Tool Use 在设计理念上和 OpenAI 有几个重要区别。

并行调用

Claude 支持一次返回多个工具调用。比如用户问 “对比一下北京和上海的天气”,Claude 会一次性请求调用两次 get_weather

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    messages=[{"role": "user", "content": "对比一下北京和上海的天气"}],
    tools=tools
)

# response.content 可能包含两个 tool_use block
for block in response.content:
    if block.type == "tool_use":
        print(f"调用 {block.name},参数:{block.input}")

这在处理复杂任务时特别有用。OpenAI 也支持并行调用,但 Claude 的实现更优雅——它会智能判断哪些调用可以并行,哪些必须串行。

Tool Choice 策略

Claude 提供了更细粒度的工具选择控制:

# 自动选择(默认)
tool_choice = {"type": "auto"}

# 强制使用工具(不用工具就不回答)
tool_choice = {"type": "any"}

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

什么时候用 any?当你确定用户的问题必须通过工具才能回答时。比如查询订单状态,不调数据库根本没法答,那就强制 AI 必须用工具。

错误处理

工具调用失败是常态。API 超时、网络抖动、参数错误……Claude 提供了一个优雅的错误处理机制:

tool_result = {
    "type": "tool_result",
    "tool_use_id": tool_use.id,
    "content": "API 调用失败:连接超时",  # 直接告诉 AI 失败原因
    "is_error": True  # 标记为错误
}

AI 看到错误后,会尝试其他方案或者给用户一个友好的提示。这点比直接抛异常强多了——用户不会看到一堆技术报错,而是”抱歉,天气服务暂时不可用,请稍后再试”。


MCP:工具标准化的未来

说到工具调用,绕不开 MCP(Model Context Protocol)。

为什么需要 MCP?

现在的工具生态太碎片化了。想给 Claude 接一个 GitHub 工具、给 ChatGPT 接一个 Slack 工具,每个都要单独开发。MCP 的目标就是建立一套统一标准——写一次工具,到处能用。

架构很简单:

MCP Client(Claude Code/Claude Desktop)

    MCP Server(工具提供者)

   External Tool/API

Claude Code 的 MCP 实践

Claude Code 是目前 MCP 支持最好的产品。用 /mcp 命令就能配置工具:

# 添加一个远程 MCP 服务器
claude mcp add my-server --transport sse --url https://api.example.com/mcp

# 添加一个本地工具
claude mcp add local-tool --command node ./my-tool.js

配置好后,Claude Code 会自动发现服务器提供的工具。你在对话里提到相关内容,它就会自动调用。

举个例子。我配置了一个 get-github-issues 工具,然后问 Claude Code:“这个项目的 open issues 有哪些?” 它直接调用工具,把结果整理给我。

整个过程我完全感知不到工具的存在——这才是工具调用的理想状态。


生产环境的几个坑

工具调用听起来简单,但真上了生产,坑还是不少的。

安全性:别让 AI 乱来

AI 可能会调用你不希望它调用的 API。解决方案:

  1. 工具权限分级:只给 AI 必要的工具,敏感操作需要人工确认
  2. 输入验证:AI 生成的参数要二次校验,别直接传给 API
  3. 调用审计:记录每次工具调用的参数和结果,方便回溯

我见过一个反面案例:AI 把用户的随意输入直接传给了数据库查询接口,结果……SQL 注入。虽然不是 AI 直接注入的,但它把恶意输入传了过去。所以,永远不要信任 AI 生成的参数。

超时和重试

工具调用可能失败。设置合理的超时时间,配合重试机制:

async def call_tool_with_retry(tool_func, args, max_retries=3):
    for attempt in range(max_retries):
        try:
            return await asyncio.wait_for(
                tool_func(**args),
                timeout=10.0  # 10 秒超时
            )
        except asyncio.TimeoutError:
            if attempt == max_retries - 1:
                return {"error": "工具调用超时"}
            await asyncio.sleep(1)  # 等待 1 秒后重试

Token 成本

工具定义和返回结果都会消耗 Token。特别是返回大量数据时,成本可能很高。几点建议:

  1. 精简工具描述:description 能短就短,但要说清楚
  2. 限制返回数据:API 返回的数据先过滤,只保留必要字段
  3. 使用缓存:相同查询的结果可以缓存几分钟

写在最后

工具调用是 AI Agent 的核心能力。没有它,AI 只能纸上谈兵;有了它,AI 才能真正帮你做事。

OpenAI 的 Function Calling 简洁易用,适合入门和简单场景;Claude 的 Tool Use 更强大,适合复杂的 agent 系统;MCP 是工具标准化的趋势,值得长期关注。

选哪个?看你的需求。但不管选哪个,安全性、错误处理、性能调优这三个坑,一定要提前想清楚。


参考资料

常见问题

OpenAI Function Calling 和 Claude Tool Use 有什么区别?
主要区别在于并行调用和错误处理。Claude 原生支持一次返回多个工具调用,并能智能判断哪些可并行;错误处理上,Claude 提供了 `is_error` 标记让 AI 优雅降级。OpenAI 更简洁易上手,适合简单场景。
什么时候该用 MCP 而不是直接 Function Calling?
当你需要构建工具生态、让同一套工具支持多个 AI 平台时选 MCP。MCP 提供了标准化的工具协议,写一次工具就能被 Claude、ChatGPT 等多个客户端使用,避免重复开发。
工具调用失败怎么处理?
三个建议:1)设置超时和重试机制(如 10 秒超时,最多 3 次重试);2)使用 Claude 的 `is_error: true` 标记告诉 AI 失败原因;3)准备降级方案,比如返回缓存数据或友好提示。
如何防止 AI 调用敏感 API?
权限分级是关键:只给 AI 必要的工具,敏感操作(如支付、删除)需要人工确认。另外,永远不要直接信任 AI 生成的参数,必须二次校验再传给 API。
Strict Mode 是什么?需要开启吗?
Strict Mode 是 OpenAI 2024 年推出的功能,保证 AI 返回的参数 100% 符合你定义的 JSON Schema。生产环境强烈建议开启,能避免各种解析错误。启用方式:在 function 定义中加 `"strict": true`。

8 分钟阅读 · 发布于: 2026年3月21日 · 修改于: 2026年3月22日

评论

使用 GitHub 账号登录后即可评论

相关文章