内容阅读
Tool Calling 深入
本文迁移自 mindcarver/91ai · 原始位置
docs/agent/ai-app-tutorials/agent-workflow/tool-calling-deep-dive.md· 由 @阿新聊ai 整理。
Tool Calling 深入
TL;DR: Tool Calling 把模型的语言推理能力连接到外部系统的确定性能力。2025 年的关键变化是 MCP(Model Context Protocol)把工具调用从"硬编码"转向"动态发现"。工具设计的关键是 Schema 质量——名称、描述、参数、返回值都要像 API 一样严谨。安全边界在工具执行层,不在 Prompt 里。
Tool Calling 的本质
Tool Calling 的本质是:把模型的语言推理能力,连接到外部系统的确定性能力。
模型擅长理解意图、归纳信息、判断下一步;工具擅长查询数据、执行计算、读写文件、调用 API。Tool Calling 把两者接起来:模型决定什么时候用工具、用哪个、传什么参数;系统负责真正执行工具,把结果返回给模型。
这带来两层风险:
- 选择风险:模型可能选错工具。本该查内部知识库,却去搜互联网。
- 执行风险:工具产生真实副作用。写文件、发邮件、更新数据库、删除记录。
所以设计 Tool Calling 时,不该只关心"模型能不能调用成功",还要关心"它有没有权调用、参数是否合理、结果能否验证、调用是否可审计"。
Tool Schema:工具和模型之间的契约
一个完整 Schema 包括四部分。
name:工具名称
短、明确、可区分。用"动词_名词"格式:search_web、query_customer_profile、calculate_roi。
不要用 tool_1、helper、process 这种含糊名字。
description:工具描述
这是模型选择工具时最重要的信息。好的描述要说清三件事:做什么、适合什么场景、不适合什么场景。
差的描述:
搜索工具。
好的描述:
根据关键词搜索公开网页,返回标题、摘要、链接和来源。
适用于获取公开资料、最新资讯和行业动态。
不适用于查询企业内部文档、用户私有数据或需要登录的网站内容。
Anthropic 把工具接口设计称为 ACI(Agent-Computer Interface),提出一个检验标准:一个不熟悉系统的实习生能不能仅凭描述正确使用这个工具? 如果不能,描述就不够好。
parameters:输入参数
参数要用结构化格式定义类型、是否必填、取值范围和格式要求。
参数设计的关键原则:
- 语义明确:
query比text清楚,start_date比date1清楚 - 格式明确:日期必须是
YYYY-MM-DD就写清楚,不要指望模型自动猜 - 范围明确:
max_results只能是 1 到 10 就在 Schema 和工具实现里都限制 - 来源明确:
user_id、session_id、tenant_id由系统填充,不让模型猜
模型负责语义参数,系统负责身份、权限和环境参数。
returns:输出格式
返回结构要稳定。不要这次返回字符串,下次返回数组。模型需要依赖稳定结构继续推理。
工具选择:为什么模型会选错
模型选择工具主要依赖两个信息:工具描述和当前任务上下文。
描述含糊 → 模型靠名字猜;上下文混乱 → 模型理解错任务。于是出现"莫名其妙"的工具调用。
三种方法提高稳定性:
减少候选工具。 不要把所有工具暴露给所有 Agent。行业研究 Agent 不需要发邮件工具。Anthropic 建议单次上下文工具数量 < 20 个——超过后模型选择准确率明显下降。
让工具职责互斥。 search_info 和 find_data 都能搜索资料,模型就难选。
在描述里写负例。 "不适用于……"比正面描述更能帮模型排除错误选项。
大规模工具集策略
| 工具数量 | 策略 |
|---|---|
| < 20 | 全部加载 |
| 20-100 | 分类/路由先筛选 |
| 100+ | MCP 动态发现或 tool_search 延迟加载 |
OpenAI 的 tool_search(gpt-5.4+)让模型按需搜索工具集,不需要全部加载到上下文。Anthropic 的 MCP 通过 tools/list 和 tools/call 实现类似能力。
结果返回
工具结果是给模型继续推理用的,不是给人看的。
结构稳定。 返回字段固定,类型固定,错误格式固定。
信息够用。 搜索结果不仅要有标题,还要有摘要、链接、来源和时间。
信息不过量。 不要一次返回几百条结果。工具应该先裁剪、排序、摘要,把最相关的返回。
错误返回尤其重要。不要只返回"失败":
{
"success": false,
"error_code": "RATE_LIMIT",
"message": "Search API rate limit exceeded.",
"retryable": true,
"retry_after_seconds": 60
}
这样模型才能判断是等待、重试、换工具还是交给人处理。
工具权限:Prompt 不是安全边界
Tool Calling 一旦连接真实系统,就必须有权限控制。不要把权限控制写在 Prompt 里。Prompt 可以提醒模型,但不能作为安全边界。
权限控制至少三层:
工具白名单。 每个 Agent 只能看到和调用自己需要的工具。看不到的工具就不会被模型选择。
参数限制。 工具执行前校验参数。查询数据库时表名只能来自允许列表;发邮件时收件人域名必须符合规则;文件写入路径必须限制在工作目录内。
操作审批。 高风险工具需要人工确认。
实用分级:
| 级别 | 类型 | 示例 | 审批要求 |
|---|---|---|---|
| L0 | 无副作用查询 | 读取公开资料 | 自动执行 |
| L1 | 读取内部资料 | 查询知识库 | 自动执行(带日志) |
| L2 | 生成草稿 | 创建邮件草稿 | 用户确认 |
| L3 | 写入业务系统 | 更新 CRM | 审批 |
| L4 | 不可逆动作 | 付款、删除、外发 | 多人审批 |
MCP 的安全注解可以辅助自动化这个分级:
| 注解 | 含义 | 自动策略 |
|---|---|---|
readOnlyHint |
只读,无副作用 | 自动允许 |
destructiveHint |
破坏性操作 | 强制人工确认 |
idempotentHint |
幂等操作 | 可自动重试 |
openWorldHint |
访问外部网络 | 需要网络策略审批 |
MCP:工具调用的范式转变
MCP(Model Context Protocol)由 Anthropic 于 2024 年 11 月发布,2025 年成为开放标准。它改变了工具调用的三个根本问题:
从硬编码到动态发现。 不再需要在代码里预注册所有工具。Agent 运行时通过 tools/list 发现可用工具,通过 tools/call 调用。
从封闭到开放标准。 任何 MCP 服务器都可以提供工具,任何 MCP 客户端都可以消费。工具生态从"自己写"变成"即插即用"。
从应用到协议的安全边界。 MCP 注解让安全策略可以在协议层自动执行,而不是每个应用自己实现。
OpenAI 已通过 MCP Connector 支持接入 MCP 服务器,两大阵营在工具协议上趋于统一。
MCP 的安全风险
MCP 也带来了新攻击面:
- 工具注入:恶意 MCP 服务器提供带注入指令的工具描述
- 工具伪装:伪造高权限工具诱骗模型调用
- 数据泄露:工具返回值中嵌入窃取 prompt 的指令
缓解措施:只安装可信来源的 MCP 服务器,审计工具代码,使用 annotations 做自动安全策略。
并行工具调用与 tool_choice
OpenAI 默认 parallel_tool_calls=true,模型可以一次返回多个工具调用。适用于独立信息查询;不适用于有依赖的操作(如先创建再关联)。
tool_choice 精细控制:
| 模式 | 行为 | 适用场景 |
|---|---|---|
auto |
模型自行决定 | 通用对话 |
required |
必须调用至少一个工具 | 强制工具使用 |
none |
禁止工具调用 | 纯文本回复 |
| 指定函数名 | 强制调用特定工具 | 路由到确定工具 |
审计:每次调用都要留痕
生产环境里,每次工具调用都应该留下记录:
- 调用时间
- Agent 或任务 ID
- 工具名称
- 参数摘要
- 执行结果
- 错误信息
- 耗时
- 调用前后的状态版本
审计日志有两个价值:调试(追溯异常行为的根因)和合规(回答"谁在什么时候让系统做了什么"。
日志也要注意安全。参数里可能包含敏感信息,需要脱敏、权限控制和保留期限。
Tool Calling 与 Agent 的关系
Tool Calling 解决"模型怎么动手"。Agent 解决"模型为什么动手、何时动手、动手后怎么判断"。
一次工具调用只是一个动作。Agent 是围绕目标持续运行的循环:多次选择工具、观察结果、更新状态、决定下一步。
不要把 Tool Calling 设计成一堆孤立 API。要把它放进完整执行循环里:工具结果如何进入状态?失败如何影响下一步?高风险工具如何审批?调用日志如何支持复盘?
常见失败模式
| 失败模式 | 根因 | 修复 |
|---|---|---|
| 工具描述太泛 | 模型不知何时用、何时不该用 | 写清适用和不适用场景 |
| 工具职责重叠 | 多个工具都能做同一件事 | 合并或严格区分 |
| 参数过度开放 | 模型能传任意路径、SQL、收件人 | 参数白名单和校验 |
| 错误信息不可行动 | 只返回"error" | 包含可行动建议 |
| 结果过大 | 原始数据塞回上下文 | 裁剪、排序、摘要 |
| 缺少审计 | 出问题无法追踪 | 每次调用留痕 |
工具设计检查清单
- 名称是否能清楚表达动作和对象?
- 描述是否写清适用和不适用场景?
- 参数是否都是必要的?
- 参数类型、格式、范围是否明确?
- 身份、权限、租户信息是否由系统填充?
- 返回结构是否稳定?
- 错误信息是否包含可行动建议?
- 工具有副作用?是否需要审批?
- 是否记录了调用日志?
- 是否限制了返回数据量?
Tool Calling 做得好,Agent 才能可靠地接触外部世界;Tool Calling 做得差,Agent 越"自主",风险越大。
延伸阅读
- Anthropic: Building Effective Agents — ACI 设计原则
- MCP Specification: modelcontextprotocol.io — 工具发现协议标准
- OpenAI: Function Calling Guide — tool_choice、parallel calls、structured outputs
- OWASP: ASI02 Tool Misuse — Agent 工具安全风险
- Galileo: Agent Failure Modes — 工具误用的分类和防御
评论
还没有评论
欢迎留下第一条评论,帮助这篇内容更快形成讨论。