智能体的能力上限,取决于我们给它的工具。这篇文章讲的是:如何写出高质量的工具与评估,以及如何让 Claude 反过来帮自己优化所用的工具。
这是全文的出发点,作者用一句话定了调。
模型上下文协议(MCP)可以让一个 LLM 智能体接入数以百计的工具,去解决真实世界的任务。但问题随之而来:怎么才能让这些工具发挥出最大的效用?这篇文章分享的,就是 Anthropic 在各类智能体系统上提升性能时最有效的一批做法。
作者把要讲的内容分成两块——先讲「怎么做」的操作流程,再讲「为什么」的设计原则:
📎 脚注 1:这里说的「提升性能」,指的是除了训练底层 LLM 本身之外的所有手段。
作者先重新定义了「工具」这个东西——它不同于我们写惯了的普通函数。关键在于「确定性」与「非确定性」的对撞。
getWeather("NYC") 这个函数调用,每次都会以完全相同的方式取回纽约的天气。这个区别会带来实际后果。当用户问「我今天要带伞吗?」时,智能体可能会去调用天气工具,也可能凭常识直接回答,甚至可能先反问一句你在哪个城市。偶尔,它还可能产生幻觉,或者压根没搞懂这个工具该怎么用。
所以,这意味着我们在为智能体写软件时,要从根本上换一种思路:不能再像给其他开发者或系统写函数和 API 那样,去写工具和 MCP 服务器——而是要专门为智能体来设计它们。
作者点明了目标:扩大智能体能够有效作业的「面积」,让它能借助工具采取多种成功策略,去解决尽可能广的任务。
这一节是「怎么做」的总纲:整个过程是一个和智能体协作、不断循环改进的闭环。下图是这个循环的骨架。
作者特别强调:在没有亲自上手之前,你很难预判哪些工具智能体用着顺手、哪些不顺手。所以一切从一个能跑起来的快速原型开始,本地测试它,再用一套全面的评估去衡量后续的每一次改动。
第一步,先把工具立起来、能跑、能连进 Claude 里试。
llms.txt 文件形式放在官方文档站上(Anthropic 自己的 API 就有一份)。claude mcp add <name> <command> [args...] 即可把本地 MCP 服务器接进 Claude Code。Settings > Developer(接 MCP 服务器)或 Settings > Extensions(接 DXT)。这是全篇分量最重的一节。光有原型不够,你得用评估去量化 Claude 到底用得怎么样。Anthropic 给出了一整套端到端的做法,还放出了工具评估 cookbook。
用早期原型,Claude Code 能快速摸清你的工具,造出几十组「提示 + 回应」的配对。提示词应当取材于真实用例,基于真实的数据源和服务(例如内部知识库、微服务)。
作者给了一组正反例对照,差别很说明问题——强任务模拟真实工作的复杂与模糊,弱任务则把答案几乎喂到嘴边:
purchase_complete 且 customer_id=9182。每条评估提示都应配一个可验证的回应或结果。验证器(verifier)可以简单到只是把标准答案和采样回应做精确字符串比对,也可以高级到请 Claude 来当评委判断回应好坏。但要避免过于严苛的验证器——别因为格式、标点、或同义的不同措辞这类无关差异,就把本来正确的回应判错。
对每组配对,你还可以选择性地指定你期望智能体会调用的工具,以衡量它是否真的领会了每个工具的用途。不过,因为解对一个任务可能有多条有效路径,要尽量避免过度规定、或对某种策略过拟合。
while 循环,里头交替进行 LLM API 调用和工具调用):每个评估任务配一个循环,每个评估智能体只拿到单个任务提示 + 你的工具。智能体是你发现问题的得力搭档,它能就各种问题给出反馈:从相互矛盾的工具描述,到低效的工具实现,再到令人困惑的工具 schema。
指标怎么读?作者给了两个对应关系:大量冗余的工具调用,可能提示你该调整分页或 token 上限参数的「合身度」;大量因参数无效而产生的工具报错,可能说明工具需要更清晰的描述或更好的示例。
query 参数后面加上 2025,这让搜索结果产生偏差、性能下降。最后他们靠改进工具描述把 Claude 引导回了正轨。这一步把循环闭上:不只是让智能体分析,而是让它直接动手改。
做法朴素得出奇:把评估智能体产生的那些轨迹拼接在一起,粘进 Claude Code。Claude 是分析轨迹、并一次性重构大量工具的专家——比如,确保在引入新改动后,工具的实现与描述始终保持自洽。
他们靠留出的测试集(held-out test sets)来确保没有对「训练」用的评估过拟合。这些测试集揭示出一个有意思的结论:即便是在「专家级」的工具实现之上(无论这些工具是研究员手写的、还是 Claude 自己生成的),仍能再榨出额外的性能提升。
📎 原文这两组对比以图表呈现(Slack / Asana 工具的留出测试集表现);本文以文字与数据卡转述其结论。
下面进入「为什么」的部分——作者把反复优化中提炼出的经验,归纳成五条指导原则。后面五节逐条展开。
| 选对工具 | 少而精地做几个针对高价值工作流的工具,而不是一股脑包装所有 API。 |
| 命名空间 | 用统一前缀给工具分组,划清功能边界,减少智能体「选错工具」的概率。 |
| 有意义的上下文 | 只把高信号的信息返回给智能体,优先语义化名称而非晦涩 ID。 |
| token 效率 | 用分页/范围/过滤/截断控制返回量,并把错误信息写得可操作。 |
| 提示工程描述 | 把工具描述当成给新同事的说明书来写,消除歧义。 |
核心命题:工具不是越多越好。一个常见错误,是把工具仅仅做成对现有软件功能或 API 端点的「包装」,而不管它是否真的适合智能体。
最关键的差异是上下文有限:LLM 智能体一次能处理的信息量是有上限的,而计算机内存却便宜又充裕。作者用「在通讯录里找联系人」这个例子把它讲透了。
search_contacts 或 message_contact,而不是 list_contacts。作者的建议是:围绕特定的高价值工作流,做少数几个经过深思熟虑的工具(让它们匹配你的评估任务),再从这里逐步扩展。
工具可以在内部承担多个离散操作(或多次 API 调用):比如用相关元数据丰富返回结果,或把经常被串起来的多步任务,收进一次工具调用里。三组对照例子:
| 与其分别做…… | 不如做一个…… |
|---|---|
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。作者还给了一个值得记住的细节:在他们的工具使用评估里,选「前缀式命名」还是「后缀式命名」会产生不可忽视的影响;而且这种影响因 LLM 而异。所以他鼓励你根据自己的评估来选择命名方案。
命名空间为什么有用,作者给了一条因果链:
工具实现要注意:只把高信号的信息返回给智能体。优先「上下文相关性」而非「灵活性」。
| 应避免返回(低信号技术标识符) | 应优先返回(直接指导后续动作) |
|---|---|
uuid、256px_image_url、mime_type | name、image_url、file_type |
response_format 兼顾两种需求有时,智能体确实需要灵活性,能同时拿到自然语言和技术标识符的输出——哪怕只是为了触发后续的工具调用(例如 search_user(name='jane') → send_message(id=12345))。
解决办法:在工具里暴露一个简单的 response_format 枚举参数,让智能体自己控制工具返回「简洁(concise)」还是「详细(detailed)」的回应。你还能加更多格式以获得更大灵活性,类似 GraphQL——精确选择你想接收哪些信息。
enum ResponseFormat {
DETAILED = "detailed",
CONCISE = "concise"
}
thread_ts 标识,而取回串中回复需要它。这类 ID(thread_ts / channel_id / user_id)可以从「详细」回应里取得,以支撑后续需要这些 ID 的工具调用;而「简洁」回应只返回帖子串内容、不含这些 ID。在这个例子里,「简洁」回应大约只用了「详细」回应 三分之一 的 token。最后还有一层:连工具回应的结构本身——XML、JSON 还是 Markdown——都会影响评估表现。不存在放之四海皆准的方案。因为 LLM 是在「下一个 token 预测」上训练出来的,往往在那些更贴合其训练数据的格式上表现更好。最优结构因任务和智能体而大相径庭,作者鼓励你按自己的评估来选。
上一节优化的是上下文的「质」,这一节优化的是上下文的「量」——返回给智能体的 token 到底有多少。
作者建议:对任何可能消耗大量上下文的工具回应,实现某种组合的分页(pagination)、范围选择(range selection)、过滤(filtering)和/或截断(truncation),并配上合理的默认参数值。
如果你选择截断回应,务必用有帮助的指示去引导智能体。你可以直接鼓励它采取更省 token 的策略——比如在知识检索任务里,做许多次小而精准的搜索,而不是一次宽泛的大搜索。
原文用三组截图分别示范了:一个截断的工具回应、一个没用的错误回应、一个有用的错误回应。其要旨是:
作者把这一条称为「最有效的方法之一」。因为工具描述和规格会被载入智能体的上下文,它们能合力把智能体引向高效的工具调用行为。
user,不如叫 user_id。有了评估,你就能更有信心地量化提示工程带来的影响。而且,即便是对工具描述的微小改进,也可能带来戏剧性的提升。
作者还给了几条延伸阅读与提醒:
结尾,作者把整篇文章拔到一个方法论的高度。
要为智能体构建有效的工具,我们需要把软件开发实践从可预测的、确定性的模式,重新定向到非确定性的模式上。
通过文中描述的这套迭代的、评估驱动的过程,他们识别出了「什么让工具成功」的一致规律:
有效的工具是 ——有意图地、清晰地被定义;审慎地使用智能体的上下文;能在多样的工作流里彼此组合;并且让智能体能直观地解决真实世界的任务。
展望未来,智能体与世界交互的具体机制还会不断演化——从 MCP 协议的更新,到底层 LLM 本身的升级。而只要坚持一套系统化、评估驱动的工具改进方法,我们就能确保:随着智能体变得更强,它们所用的工具也会与之一同进化。
本文由 Ken Aizawa 撰写,并得到 Anthropic 多个团队同事的宝贵贡献:研究团队(Barry Zhang、Zachary Witten、Daniel Jiang、Sami Al-Sheikh、Matt Bell、Maggie Vo)、MCP 团队(Theodora Chu、John Welsh、David Soria Parra、Adam Jones)、产品工程(Santiago Seira)、市场(Molly Vorwerck)、设计(Drew Roper)、以及应用 AI(Christian Ryan、Alexander Bricken)。