乐于分享
好东西不私藏

给 AI Agent 写工具?Anthropic 官方指南来了

给 AI Agent 写工具?Anthropic 官方指南来了

基于 Anthropic 官方文章《Writing Tools for Agents》的解读与实战笔记

当 AI Agent 可以调用上百个工具时,如何让这些工具真正有效?Anthropic 最近发布了一篇深度技术文章,分享了他们在优化 Agent 工具方面的实战经验。
本文将通过5 个典型场景 + 原文核心方法论,帮你完整理解“为 AI 设计工具”这件事。

Part 1:先搞懂一个核心认知

工具是一种“新物种”

传统函数:
weather = getWeather("NYC")程序员写死了调用时机、调用次数、参数内容,一切都是可控的。
Agent 工具:
AI 自己决定要不要调用AI 自己决定传什么参数AI 自己决定调用几次
这带来了什么变化?
传统软件是“程序员对程序员”的契约——你知道调用方会怎么用你的函数。
但 Agent 工具是“程序员对 AI”的契约——你不知道 AI 会:
什么时候调用(可能一轮对话调 50 次)
传什么参数(可能把姓名当邮箱传进来)
怎么理解返回结果(可能被无关信息淹没)

这就是“工具是一种新型软件”的真正含义。

三个核心挑战

挑战

具体含义

描述要写得让 AI 看得懂

AI 靠描述决定“什么时候用、怎么用”,描述模糊 → AI 用错

返回结果要让 AI 用得好

信息量、格式、长度都要考虑,否则 AI 要么被淹没,要么用不上

错误信息要让 AI 能恢复

不是给程序员看的 stack trace,而是告诉 AI “下一步该做什么”


Part 2:五个典型场景,看懂工具设计的坑

场景 1:工具描述写得太随意

