ClaudeClaude API

给智能体写工具:Anthropic 的五条原则,和同一批数据两版工具的实测对比

自己写 MCP 服务器或给智能体加工具时,照着接口一个个包起来往往不是好办法。本文整理 Anthropic 工程博客的五条原则,并在同一批数据上做了两版工具:四道题都答对了,按任务设计的那版少调三分之二的工具,输入 token 不到三分之一。

发布 · 约 11 分钟读完 · 经人工审核()· 本站的内容怎么来的

本站已实测,测试日期:2026-10-16。

本页目录(7 节)
  1. 工具和普通函数有什么不一样
  2. 五条原则
  3. 本站实测:同一批数据,两版工具
  4. 怎么改进工具:原型、评测、让 Claude 帮你改
  5. 工具很多时:代码执行和三个平台功能
  6. 这次实测没有覆盖到的
  7. 参考

这篇解决一个问题:自己写 MCP 服务器、给 Agent SDK 或 Claude API 的智能体加工具时,工具该怎么设计。

最常见的做法是把现成的接口一个个包成工具:有 list_customers 接口就做一个 list_customers 工具。Anthropic 工程博客的《Writing effective tools for AI agents》说这往往不是好办法:工具的使用者是智能体,不是另一个程序,要按智能体的特点来设计。文章总结了五条原则,还讲了怎么用评测加 Claude Code 来改进工具。

本站拿同一批虚构的客服数据做了两版工具,一版照接口包一层,一版按文章的原则改,让 Claude 用两版各答四道题:

  • 四道题两版都答对了。 这批数据小,模型也够强,照接口包的那版也能硬查出来。
  • 代价差很多。 按任务设计的那版,工具调用从 26 次降到 8 次,输入 token 从约 5.8 万降到约 1.7 万,工具返回的文字从 5.7 万字降到 3 千字。
  • 差距随数据量放大。 照接口包的那版有一道题要逐个客户拉订单,调了 17 次工具;客户多十倍,就要多十倍。
实测环境
日期 2026-10-16
模型 Claude Sonnet 5.5(claude-sonnet-5-5)
接口 Claude API 的 Messages 接口,Python SDK,自己写的工具调用循环;通过酷站AI 中转站,不是直连官方
数据 随机生成的 16 个客户、86 笔订单、18 个工单,全是虚构的
次数 每道题每版各跑 1 次

工具和普通函数有什么不一样

文章开头的说法很好懂:普通的函数调用是两个确定的程序之间的约定,getWeather("NYC") 每次都会用同样的方式去查纽约的天气。工具是确定的程序和不确定的智能体之间的约定:用户问“今天要带伞吗”,智能体可能调天气工具,可能凭常识回答,也可能先反问在哪个城市;偶尔还会用错工具。

所以写工具不能照着给别的程序员写接口的方式来写。好在文章发现,对智能体顺手的工具,人用起来通常也顺手。

五条原则

一、选对要做的工具,不要照接口一个个包

智能体的上下文有限,电脑的内存却又便宜又多。从通讯录里找一个人,程序可以一条条比对;智能体要是调一个返回全部联系人的工具,就得一个字一个字读完,把有限的上下文浪费在无关的内容上。更自然的做法是直接翻到那一页。所以与其做 list_contacts,不如做 search_contacts。

工具可以把常一起用的几步合成一步。文章举的例子:

不要 改成
list_users、list_events、create_event 一个 schedule_event,自己找空闲时间并约好
read_logs search_logs,只返回相关的几行和上下文
get_customer_by_id、list_transactions、list_notes 一个 get_customer_context,一次给齐这个客户最近的相关信息

工具多了不一定好,功能重叠或者用途含糊的工具会让智能体分心。先针对几个影响最大的工作流做少数几个,再按评测结果加。

二、用前缀分组

智能体可能同时接着几十个 MCP 服务器、几百个工具,有些还是别人写的。按服务(asana_search、jira_search)或按资源(asana_projects_search、asana_users_search)加前缀,能帮它分清该用哪个。文章说前缀和后缀两种写法在评测里的效果差别不小,而且因模型而异,要用自己的评测来选。

三、返回有意义的内容

工具只返回高信号的信息,不要返回 uuid、256px_image_url、mime_type 这类底层标识;name、image_url、file_type 更能直接帮它决定下一步。把一串随机的 UUID 换成有意义的名字,哪怕只是从 0 开始的编号,都能明显提高 Claude 在检索任务里的准确度,减少编造。

有时智能体确实需要 ID 去调下一个工具。办法是给工具加一个 response_format 参数,让它自己选 concise(只给内容)还是 detailed(带上各种 ID)。文章的例子里,同一个 Slack 消息串,详细版 206 个 token,精简版 72 个,约三分之一。

