来源:Anthropic Engineering原文:Writing effective tools for agents — with agents发布时间:2025-09-11
这个系列进度
这个系列按 Anthropic Engineering 的 5 篇文章逐篇学习 AI Agent 工程:
1. Effective context engineering for AI agents 2. Writing effective tools for agents 3. Equipping agents for the real world with Agent Skills 4. Code execution with MCP 5. Harness design for long-running application development
第一篇讲 Context:模型每一步应该看见什么。第二篇开始看 Tools:Agent 要通过什么工具和外部世界交互,以及这些工具为什么不能简单照搬传统 API 设计。
简介
Agent 的能力很大程度取决于我们给它的工具。工具不是普通函数,也不是简单包一层 API endpoint 就够了。它是确定性软件系统和非确定性 Agent 之间的接口。
Anthropic 原文先讲如何构建、测试、评估和迭代工具,再总结了几条工具设计原则:选对工具、给工具做命名空间、返回有意义的上下文、控制 token 消耗,以及对工具描述和 schema 做 prompt engineering。
什么是 tool
在传统软件里,确定性系统在相同输入下会得到相同输出。比如 getWeather("NYC") 每次都会按同样方式查询纽约天气。
但 Agent 是非确定性的。用户问“我今天要不要带伞?”时,Agent 可能调用天气工具,也可能根据常识回答,也可能先追问用户的位置。有时它甚至会幻觉,或者没有理解工具该怎么用。
所以,工具是一种新的软件形态。它体现的是确定性系统和非确定性 Agent 之间的 contract。
这意味着为 Agent 写工具时,不能只按传统函数、API 或 MCP server 的思路设计。工具的使用者不是另一个确定性程序,也不一定是熟悉接口语义的人类开发者,而是一个会推理、会误解、会探索、也可能走弯路的 Agent。
Anthropic 的目标是扩大 Agent 能有效解决任务的范围。工具应该支持 Agent 用多种成功策略完成真实任务。一个有意思的经验是:对 Agent 来说 ergonomics 好的工具,对人类也往往更直观。
如何写工具
Anthropic 建议的流程是:
1. 先快速做出工具原型。 2. 本地测试,找出粗糙边缘。 3. 建立评估,系统衡量工具表现。 4. 让 Agent 参与分析结果和改进工具。 5. 重复评估和优化,直到 Agent 在真实任务上有稳定表现。

1. 先做原型
很多时候,提前想象哪些工具对 Agent 好用、哪些不好用是很难的。最直接的方法是先做一个快速原型,自己上手测试。
如果用 Claude Code 写工具,可以把工具依赖的软件库、API、SDK 文档给 Claude。这里也包括 MCP SDK。
Anthropic 提到,适合 LLM 阅读的文档通常可以在官方文档站点的 llms.txt 里找到。把这类文档提供给 Agent,有助于它理解依赖的真实用法。
为了在 Claude Code 或 Claude Desktop 里测试工具,可以把工具包装成本地 MCP server 或 Desktop extension,也就是 DXT。
连接方式包括:
• 在 Claude Code 里连接本地 MCP server: claude mcp add <name> <command> [args...]• 在 Claude Desktop 里连接本地 MCP server:进入 Settings > Developer• 在 Claude Desktop 里连接 DXT:进入 Settings > Extensions• 如果是程序化测试,也可以直接把工具传入 Anthropic API 调用
原型阶段要自己测试工具,找到使用上的粗糙点。同时也要收集用户反馈,形成对真实使用场景和真实 prompt 的直觉。
2. 跑评估
下一步是衡量 Claude 使用这些工具的效果。
评估任务要来自真实使用,而不是过于简单的 sandbox。Anthropic 建议和 Agent 协作生成大量评估任务,再用 Agent 帮助分析结果、判断工具应该怎么改。

