一句话定义
工具设计是为"模型"而非"人"设计 API 的技艺:模型对工具的全部认知就是名称、描述与参数 schema——这三样写得像不像"模型眼里的好工具",直接决定调用正确率;其中错误返回的设计,决定 Agent 能否自我纠正。
为什么重要
Agent 团队的一个反直觉经验:工具描述改几个词带来的提升,常常大于换更贵的模型。工具是模型的"感官与四肢",感官失真则大脑再好也没用。另一个理由:工具是你系统中最可控的杠杆——提示改了容易过拟合,模型换了成本跳升,而工具接口的优化稳定、可测、可积累(每个工具都能单独评测,kp-024)。
前置知识
kp-009(协议流)、kp-005(schema)。
核心概念
好工具的六条设计守则
- 名称自解释:
search_flights好于query_api;名称就是最强的选择特征 - 描述写"何时用"而非"是什么":❌"这是一个搜索函数" → ✅"当用户询问航班、需要实时票价与时刻时使用;不要用它查火车票"
- 参数少而扁平:≤5 个参数、嵌套 ≤2 层;能默认就默认(
page_size默认 20) - 用枚举与边界收窄输入:
enum: ["asc","desc"]、minimum/maximum——每个约束都是一道免费的防幻觉闸(kp-005) - 返回面向模型的结构:返回模型下一步需要的结论性字段 + 摘要,不是数据库原始行;大结果返回"句柄 + 摘要"(
file_id+ 前几行),需要时再用另一个工具取 - 错误要"可行动"(actionable):这是本篇的灵魂,见下
错误返回:自我纠正的教材
错误信息会被模型读到并据此决定下一步。三种写法的高下:
❌ "Error: invalid input" → 模型:换个参数再试?(盲猜)
⚠️ "Error: date must be YYYY-MM-DD" → 模型:改格式(但可能改错语义)
✅ "Error: date '2026-02-30' 不存在。
今天是 2026-09-29,date 必须是今天及以后的合法日期,
格式 YYYY-MM-DD。若用户说的日期含糊,请先向用户确认。"
第三种把事实(今天几号)、约束(合法格式与范围)、建议(怎么办)都给了模型——Agent 的纠错循环(kp-006)质量一半取决于此。
工具粒度的取舍
- 细粒度(
read_file/write_file/list_dir):组合自由、易测试、权限细——编程 Agent 的选择(kp-028) - 粗粒度(
deploy_application):一步到位、不易组合错误、但黑盒难纠错——适合确定性子流程 - 经验:让模型做"判断密集"的层,把"过程确定"的序列打包成粗工具(用代码而非模型串联确定性步骤)
原理与机制
模型选工具的机制 = 语义匹配 + 上下文条件。它在每一步对"当前对话状态"与"各工具名称/描述"做语义比对,输出"选哪个/不选"的分布。由此推出三条机制性结论:
- 描述里的否定要慎用("不要查火车票"在多数情况下有效,但会把注意力引向火车票,kp-004 的否定陷阱)
- 两个工具描述高度相似时,选择会不稳定——功能重叠的工具必须合并或用描述明确划界("仅用于…时")
- 工具结果也是"决策特征":返回里写
"status": "success"比写一堆让模型自己判断的字段,误判少得多——把判断显式化进返回结构。
直观类比
工具描述 = 给一个只看你简历就从没共事过的外包团队写接口文档。人脑会脑补"query 应该是查数据库",模型只认识你写下的字。你写给初级外包能看懂的文档(何时用、参数含义、错误时怎么办、示例),就是给模型的好工具。
实例与案例
"发布文章"工具的两个版本对比(真实项目常见):
python# v1:程序员的直觉
{"name":"publish", "input_schema":{
"properties":{"draft_id":{"type":"string"},
"opts":{"type":"object"}}, # ← 嵌套、无约束、语义不明
"required":["draft_id","opts"]}}
# 症状:模型乱填 opts,覆盖了作者已设置的一切
# v2:面向模型重设计
{"name":"publish_draft",
"description":"将指定草稿发布上线。发布后不可撤回,需用户明确确认后才可调用。",
"input_schema":{
"properties":{
"draft_id":{"type":"string","description":"草稿ID,形如 dft_xxx"},
"confirm":{"type":"boolean","description":"必须为 true 才执行,调用前需用户已确认"}},
"required":["draft_id","confirm"],"additionalProperties":false}}
# 改进:名称带语义、危险操作加确认参数(安全 kp-026)、无自由嵌套
v2 的 confirm 参数是一个经典模式:把人类审批门编码进工具接口本身(kp-023)。
常见误区
- 误区一:把 REST API 原样暴露给模型。人用的接口 ≠ 模型用的接口:REST 的分页、鉴权、错误码语义对模型都是噪声。包一层"模型友好 API"。
- 误区二:错误处理 = 抛异常给框架。异常堆栈对模型是噪声;要转译成"可行动错误消息"。
- 误区三:工具数量无节制。>20 个就会遇到选择困难与窗口挤占——解法:按任务分组动态加载(kp-011)、工具检索,或干脆给一个代码执行器让模型自己组合(kp-018)。
- 误区四:忽略幂等性。模型可能重复调用"创建订单"——写操作要么幂等(带幂等键),要么在工具侧防重。
自测题
- 好的错误信息包含哪三要素?为什么它决定 Agent 的自我纠正质量?
- 为什么两个描述相似的工具会导致调用不稳定?
confirm: true参数模式解决什么问题?
(参考答案:1. 事实、约束、建议——模型的下一步分布由错误文本条件化,可行动错误把"盲试"变成"定向修正";2. 选择靠语义匹配,相似描述使匹配分布扁平而不稳定;3. 把高风险操作的人类确认编码进接口,未确认时模型无法(合法)执行。)
与其他知识点的关系
- 协议层 → kp-009;协议标准化与动态加载 → kp-011
- 代码执行作为"终极工具" → kp-018;危险操作审批 → kp-023/026
延伸阅读
- Anthropic, Tool Use 最佳实践(错误处理与描述写法章节)
- OpenAI, Function Calling Guide("writing good descriptions")