返回的格式(XML、JSON、Markdown)也会影响效果,没有通用的最优解,要按自己的评测选。

四、控制返回的长度

可能返回很多内容的工具,都要有分页、范围、过滤或截断,并给合理的默认值。截断时告诉它怎么继续,比如“结果太多,请加过滤条件”。Claude Code 自己也有限制:按现在的文档,MCP 工具的返回超过 1 万 token 会提醒,默认最多 25,000 个 token,可以用环境变量 MAX_MCP_OUTPUT_TOKENS 调。

报错也一样:不要只回一个错误码或一段堆栈,要说清楚哪里不对、该怎么改。

五、把描述当提示词来写

工具的描述会被放进智能体的上下文,是改进工具最有效的办法之一。写的时候想象在给新同事讲这个工具:你脑子里默认的东西(查询的格式、行业术语、资源之间的关系)都要写出来。参数名要没有歧义:与其叫 user,不如叫 user_id。文章提到,Claude Sonnet 3.5 在 SWE-bench Verified 上拿到当时的最好成绩,靠的就是对工具描述做了精确的修改。

给 MCP 服务器写工具时,还可以用工具注解标明哪些工具会访问外部世界、哪些会做破坏性的修改。

本站实测:同一批数据,两版工具

两版工具

数据是一个虚构的客服后台:16 个客户,每个人有几笔订单和几个工单。

v1 照接口包一层,四个工具,描述只有一句英文,原样返回数据库里的记录:

工具 描述 返回
list_customers List customers. 全部客户,每个带 UUID、手机号、头像地址、营销偏好等字段,共 6,188 字
list_orders List orders for a customer. 这个客户的全部订单,带 UUID、支付方式 ID、来源等
list_tickets List support tickets for a customer. 这个客户的全部工单
get_plan Get a plan. 套餐详情

传错 ID 时只回一句 Error: 404。

v2 按任务设计,三个工具,描述写清楚什么时候用、返回什么:

工具 做什么
search_customers 按名字或邮箱的一部分搜客户,返回 C07 林晓雯 邮箱 套餐 这样的一行
get_customer_context 一次给齐一个客户的套餐、最近几个月按月汇总的订单、未解决的工单原文;response_format 选 detailed 时再加订单明细
search_orders 按客户、状态、日期范围搜订单,可以不限客户;结果多时分页,末尾说明还有多少条、用什么 offset 看后面

客户编号用 C01 这样的短编号,金额直接写成 ¥99.00。找不到客户时,报错会给出相近的名字,并建议先用 search_customers 搜。get_customer_context 的返回长这样:

C01 林晓雯 lin.xw@example.com,套餐:基础版(¥29.00/月)
最近 3 个月(2026-07-17 起)的订单:
  2026-08:refunded 1 笔 ¥99.00
  2026-09:paid 3 笔 ¥457.00,refunded 2 笔 ¥144.00
  2026-10:paid 1 笔 ¥29.00
未解决的工单:没有

四道题

  1. 客户林晓雯 2026 年 9 月有几笔退款,合计多少?
  2. 邮箱 xu.jy@example.com 的客户用的是什么套餐,有没有未解决的工单?
  3. 有没有客户被重复扣款(同一客户、同一天、金额相同、都已支付的两笔)?列出名字。
  4. 王建国提交了取消请求:他为什么要走,最近三个月实际付了多少钱?

标准答案是脚本从数据里直接算出来的。第 3 题我们埋了两起重复扣款,随机生成的数据里碰巧还多出一起,所以答案是三个人。

结果

题 v1 工具调用 v1 输入 token v2 工具调用 v2 输入 token 两版都答对
1 3 11,066 2 3,747 是
2 3 9,871 1 2,432 是
3 17 26,027 2 7,003 是
4 3 10,958 3 4,196 是
合计 26 57,922 8 17,378

输入 token 是这道题所有请求加起来的。几处值得看:

  • 第 3 题最能说明问题。 v1 只能先拉全部客户,再逐个拉订单,16 个客户的 list_orders 是在一轮里并行发出的,所以总共 17 次调用。v2 用 search_orders 按“已支付”过滤,翻了两页就找齐了。两版都找到了三个人,v1 还多说了一句“罗佳琪那两笔隔了 6 小时,可能是两次正常购买,建议核实”。
  • v1 每道题第一步都是拉全部客户。 每次 6,188 字,不管问的是谁。客户多到几千个,这一步本身就装不进上下文了。
  • 工具返回的文字差得更多。 四道题加起来,v1 的工具返回了 57,102 字,v2 只有 3,028 字。输入 token 的差距没那么大,是因为每次请求都还带着系统提示、工具定义和对话本身。
  • 耗时没有稳定的规律。 第 3 题 v1 17.1 秒、v2 8.8 秒;第 2 题反过来,v1 9.0 秒、v2 24.6 秒。每道题只跑了一次,时间受接口的响应影响大,这一项不下结论。