生成评估任务
有了早期原型后,Claude Code 可以快速探索工具,并生成几十组 prompt 和 response pair。
Prompt 应该来自真实使用场景,基于真实的数据源和服务,比如内部知识库、微服务等。Anthropic 不建议用过于简单、表面的 sandbox 环境,因为它们无法用足够复杂度压力测试工具。
强评估任务可能需要多次工具调用,甚至几十次。
强任务示例:
• 安排下周和 Jane 开会,讨论最新的 Acme Corp 项目。附上上一次项目计划会的会议记录,并预订一个会议室。 • 客户 ID 9182 报告说一次购买尝试被扣款三次。找出所有相关日志,并判断是否有其他客户受到同一问题影响。 • 客户 Sarah Chen 刚提交取消请求。准备一个挽留方案。需要判断:1. 她为什么离开;2. 什么挽留方案最有吸引力;3. 在提出方案前需要注意哪些风险因素。
弱任务示例:
• 安排下周和 jane@acme.corp[1] 开会。 • 在支付日志里搜索 purchase_complete和customer_id=9182。• 通过 Customer ID 45892 找到取消请求。
强任务和弱任务的区别在于:强任务更接近真实工作,需要 Agent 自己规划路径、组合工具、处理上下文;弱任务更像直接调用某个接口。
每个评估 prompt 都应该配一个可验证的响应或结果。Verifier 可以很简单,比如 ground truth 和 sampled response 做精确字符串比较;也可以更复杂,比如让 Claude 判断回答是否正确。
但 verifier 不要过于严格。正确答案可能因为格式、标点或合理改写而不同,不能因为这些无关差异把正确回答判错。
每组 prompt-response 也可以指定预期会调用哪些工具,用来衡量 Agent 是否理解每个工具的用途。但要注意,不同任务可能有多条正确路径,不要过度指定策略,避免过拟合。
运行评估
Anthropic 建议用直接 LLM API 调用来程序化运行评估。
实现上可以用简单 agentic loop:一个 while loop 包住交替进行的 LLM API 调用和工具调用。每个评估任务对应一个 loop,每个评估 Agent 拿到一个任务 prompt 和工具集。
在评估 Agent 的 system prompt 里,Anthropic 建议要求 Agent 不只输出用于验证的结构化 response blocks,还要输出 reasoning 和 feedback blocks。
如果让 Agent 在 tool call 和 response blocks 之前先输出 reasoning 和 feedback,可能会触发 chain-of-thought 行为,提高 LLM 的有效智能。
如果使用 Claude,也可以开启 interleaved thinking,获得类似能力。这有助于观察 Agent 为什么调用或不调用某些工具,也能发现工具描述和 schema 里的具体改进点。
除了顶层准确率,还应该收集其他指标:
• 单个工具调用的总运行时间 • 单个任务的总运行时间 • 工具调用总次数 • token 总消耗 • 工具错误
跟踪工具调用可以揭示 Agent 常走的工作流,也可能暴露哪些工具可以合并。

