深色模式
05 · 工具设计
Agent 的能力上限由工具质量决定
📚 系列导航:这是《Agent 开发进阶》的第 5 篇(共 24 篇)。上一篇你手写循环时多半撞见过"模型不按预期调工具",这一篇治这个病:把工具打磨成模型一看就会用。下一篇:06 · 上下文工程。
循环跑通后,多数人把精力全花在改 prompt 上,工具定义随手一写:描述四个字、参数全自由串、返回原样甩 JSON,然后奇怪模型乱调。换个视角:工具是写给模型看的 API——模型没有源码可读,描述和 schema 就是它的全部文档,写得含糊它只能瞎猜。这一篇只干一件事:给你一套工具设计规范,把调用正确率从"看运气"变成"可优化"。
看完这一篇,你会拿到:
- 一个工具描述的黄金结构四段模板
- 两条参数设计铁律:枚举优于自由串、扁平优于嵌套
- 一套返回双轨设计:结构化 + 人话摘要 + 可行动错误
- 一份重构前后的调用正确率 AB 对比数据(动手产出)
01 描述黄金结构:何时不用和何时用一样重要
我见过最烂的描述就四个字:"查询数据"——模型逢问必调,不该查的也查。好比药品说明书只写"治病"两个字,不写适应症和禁忌症,谁敢照着吃?黄金结构四段:做什么(一句话)、何时用(典型场景)、何时不用(指路别的工具)、参数说明(含格式示例):
python
# 伪代码,schema 字段名以官方文档为准
search_orders = {
"name": "search_orders",
"description": "按条件查询订单。适用:查订单状态、物流进度。"
"不适用:退款政策(用 get_policy)、改订单(用 update_order)。",
"parameters": {
"status": {"type": "string", "enum": ["paid", "shipped", "done"]},
"days": {"type": "integer", "description": "查最近 N 天,默认 7"}
}
}预期效果:模型对"退款政策"类问题不再误调此工具。
💡 一句话总结:四段写全:做什么/何时用/何时不用/参数说明——不写禁忌症的说明书最危险。
02 参数设计:枚举优于自由串,扁平优于嵌套
每多一个自由字符串参数就多一分错误率:模型可能传"已发货"、"shipped"甚至"发货了"。能穷举的一律上 enum,把自由发挥变成三选一。嵌套同理:三层深的参数对象,模型常把字段放错层——拍扁成平铺字段,错误率立降。必填越少越好,能给默认值就给。
💡 一句话总结:参数设计的方向只有一个——把模型的自由发挥空间压到最小。
03 返回设计:双轨输出 + 可行动错误
返回要为模型消费而设计,两条轨:结构化数据(程序要用的字段)+ 人话摘要("共 3 笔订单,最新一笔已发货")。错误信息必须"可行动":写"日期格式应为 YYYY-MM-DD",别写"参数错误"——我踩过坑,错误只返回"失败"两字,agent 拿同样参数重试了 5 次。体积同理:三千行原始 JSON 就是下一轮的 token 炸弹——摘要和截断是义务,不是优化。
💡 一句话总结:返回是喂给下一轮的上下文——摘要、截断、可行动错误,一个都不能少。
04 工具粒度:三个细工具赢过一个万能工具
"万能工具"(一个 do_everything 带 action 参数)看着省事,实际把路由压力全甩给模型。判据一句话:**这个工具的描述能一句话说清吗?**说不清就该拆。三个职责清晰的细工具,描述好写、参数简单,模型选起来反而不容易错。反过来别拆过头——20 个微工具让选择本身变难,工具列表也是上下文负担。
💡 一句话总结:粒度的尺子是"一句话说清职责"——说不清就拆,拆到说得清为止。
05 动手:重构烂工具,AB 测正确率
任务:把"描述只写查询数据、参数全自由串、返回原始 JSON"的反例当 A 版,按本篇规范重构出 B 版。准备 20 条测试问题(一半该调、一半不该调),接进上一篇的循环各跑一遍,统计"该调时调了、不该调时没调、参数正确"三项比例。
验收标准:一张 A/B 正确率对比表,B 版三项指标可见提升。
两种结果都正常:B 版明显胜出,把黄金结构固化成你的工具模板;提升不明显,检查测试问题是不是太简单,或瓶颈在 system prompt——那是下一篇的事,带着数据去。
06 小结
你现在应该能:按黄金结构写工具描述、用枚举和扁平化压低参数错误、设计双轨返回与可行动错误、用一句话判据定粒度。
工具是 agent 的手,下一篇管大脑的注意力:06 · 上下文工程——为什么塞得越多模型越笨。
📎 实战案例
工具描述只写「查询数据」四个字,模型逢问必调。开发者补上「何时用/何时不用」、状态参数改枚举、返回改成「结构化 + 人话摘要」双轨后,20 条测试问题 AB 测:调用正确率从 6 成升到 9 成,误调基本归零——工具是写给模型看的 API。
踩坑
- 我的工具返回过 3000 行原始 JSON,下一轮直接 token 超限——server 端摘要是义务。
- 错误信息只写"失败",agent 拿同样参数重试了 5 次——错误要教它怎么改。
- 一个自由字符串的 status 参数,模型传出 4 种写法,命中率不到一半——改成枚举后一次没错过。