所以这次实测的结论比文章保守:在小数据上,强模型用一套粗糙的工具也能答对,好的工具省下的是调用次数和 token。 文章说的准确度提升(比如把 UUID 换成有意义的名字能减少编造),在这么小的数据上没有体现出来,要更大、更难的任务才测得出。

怎么改进工具:原型、评测、让 Claude 帮你改

文章给的流程分三步。

先做原型,自己试。 用 Claude Code 写工具时,把要用到的库和接口的文档给它,官方文档站一般有 llms.txt。把工具包成一个本地的 MCP 服务器,用 claude mcp add <名字> <命令> [参数…] 接进 Claude Code,自己用一用,找出别扭的地方。怎么写和接 MCP 服务器,见《Claude Code 接 MCP 服务器实战》。

再做评测。 让 Claude Code 照着真实的用法生成几十个任务,每个配一个能核对的答案。好的任务要用到多个工具,甚至几十次调用,比如“客户 9182 说一次购买被扣了三次款,找出相关日志,看还有没有别的客户受影响”;差的任务太直白,比如“搜 customer_id=9182 的支付日志”。核对答案不要太死,格式、标点、说法不同就判错是不对的。跑评测用最简单的循环就行:一个任务一个循环,交替调接口和工具。除了准确率,还要记工具调用次数、token 用量、耗时和工具报错:很多重复调用说明分页或长度限制该调整,很多参数错误说明描述或例子不够清楚。

让 Claude 帮你分析和改。 把评测的完整记录拼在一起贴给 Claude Code,它擅长读记录、一次重构一批工具并保持描述一致。文章说里面的大部分建议,就是他们反复用 Claude Code 优化内部工具得出来的。有一个例子:Claude 的网页搜索工具刚上线时,Claude 总在查询词后面加上“2025”,把结果带偏了,改了工具描述才好。还要留一份不参与调优的测试集,免得在评测上过拟合。

评测本身怎么建,见本站的《给智能体建评测》。

工具很多时:代码执行和三个平台功能

接的 MCP 服务器多了以后,还有两个问题:工具定义本身就占掉大量上下文;中间结果一层层传给模型,也很占地方。

《Code execution with MCP》这篇文章的思路是把 MCP 服务器当成代码接口给智能体,而不是一个个直接调用的工具:每个工具对应文件系统里的一个代码文件,智能体浏览目录找到需要的那几个,读了定义再写代码去调,数据在代码执行环境里处理完再把结果交给模型。文章的例子里,token 从 15 万降到 2 千,省了 98.7%。另一种做法是给服务器加一个 search_tools 工具,按需查找定义,并让它选要多详细(只要名字、名字加描述、完整定义)。

Claude 开发平台上有三个对应的功能,《Introducing advanced tool use》讲了各自什么时候用:

你的瓶颈 用什么 什么时候值得
工具定义太占上下文 工具搜索 工具定义超过 1 万 token;工具超过 10 个;接了多个 MCP 服务器;选错工具的情况多
中间结果太大 程序化工具调用:让 Claude 在代码执行里调你的工具 只需要汇总的大数据;三步以上互相依赖的调用;要对很多项做同样的操作
参数总是传错 工具使用示例(input_examples) 嵌套复杂的结构;可选参数多;有 schema 表达不了的约定;几个相似的工具需要靠例子区分

文章的建议是先解决最大的那个瓶颈,再按需叠加,不要一开始就全上。三个功能的用法本站另有文章:工具搜索和程序化工具调用见《Claude API 的服务器端工具》,input_examples 见《Claude API 工具调用入门》,Agent SDK 里的工具搜索见《Agent SDK 进阶:工具搜索》。

这次实测没有覆盖到的

  • 每道题每版只跑了一次。 结果有随机性,跑多次才能看出稳定性。
  • 数据很小。 16 个客户,强模型用粗糙的工具也能答对;文章说的准确度提升没有测出来。
  • 只测了 Claude API 的工具调用。 同样的工具包成 MCP 服务器接进 Claude Code,原则一样,但本站没有另外测。
  • 没有测前缀分组、返回格式(JSON 和 Markdown)的影响。
  • 花费:两版各 4 道题,加起来输入约 7.5 万 token、输出约 4 千 token,按 Sonnet 5.5 的官方价(每百万 token 输入 2 美元、输出 10 美元)估算约 0.2 美元。这是估算,不是中转站实际扣的金额。

参考

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章