分析结果
Agent 可以帮助发现问题和给反馈,包括:
• 工具描述互相矛盾 • 工具实现低效 • tool schema 让人困惑 • 参数命名不清楚 • 返回结果不利于下一步推理
但 Anthropic 特别提醒:Agent 没说出来的东西,往往比它说出来的东西更重要。LLM 不总是“说出自己真正的意思”。
因此,不能只看 Agent 的反馈文字。还要观察 Agent 卡住或困惑的地方,阅读 reasoning 和 feedback,检查原始 transcript,包括工具调用和工具返回结果。
如果 CoT 里没写出某个问题,也不代表问题不存在。评估 Agent 本身不一定知道正确答案和正确策略,所以要学会 read between the lines。
工具调用指标也很重要:
• 大量重复工具调用,可能说明分页或 token limit 参数需要重新设计。 • 大量 invalid parameter 错误,可能说明工具描述不清楚,或者缺少更好的例子。
Anthropic 举了 Claude web search 工具的例子。上线时他们发现 Claude 会无意义地把 2025 追加到 query 参数里,导致搜索结果偏斜、性能下降。后来通过改进工具描述,把 Claude 引导回了正确方向。
3. 和 Agent 协作优化工具
评估完成后,可以直接让 Agent 帮你分析结果、改进工具。
做法很简单:把评估 Agent 的 transcripts 拼接起来,粘贴给 Claude Code。Claude 很擅长分析 transcript,并一次性重构很多工具,比如在新改动后确保工具实现和描述仍然自洽。
Anthropic 说,这篇文章里的大多数建议,来自他们反复用 Claude Code 优化内部工具实现的过程。
他们的评估建立在内部 workspace 之上,保留了内部工作流的复杂度,包括真实项目、文档和消息。
同时,他们使用 held-out test sets,确保不会过拟合“训练用”的评估集。结果显示,即使在“专家实现”的工具基础上,还能继续挖出额外性能提升。这里的专家工具既包括研究人员手写的工具,也包括 Claude 自己生成的工具。
写好工具的原则
下面是 Anthropic 从这个过程里总结出的工具设计原则。
1. 为 Agent 选择正确的工具
更多工具不一定带来更好结果。
一个常见错误是:只是把已有软件功能或 API endpoint 包成工具,不管这些工具是否适合 Agent 使用。
原因是 Agent 和传统软件有不同的 affordances。这里可以理解为:Agent 感知和选择行动的方式,与普通程序不同。
LLM Agent 的 context 是有限的,而计算机内存便宜且充足。
以地址簿里找联系人为例。传统软件可以高效地存储和逐条处理联系人列表。但如果 LLM Agent 调用一个返回所有联系人的工具,再逐 token 读完整个列表,那就是在用有限 context 处理大量无关信息。
这就像在通讯录里找一个联系人,却从第一页开始逐页读完。更自然的方法是先跳到相关页面,比如按字母索引定位。
因此,Anthropic 建议先构建少量、经过思考的工具,聚焦高影响工作流,并让它们匹配评估任务,然后再扩展。
在地址簿场景中,比起实现 list_contacts,更适合实现:
• search_contacts• message_contact
工具可以在内部整合多个离散操作或 API 调用。比如工具可以把相关元数据加入返回结果,也可以把经常串联的多步任务包装成一次工具调用。
例子:
• 与其实现 list_users、list_events、create_event三个工具,不如实现一个schedule_event工具,负责查找可用时间并安排会议。• 与其实现 read_logs工具,不如实现search_logs工具,只返回相关日志行和周边上下文。• 与其实现 get_customer_by_id、list_transactions、list_notes,不如实现get_customer_context,一次汇总客户近期相关信息。
每个工具都应该有清晰、独立的目的。工具要帮助 Agent 像人类一样拆分和解决任务,同时减少中间输出消耗的 context。
工具太多、重叠太多,也会干扰 Agent 选择高效策略。谨慎决定哪些工具该做、哪些不该做,会带来真实收益。
2. 给工具做 namespacing
AI Agent 可能接入几十个 MCP server,获得几百个工具,其中还包括其他开发者写的工具。
当工具功能重叠或目的模糊时,Agent 会不知道该用哪个。
Namespacing,也就是把相关工具放在共同前缀下,可以帮助 Agent 区分工具边界。MCP client 有时会默认这么做。
例子:
• 按服务命名: asana_search、jira_search• 按资源命名: asana_projects_search、asana_users_search
这样可以帮助 Agent 在正确时间选择正确工具。
Anthropic 发现,前缀式命名和后缀式命名在工具使用评估中会产生非平凡影响。不同 LLM 的效果也不同,所以命名方案最好根据自己的评估选择。
Agent 可能犯的错包括:
• 调错工具 • 用错参数调用正确工具 • 调用工具太少 • 错误处理工具返回结果
通过选择性实现工具,并让工具名反映任务的自然拆分方式,可以同时减少进入 Agent context 的工具数量和工具描述数量,也能把一部分 agentic computation 从 Agent context 转移到工具调用内部。这样能降低 Agent 出错风险。
3. 工具要返回有意义的 context
工具实现应该只把高信号信息返回给 Agent。
工具返回结果应该优先考虑上下文相关性,而不是最大灵活性。低层技术标识符通常不适合直接返回给 Agent,比如:
• uuid• 256px_image_url• mime_type
更可能直接帮助 Agent 后续行动和回答的是:
• name• image_url• file_type
Agent 处理自然语言名称、术语或标识符,通常比处理隐晦技术 ID 更成功。
Anthropic 发现,仅仅把任意字母数字 UUID 解析为更有语义、更容易理解的语言,甚至改成 0-indexed ID scheme,都能显著提升 Claude 在检索任务中的 precision,并减少幻觉。
有些场景里,Agent 既需要自然语言信息,也需要技术 ID,因为后续工具调用可能依赖这些 ID。比如:
search_user(name="jane") -> send_message(id=12345)
这时可以暴露一个简单的 response_format enum 参数,让 Agent 控制工具返回 concise 还是 detailed。
也可以增加更多格式,类似 GraphQL 让调用方选择具体需要哪些信息。
示例 enum:
enum ResponseFormat { DETAILED = "detailed", CONCISE = "concise"}原文给了两个例子:
• detailed tool response:206 tokens • concise tool response:72 tokens


在 Slack 线程场景里,线程和回复通过唯一的 thread_ts 标识。获取线程回复时需要 thread_ts,其他 ID 如 channel_id、user_id 也可能用于后续工具调用。
detailed 返回可以包含这些 ID,让 Agent 有能力继续调用需要 ID 的工具。
concise 返回只包含线程内容,不包含 ID。这个例子里,concise 只用了大约三分之一 token。
工具响应的结构也会影响评估表现,比如 XML、JSON、Markdown。不存在一种适用于所有场景的格式。因为 LLM 是按 next-token prediction 训练的,它们通常更擅长处理训练数据中常见的格式。最优响应结构会随任务和 Agent 大幅变化,需要通过自己的评估选择。
4. 优化工具响应的 token 效率
优化返回 context 的质量很重要,优化数量也同样重要。
对可能大量消耗 context 的工具响应,Anthropic 建议组合使用:
• pagination • range selection • filtering • truncation
同时要给这些参数设置合理默认值。
Claude Code 默认把工具响应限制在 25,000 tokens。Anthropic 预计 Agent 的有效 context 长度会继续增长,但 context-efficient tools 的需求仍然会存在。
如果选择截断响应,要给 Agent 有帮助的指令。可以直接鼓励 Agent 采取更省 token 的策略,比如在知识检索任务中,做多次小而精准的搜索,而不是一次宽泛搜索。
如果工具调用因为输入校验而报错,也可以对错误响应做 prompt engineering,让错误信息清楚说明具体、可执行的改进,而不是只返回不透明的错误码或 traceback。
原文给了一个截断响应示例:

