为 AI Agent 编写有效工具

原文:Writing Effective Tools for AI Agents
来源:Anthropic Engineering Blog
翻译整理:2026-06-16


核心洞察

工具是一种全新类型的软件,它反映的是确定性系统与非确定性 Agent 之间的契约

这一定义揭示了工具设计区别于传统 API 设计的本质:API 的调用方是另一段代码(行为确定),而 Agent 工具的调用方是 LLM(行为非确定)。这意味着工具设计必须优先考虑 LLM 的理解能力和决策特点,而非仅仅封装底层 API 的能力。


最常见的错误:把 API 端点直接封装成工具

“仅封装现有 API 端点”是工具设计中最常见的错误。

反例:GitHub MCP server

GitHub MCP server 将 GitHub 的每个 API 端点都暴露为一个独立工具,结果工具定义本身就消耗了 40,000-55,000 tokens 的上下文窗口。

这直接造成两个问题:

  1. Agent 的可用上下文空间被工具定义大幅压缩
  2. 工具数量过多,Agent 无法准确判断在特定场景应该调用哪个工具

正确方向:针对高价值工作流构建精炼工具

不要问「这个 API 端点要不要封装?」,而要问「Agent 最常需要完成哪些任务?」针对这些任务设计工具,而不是机械地映射 API。


工具设计三步法

第一步:构建原型

基于 API 文档和 SDK,创建工具的初始实现,通过 MCP server 或 Desktop 扩展在本地进行测试。

目标:快速构建可运行的原型,不追求完美,先让 Agent 能用起来。

第二步:运行评估

围绕真实工作流设计测试用例,系统性地衡量 Agent 表现:

  • 准确率:Agent 是否正确完成了任务?
  • Token 消耗:每次任务消耗了多少上下文?
  • 工具错误率:Agent 选错工具或调用失败的频率?

关键:测试用例必须基于「真实工作流」,而非人为构造的边缘情况。

第三步:用 AI 迭代优化

使用 Claude Code 分析评估结果中的 transcript(执行日志),自动识别瓶颈并优化工具实现。

这一步的核心是让 AI 来优化 AI 使用的工具,而非依赖工程师的直觉手动调整。


五大设计原则

原则 1:工具少而精,而非多而全

“更多的工具不总是带来更好的结果。”

推荐做法:构建少数能处理多步操作的强力工具,而非把每个 API 端点单独封装。

示例对比

❌ 错误做法:

check_calendar_availability(date, time)
create_calendar_event(title, date, time, attendees)
send_calendar_invite(event_id, attendees)

✅ 正确做法:

schedule_event(title, date, time, attendees)
  # 内部自动处理:检查可用性 → 创建事件 → 发送邀请

合并成单一工具的好处:Agent 只需做一次决策,而不是链式调用三次,大幅降低出错概率。

原则 2:用命名空间防止工具混淆

当 Agent 同时接入多个系统时,使用一致的前缀进行分组:

asana_search        # Asana 相关
asana_create_task
asana_update_task

jira_search         # Jira 相关
jira_create_issue
jira_update_issue

这使 Agent 在选择工具时能快速定位到正确的系统,减少「混用工具」的决策错误。

原则 3:返回高信息密度的响应

工具的返回值应该让 Agent「一眼看懂」,而不是返回需要二次解析的原始数据。

示例对比

❌ 低质量返回(返回内部 ID):

{"task_id": "TASK-4721934", "assignee_id": "USR-001923"}

✅ 高质量返回(返回语义化信息):

{"task": "Fix login bug", "assignee": "Alice Chen", "due": "2026-06-20"}

进阶技巧:提供 response_format 参数,让 Agent 按需选择详细程度:

  • summary:只返回关键字段(省 token)
  • full:返回完整信息(需要细节时)

原则 4:Token 优化——分页、过滤、截断

工具返回值过大是上下文污染的主要来源之一。

最佳实践

  • 默认返回分页结果,而非一次性返回所有数据
  • 支持过滤参数,让 Agent 只获取相关数据
  • 对超长文本进行截断,并在响应中说明「已截断,可通过 X 获取完整内容」
  • 通过有用的错误信息引导 Agent 向正确的查询模式靠拢

示例

# 错误信息不应该是:
"Error: too many results"

# 而应该是:
"返回了 1000+ 条结果,建议添加时间范围过滤(参数:start_date, end_date)
 以缩小结果集。当前仅返回前 20 条。"

原则 5:工具描述即指令,而非文档

工具描述对 Agent 性能的影响远超大多数工程师的预期。

心智模型转变:不要把工具描述当「API 文档」来写,要把它当「给新团队成员的操作指南」来写。

差异对比

❌ 文档风格(描述「是什么」):

search_emails: Searches the email database using the provided query string.
Parameters:
  - query: Search query
  - limit: Max results

✅ 指令风格(描述「怎么用」和「什么时候用」):

search_emails: 在用户邮件中搜索相关内容。
适用场景:用户询问某封邮件是否存在、需要找特定人发的邮件、
          或需要根据邮件内容采取行动时。
注意:对于"最近的邮件",使用 date_filter="last_7_days";
     对于发件人搜索,使用 from="email@example.com" 而非在 query 中写名字。

关键结论

通过这套「原型 → 评估 → AI 迭代」的流程,Anthropic 内部评估显示工具性能有可量化的显著提升,远优于依靠工程师直觉手动调优的结果。

工具设计的根本原则只有一条:工具是为 LLM 设计的,不是为人类设计的。所有设计决策——少而精、命名清晰、返回语义化、描述像指令——都是这一原则的不同侧面。


与其他文章的关联

  • 本文工具设计原则与 Context Engineering 强关联:精炼的工具集是有效上下文管理的前提条件
  • GitHub MCP server 的反例同时出现在两篇文章中,印证了「工具膨胀 → 上下文污染 → Agent 性能下降」的完整链条