两个工具定义,你觉得哪个更好?
工具 A:
名称:search描述:搜索参数:q(字符串)
工具 B:
名称:search_customer_orders描述:根据客户邮箱搜索其历史订单。      返回订单 ID、下单时间、金额、状态。      仅返回最近 90 天内的订单。参数:  - customer_email(字符串,必填,客户的邮箱地址)  - status(可选,过滤订单状态: 'pending' / 'shipped' / 'delivered' / 'cancelled'
工具B 是好在哪里呢?
1. 命名精确
search 起的名字一看实在是太宽泛了,AI 不知道搜什么,要干什么
search_customer_orders 职责单一,一看就懂,一看就是一个搜索订单的功能
2. 描述完整
好的工具描述要回答三个问题:
能做什么:“根据客户邮箱搜索历史订单”
返回什么:“订单 ID、下单时间、金额、状态”
不能做什么:“仅返回最近 90 天内”
3. 参数约束清晰
参数名是完整单词,不是缩写
类型、必填/可选明确
枚举值显式列出

记住:工具参数要做到“AI 看完不用猜”。


场景 2:返回结果设计不当

一个真实场景:
search_documents(query) 工具,搜公司内部 10000 份文档。用户问“找一下我们关于退款政策的文档”。
三种返回方式:
方式 1:返回所有 10000 份文档的标题和内容摘要
Context 直接爆掉,AI 被淹没
方式 2:返回匹配度最高的 5 份文档,每份包含标题、摘要、文档 ID、相关度评分
这个才是最好的方案
方式 3:只返回文档 ID 列表 ["doc_123", "doc_456", ...],让 AI 再调用 get_document(id) 获取详情
强制 AI 再绕一圈
方式 3 为什么不好?
很多人觉得“只返回 ID 最省 context”,但忽略了:

“省 context”不是唯一目标,“让 AI 高效完成任务”才是。

方式 3 的流程:
工具返回 ["doc_123", "doc_456", ...]
AI 啥也不知道——这些 ID 是什么文档?
AI 只能逐个调用 get_document(id) 去看
如果有 10 个 ID,就要再发 10 次工具调用
每次调用都要推理、等响应、花 token
生活分别与3个方式的类比
你问图书管理员:“有没有讲退款政策的书?”
方式 1:管理员把整个图书馆 10000 本书的清单塞给你
方式 2:管理员说“有 3 本最相关:《公司退款政策手册》《2024 退款流程更新》《客服退款 SOP》——要看哪本?”
方式 3:管理员说“有,编号是#123#456”——你还得一本一本去问内容

好工具返回的内容,要让 AI “看完就能决策”——既不淹没它,也不让它再绕一圈。


场景 3:错误信息要写给程序员

AI 调用 transfer_money(from_account, to_account, amount),报错提示目标账号不存在,下面有不同的返回。
返回 A:
ErrorValidationError at line 47 in transfer.pyaccount_lookup() returned NoneStack trace: ...
返回 B:
ErrorAccount 'ACC_99999' not found. Please verify the account numberYou can use list_accounts() to see all available accounts.
一看B的错误提示相对于A来讲就好很多,来看看B 好在哪里?
1. 用自然语言,不是 stack trace
AI 不会去看你的代码,stack trace 对它是噪音
2. 包含具体的错误值
不只说“账号不存在”,而是说“ACC_99999 不存在”
AI 立刻知道是哪个参数错了
3. 给出可行动的下一步
"You can use list_accounts() to see all available accounts"
在错误信息里指了一条路

工具的错误信息不是“事故报告”,是“恢复指南”。

口诀:人话 + 具体 + 出路。


场景 4:综合设计不够专业

一道设计题:
给客服 Agent 设计查询订单状态的工具。
初学者的设计:
工具名:get_order_status参数:订单 id 或订单 id 列表返回:订单状态(如 New, Cancel, Success)
一起看看问题在哪?
1. 参数设计不统一
“id 或 id 列表”这种二选一设计让 AI 犯迷糊。
专业写法:
参数:order_ids(必填,订单 ID 列表)
示例:["ORD_001"] 或 ["ORD_001", "ORD_002"]

支持批量的工具,参数永远是 list;单个调用就传只有一个元素的列表。

2. 返回内容太薄
只返回状态码,AI 无法回答“为什么订单取消了?”
专业的返回设计:
{  "results": [    {      "order_id": "ORD_001",      "found": true,      "status": "cancelled",      "status_updated_at": "2026-05-10",      "amount": 299.00,      "cancel_reason": "客户主动取消"    },    {      "order_id": "ORD_999",      "found": false,      "error": "Order ID not found. Please verify the order number."    }  ]}
这个设计做对了四件事:
  • 每条都带 order_id,AI 能对应回复用户的输入
  • found 字段区分订单是否可以查到
  • 失败的也返回,AI 知道哪个 order_id 错了
  • 状态码附带辅助信息(时间、金额、原因)
3. 没考虑大结果集
如果用户问“我所有订单的情况”,有 200 单怎么办?
不要把 200 单原始数据丢给 AI。
专业设计:分页 + 默认限制
工具:list_customer_orders(customer_id, limit=10, offset=0, status_filter=None)
  • 默认只返回最近 10 单
  •  limit 最大不超过 50
  • 支持分页查更多
  • 支持按状态过滤

分页、排序、过滤这些事,工具自己要做,别直接推给 AI。


场景 5:选择了错误的工具

反面案例:
想象一个通讯录搜索任务。如果工具返回所有 10000 个联系人,Agent 需要逐个 耗费token 阅读——这就像你在通讯录里从头到尾逐页查找,而不是直接跳到相关页面(比如按字母顺序)。
关键洞察:

LLM Agent 的上下文是有限且昂贵的,而计算机内存是廉价且充足的。

正面做法:
不要:list_contacts() 返回所有联系人
应该:search_contacts(name) 或 message_contact(name)
工具可以整合功能:
一个工具可以在底层处理多个离散操作或 API 调用。
示例:
  • 搜索工具返回结果时,附带相关元数据
  • 处理经常链式调用的多步任务
  • 一次工具调用完成人类通常需要多步的操作
核心原则:
  • 每个工具都应该有清晰、独特的目的
  • 让 Agent 能像人类一样细分和解决任务
  • 减少中间输出消耗的上下文

更多工具 ≠ 更好的结果。太多工具或重叠的工具会分散 Agent 的注意力。


Part 3:上述的总结

学完这篇要带走的 7 句话:
  1. 传统软件是程序员对程序员的契约;工具是程序员对 AI 的契约。
  2. 好的工具描述要回答三个问题:能做什么、返回什么、不能做什么。
  3. 工具参数要做到 AI 看完不用猜——名字、类型、含义、可选值、必填性要全明示。
  4. 好工具返回的内容,要让 AI 看完就能决策——既不淹没它,也不让它再绕一圈。
  5. 分页、排序、过滤这些事,工具自己要做,别推给 AI。
  6. 工具错误信息不是事故报告,是恢复指南——人话 + 具体 + 出路。
  7. 支持批量的工具,参数永远是 list;单个调用就传只有一个元素的列表。

展望未来

要为 Agent 构建有效的工具,我们需要将软件开发实践从可预测的确定性模式重新定向到非确定性模式
通过本文描述的迭代、评估驱动的过程,我们发现了让工具成功的一致模式:

有效的工具是有意图且清晰定义的,明智地使用 Agent 上下文,可以在多样化的工作流中组合使用,并使 Agent 能够直观地解决真实世界的任务。

未来,Agent 与世界交互的具体机制会不断演进——从 MCP 协议的更新到底层 LLM 本身的升级。通过系统性、评估驱动的方法改进 Agent 工具,我们可以确保:随着 Agent 变得更强大,它们使用的工具也会随之进化。