也对比了无帮助和有帮助的错误响应:


工具截断和错误响应本身也能引导 Agent 采用更省 token 的工具使用行为,比如使用 filters 或 pagination,也能给出正确格式化工具输入的例子。
5. 对工具描述做 prompt engineering
最后,Anthropic 认为最有效的工具改进方式之一,是对工具描述和 spec 做 prompt engineering。
因为这些描述会被加载进 Agent 的 context,所以它们会共同引导 Agent 的工具调用行为。
写工具描述时,可以想象自己在向团队新成员介绍这个工具。你脑子里隐含的上下文要写出来,比如:
• 特殊查询格式 • 专有术语定义 • 底层资源之间的关系 • 输入输出的约束 • 工具适合和不适合的场景
要避免歧义,清楚描述输入输出,并用严格数据模型 enforcing。
输入参数尤其要命名明确。比如,与其把参数叫 user,不如叫 user_id。
有了评估,就能更有信心地衡量 prompt engineering 的影响。即使很小的工具描述修改,也可能带来明显提升。
Anthropic 提到,Claude Sonnet 3.5 在 SWE-bench Verified 上达到当时最优表现,其中一个关键点就是对工具描述做了精确优化,显著降低错误率并提升任务完成度。
如果为 Claude 构建工具,可以参考 Anthropic Developer Guide 里的工具定义最佳实践,也可以了解工具如何动态加载进 Claude 的 system prompt。
如果为 MCP server 写工具,MCP 的 tool annotations 可以说明哪些工具需要 open-world access,哪些会做破坏性修改。
展望
要为 Agent 构建有效工具,需要把软件开发实践从传统的确定性模式,调整到适配非确定性系统的模式。
通过这篇文章描述的迭代式、评估驱动流程,Anthropic 总结出有效工具的一些共同模式:
• 工具要有意设计,并清楚定义。 • 工具要谨慎使用 Agent context。 • 工具之间可以组合成多样工作流。 • 工具要帮助 Agent 直观地解决真实任务。
未来,Agent 和世界交互的具体机制还会变化,比如 MCP 协议更新、底层 LLM 升级。但只要用系统化、评估驱动的方法改进 Agent 工具,就能让工具随着 Agent 能力一起演进。
关键术语说明
• Tool:Agent 调用外部系统、获取信息或执行动作的接口。 • Deterministic system:相同输入总是得到相同输出的系统。 • Non-deterministic agent:即使初始条件相同,也可能产生不同响应和行动路径的 Agent。 • MCP server:通过 Model Context Protocol 暴露工具和资源的服务。 • DXT:Desktop extension,用于把本地能力接入 Claude Desktop。 • Evaluation:用可验证任务系统衡量工具表现的方法。 • Held-out test set:不参与优化过程、只用于最终验证的测试集,用来避免过拟合。 • Namespacing:通过共同前缀或结构化命名,把相关工具分组,帮助 Agent 识别边界。 • Response format:工具返回内容的格式或详细程度,比如 concise和detailed。• Token efficiency:让工具用更少 token 返回更有用的信息。 • Tool annotations:MCP 中用于声明工具特性、权限和风险的信息。
使用场景和注意点
这篇文章适合三类人重点学习:
第一,正在写 MCP server、内部 Agent 工具或 Claude Code 插件的人。它会帮助你避免把 API endpoint 机械包装成工具。
第二,正在做 Agent 产品评估的人。文章强调不要只凭感觉改工具,而要用真实任务、真实数据和 held-out test set 迭代。
第三,正在做长任务 Agent 的人。工具返回内容越臃肿,Agent 越容易浪费 context;工具边界越模糊,Agent 越容易走错路。
实际使用时要注意:工具设计不是“功能越多越好”。对 Agent 来说,工具应该让正确行动更容易,让无关 context 更少进入模型。
可复习要点
1. Agent 工具不是传统 API;它是确定性系统和非确定性 Agent 的 contract。 2. 写工具要走原型、评估、分析、迭代的流程,不能只靠直觉。 3. 强评估任务要接近真实工作,通常需要多步工具调用。 4. 工具越多不一定越好;应优先做高影响、边界清晰的工具。 5. 工具返回内容要高信号、低噪声、token efficient。 6. 工具描述和 schema 本身也需要 prompt engineering。
夜雨聆风