作者:simon · 2026-10-23
你给 agent 接了十几个工具,它却越用越糊涂:该调的不调,不该调的乱调,返回一大坨东西把上下文塞满。
多半不是模型的问题,是工具写得不对。Anthropic 工程博客有一篇专门讲怎么给 agent 写工具,我读完,挑了最实用的 5 条,用人话讲一遍。
先说结论
- 原文第一句就把话说完了:"Agents are only as effective as the tools we give them."(agent 能做到什么程度,取决于你给它什么工具。)
- 写工具不是"把现有接口包一层",要站在 agent 的角度设计:少而精、名字清楚、返回的东西有用、说明写得像给新人交接。
- 原文的做法是"先做原型、再用评测去磨"。这是 Anthropic 的经验,我没有实测,下面的"我的看法"只是读后的判断。
工具到底是什么
传统软件是确定的:同样的输入,永远得到同样的输出。agent 不是:同一个问题,它可能调工具,可能凭常识直接答,也可能反问你一句。
所以原文把工具定义成:"Tools are a new kind of software which reflects a contract between deterministic systems and non-deterministic agents."(工具是一种新软件,反映的是确定性系统和非确定性 agent 之间的契约。)
我的看法: 这句话的意思是,你写的不是给程序员看的接口,而是给一个"会走神、会猜错"的使用者看的说明书。那就别按"接口文档"的思路写,要按"别让它猜"的思路写。
怎么写:原型、评测、让 agent 帮你改
原文的流程分三步:
- 先搭一个原型。 把库或 API 的文档喂给 Claude,让它快速写出来,再用本地 MCP 服务器或桌面扩展接进去,自己试一试。
- 做评测。 先造一批贴近真实的任务。原文强调别用太简单的"沙盒题":"Strong evaluation tasks might require multiple tool calls—potentially dozens."(好的评测任务可能需要多次工具调用,甚至几十次。)而且每个任务都要有可以验证的结果:"Each evaluation prompt should be paired with a verifiable response or outcome."
- 分析结果,再改。 不只看 agent 说了什么,也要看它没做什么,读它的推理和原始调用记录。比如:冗余调用多,可能是分页或限制设得不对;参数老填错,可能是描述或示例不清楚。
跑评测时,原文建议让每个任务由一个简单的循环 agent 去跑,并让它在每次调用前后输出"推理"和"反馈",这样你能看到它为什么调、为什么不调。要收集的指标也列得很具体:每次工具调用和每个任务的耗时、工具调用的总次数、消耗的 token、工具报错的次数。
另外,原文说到一个省力的办法:把一批评测的完整记录拼起来,直接贴给 Claude Code,让它帮你一起重构工具,顺便保证各个工具的命名和写法保持一致。原文称,他们文中大部分建议,就是这样反复用 Claude Code 去优化内部工具得来的,并且用留出来的测试集防止"越改越过拟合"。
原文还举了个小例子:Claude 的网页搜索工具上线时,他们发现 Claude 总会多此一举,往查询参数里加上 2025 这个年份,结果让搜索结果有偏差。改了工具描述就解决了。
我的看法: 指标里最容易被忽略的是"工具报错次数":它常常直接告诉你,哪条描述写得让 agent 看不懂。另外"看它没做什么"这条很多人会漏。agent 不调某个工具,往往不是它偷懒,是你的描述没让它明白什么时候该用。
原则 1:少而精,别把接口一股脑包进来
原文说得很直白:"More tools don’t always lead to better outcomes."(工具多了不一定效果更好。)常见错误是把已有的 API 端点原样包一层。
agent 的上下文有限。原文举的例子:与其做一个把所有联系人都吐出来的 list_contacts,不如做 search_contacts。多步操作也该合并:用一个 schedule_event 代替 list_users、list_events、create_event 三连。
还有一句:每个工具都要有清晰、独特的用途("Make sure each tool you build has a clear, distinct purpose.")。功能重叠的工具,只会让 agent 犹豫选哪个。
我的看法: 可以拿"你会不会给新同事发三个差不多的工具"来检验自己。
原则 2:名字要有前缀
工具多了以后,原文建议用统一前缀划清边界。比如按服务分:asana_search、jira_search;也可以按资源再细分:asana_projects_search、asana_users_search。
原文也提醒:前缀还是后缀、怎么命名,对不同模型的影响不一样,要用自己的评测去选,不要想当然。
原则 3:返回有意义的内容,别返回一堆 ID
给 agent 的结果要"高信号"。原文的建议是:多给名字、图片链接、文件类型;少给 UUID 这类它看不懂的东西。原文称,把乱码一样的 UUID 换成有语义的名字,能减少幻觉、提高检索精度。
另一个好用的办法:加一个参数,让 agent 自己选"详细"还是"简洁"。原文的例子里,详细回复用了 206 个 token,简洁回复只用了 72 个,大约是三分之一(原文称)。
我的看法: 这是性价比最高的一条。工具返回的内容,每个字都在占 agent 的上下文,写得越啰嗦,越容易挤掉真正重要的信息。
原则 4:控制返回的体量,错误信息也要写给 agent 看
返回内容大的时候,用分页、范围选择、过滤、截断,并设置合理的默认值。原文提到,Claude Code 默认把工具返回限制在 25,000 个 token(原文称)。
截断时别一刀切,要引导 agent:"用多个小而准的搜索,别用一个大而泛的搜索"。报错也一样,别只丢一个错误码或一大堆堆栈,要写成它能照着改的话,最好直接给出正确的输入格式。
原则 5:描述要像给新人交接
工具的描述会被装进 agent 的上下文,直接影响它怎么用。原文的建议是:像给一个新入职的同事讲解一样,把隐含的背景、查询格式、术语、资源之间的关系都写明白。参数名要没歧义(比如用 user_id,别只写 user),输入输出用严格的数据结构约束,把"能传什么、会返回什么"写清楚,别让 agent 去猜。
原文还说,描述里很小的改动也能带来很大的变化:他们在把描述改精确之后,Claude Sonnet 3.5 在 SWE-bench Verified 上达到了当时的最好成绩(原文称,具体分数原文未给)。
一句话带走
- 工具是给 agent 的"说明书",不是给程序员的接口。
- 少而精、名字清楚、返回的东西有用且体量可控、描述像给新人交接。
- 先做原型,再用有真实难度、有可验证结果的评测去磨,并认真看 agent 没做什么。
参考与出处
- 《Writing effective tools for agents — with agents》,Anthropic Engineering,Published Sep 11, 2025;致谢处署名 Ken Aizawa。www.anthropic.com/engineering… (2026-10-19 读取,核对了文中引语和数字)
- 文中带引号的英文都是原文原句,每句不超过 25 个词;206/72 个 token、25,000 个 token、2025 这个年份的例子、SWE-bench Verified 的说法都是原文自述,我没有第三方佐证。