给 AI Agent 写工具函数的五个坑
工具函数不是给人用的 API
给人写接口,可以靠文档、靠示例、靠沟通补足模糊之处。给 Agent 写工具,模型只能看到函数名、描述和参数 schema,看不到你的意图。描述写得含糊,模型就一定会用错,而且错得很自信。
下面五个坑,是实际把 Agent 接到生产流程里之后总结的。
坑一:描述写成了「标题」
反面例子:
name: query
description: 查询数据
模型看到这个只能猜:查什么数据?按什么条件?返回什么?
正面写法:
name: search_orders
description: 按条件查询订单列表。只返回最近 90 天的数据,最多 50 条。
当用户询问"我的订单""买过什么""退款的单子"时使用。
如果用户只给了模糊描述(比如"上次那个"),先用 list_recent_orders 获取候选,
不要凭猜测直接调用本函数。
parameters:
status: 可选,枚举 pending/paid/refunded,不传表示全部
keyword: 可选,匹配订单号或商品名
三件事必须写清楚:做什么、什么时候用、什么时候不该用。其中「不该用」最容易被忽略,但恰恰是减少误调用的关键。
坑二:参数设计成万能对象
有的工具签名长这样:
{ "params": { "type": "object", "description": "查询参数" } }
把决策权全交给模型,等于让它自由发挥。它可能传一个嵌套三层的结构,也可能把日期写成「上周三」。
正确做法是把参数收敛成枚举、必填项和明确的格式约束:
{
"date_from": { "type": "string", "description": "起始日期,格式 YYYY-MM-DD,例如 2026-10-01" },
"status": { "type": "string", "enum": ["pending", "paid", "refunded"] }
}
有 enum 就用 enum。枚举把「模型猜」变成「模型选」,成功率差得非常远。日期这类有格式要求的,描述里必须给一个真实示例,光说「ISO 格式」不够。
坑三:忘了幂等
Agent 会重试。网络抖一下、超时一次,它可能就把同一个操作再执行一遍。如果你的工具是「提交订单」「发送邮件」「创建工单」,重复执行的后果是真实损失。
三个手段,按成本从低到高:
第一,读操作和写操作分成两个工具,名字上就区分开(get_order / create_order),别让一个工具既能读又能写。
第二,写操作接收一个 idempotency_key 参数,服务端按 key 去重。描述里明确告诉模型:同一个逻辑操作要复用同一个 key。
第三,危险操作加 dry_run 参数:
dry_run: 布尔,默认 true。为 true 时只返回将要执行的操作预览,不产生实际副作用。
用户明确确认后再传 false 执行。
这条对 Agent 场景特别有效——模型先生成计划给用户看,确认了才动手,比事后再补救强得多。
坑四:错误信息只写了一句话
工具失败时返回 {"error": "failed"},模型就彻底失明了:它不知道是参数错了、权限不够、还是资源不存在,只能瞎猜着重试。
错误返回应该包含可执行的下一步:
{
"error": "PERMISSION_DENIED",
"message": "当前账号没有该仓库的写权限",
"hint": "请换用有写权限的仓库,或先调用 list_writable_repos 查看可用列表"
}
关键在 hint:告诉模型接下来该干什么。有了这一条,模型能自己纠偏;没有这一条,它只会重试三次然后放弃,还给你一个「操作失败」的空洞结论。
另外建议把错误码做成有限枚举(NOT_FOUND / PERMISSION_DENIED / INVALID_ARGUMENT / RATE_LIMITED / UPSTREAM_ERROR),模型对不同错误码的处理策略可以完全不同——RATE_LIMITED 该等一会儿重试,INVALID_ARGUMENT 重试一万次也没用。
坑五:返回值塞了整个接口响应
顺手把上游 API 的原始 JSON 返回出去,几百个字段,其中 90% 是模型不需要的。后果是上下文被瞬间撑爆,后面几轮对话它就开始「忘事」。
工具返回应该为模型裁剪过:
· 列表接口默认只返回关键字段,最多 20 条,并给出总数;
· 大文本做截断,明确标注 truncated: true 和原始长度;
· 时间统一成带时区的 ISO 字符串,别混着时间戳和「3 天前」;
· 字段名保持稳定,模型会依赖这个稳定性。
还有个细节:返回结构里不要把「人类看的文案」和「机器用的数据」混在一起。模型容易把展示文案当成数据来源,导致后续解析错误。
最后:工具数量和粒度
工具不是越多越好。二十个语义重叠的工具,模型选择准确率会明显下降。宁可把同类操作合并成一个带 action 枚举的工具,也不要拆成一堆名字相近的小函数。
粒度上,一个工具对应一个「用户能说出口的动作」。用户会说「帮我查一下上周的订单」,不会说「帮我调用 search_orders 并传入 date_from」。工具设计应该贴着前者的语言习惯走。
写完之后找个不懂技术的人看一遍描述,问他「这个函数是干什么的、什么时候该用」。如果他答不上来,模型多半也答不上来。
- 点赞
- 收藏
- 关注作者
评论(0)