【智能体工具】Claude工具设计原则
原文Claude如何为智能体撰写工具,介绍了工具撰写的很多细节,个人觉得这些细节也可以用到提示词中。
为智能体编写高效工具——借助智能体自身实现
智能体的效能完全取决于我们为其配备的工具。本文将分享如何编写高质量的工具与评估方案,以及如何利用Claude优化其自身工具以提升性能。
模型上下文协议(MCP)能为大语言模型(LLM)智能体赋能,使其可调用数百种工具解决现实世界的任务。但如何让这些工具发挥最大效用?
在本文中,我们将介绍在各类智能体人工智能系统中提升性能的最有效技术¹。内容将从以下方面展开:
- 构建并测试工具原型
- 利用智能体创建并运行全面的工具评估
- 与Claude Code等智能体协作,自动提升工具性能
最后,我们将总结编写高质量工具的核心原则:
- 选择适合实现(及无需实现)的工具
- 对工具进行命名空间划分,明确功能边界
- 工具向智能体返回有意义的上下文信息
- 优化工具响应以提升令牌效率
- 对工具描述和规格进行提示工程优化
- 整合附加内容
什么是工具?
在计算机领域,确定性系统在输入相同时始终产生相同输出,而非确定性系统(如智能体)即使初始条件一致,也可能生成多样化响应。
传统软件开发中,我们实则在确定性系统间建立一种约定。例如,getWeather("NYC") 这类函数调用,每次执行时都会以完全相同的方式获取纽约市的天气数据。
工具是一类新型软件,反映了确定性系统与非确定性智能体之间的约定。当用户询问“今天我需要带雨伞吗?”时,智能体可能会调用天气工具、凭借常识回答,甚至先询问具体位置以明确上下文。有时,智能体也可能出现幻觉,或完全无法理解如何使用工具。
这意味着为智能体编写软件时,我们需要从根本上重新思考方法:不应像为其他开发者或系统编写函数和API那样设计工具和MCP服务器,而需专为智能体量身打造。
我们的目标是通过工具支持多种成功策略,扩大智能体有效解决各类任务的范围。幸运的是,根据我们的经验,对智能体“易用”的工具,对人类而言也往往极具直观性。
如何编写工具
本节将介绍如何与智能体协作,实现工具的编写与优化。首先快速搭建工具原型并进行本地测试,接着通过全面评估衡量后续改进效果。与智能体携手,反复执行评估与优化流程,直至智能体在现实任务中达到理想性能。
构建原型
若不亲自实践,很难预判智能体对工具的适配程度。首先快速搭建工具原型:若使用Claude Code编写工具(可能通过单次交互完成),需向Claude提供工具所依赖的所有软件库、API或SDK(包括MCP SDK)的文档。官方文档网站通常会提供适合大语言模型读取的扁平化 llms.txt 文件(示例见我们的API文档)。
将工具封装到本地MCP服务器或桌面扩展(DXT)中,即可连接并在Claude Code或Claude桌面应用中测试。
- 连接本地MCP服务器至Claude Code:运行
claude mcp add <名称> <命令> [参数...] - 连接本地MCP服务器或DXT至Claude桌面应用:分别导航至
设置 > 开发者或设置 > 扩展 - 工具也可直接传入Anthropic API调用,进行程序化测试
亲自测试工具以发现潜在问题,收集用户反馈,深入理解工具的预期使用场景和触发提示词。
执行评估
接下来,通过评估衡量Claude对工具的使用效果。首先基于现实场景生成大量评估任务,建议与智能体协作分析结果、确定改进方向。完整流程可参考我们的工具评估指南。
生成评估任务
借助早期原型,Claude Code能快速探索工具功能,生成数十组提示词-响应对。提示词应基于真实使用场景,依托真实数据源和服务(如内部知识库、微服务),避免使用过于简化或表层的“沙箱”环境——这类环境无法通过足够复杂度检验工具性能。优质评估任务可能需要多次(甚至数十次)工具调用。
优质任务示例:
- 下周与Jane安排会议,讨论Acme Corp最新项目,附上上次项目规划会议的纪要并预订会议室。
- 客户ID 9182反馈单次购买尝试被收取三次费用,查找所有相关日志条目,确认是否有其他客户受同一问题影响。
- 客户Sarah Chen刚提交取消请求,制定挽留方案:(1)明确其取消原因;(2)确定最具吸引力的挽留条件;(3)梳理提供该方案前需关注的风险因素。
劣质任务示例:
- 下周与jane@acme.corp安排会议。
- 在支付日志中搜索
purchase_complete和customer_id=9182。 - 查找客户ID 45892的取消请求。
每个评估提示词需搭配可验证的响应或结果。验证器可简单至精确字符串比对(对比基准答案与生成响应),也可进阶至委托Claude进行结果判定。避免使用过于严格的验证器——这类验证器可能因格式、标点差异或合理的表述变体而误判正确响应。
对于每组提示词-响应对,可选择性指定解决任务所需调用的工具,以评估智能体在测试过程中是否能准确理解各工具的用途。但需注意,任务的正确解决路径可能不止一条,应避免过度指定或过度拟合特定策略。
运行评估
建议通过直接调用LLM API程序化执行评估,为每个评估任务设置简单的智能体循环(while 循环包裹交替的LLM API调用和工具调用)。每个评估智能体仅分配一个任务提示词和相关工具。
在评估智能体的系统提示词中,建议要求其不仅输出结构化响应块(用于验证),还需输出推理过程和反馈块。在工具调用和响应块之前输出这些内容,可通过触发思维链(CoT)行为提升大语言模型的实际智能表现。
若使用Claude执行评估,可直接开启“交错思维”功能以实现类似效果。这有助于探究智能体调用或不调用特定工具的原因,并凸显工具描述和规格中需改进的具体环节。
除整体准确率外,建议收集其他指标:单个工具调用和任务的总运行时间、工具调用总次数、令牌消耗总量及工具错误情况。追踪工具调用可揭示智能体常用的工作流程,为工具功能整合提供方向。
分析结果
智能体是发现问题的得力助手,能就工具描述矛盾、实现效率低下、架构混乱等问题提供反馈。但需注意,智能体在反馈和响应中“未提及”的内容往往比“已提及”的更重要——大语言模型并非总能准确表达真实想法。
观察智能体受阻或困惑的环节,研读评估智能体的推理过程和反馈(或思维链)以发现潜在问题,查看原始记录(包括工具调用和响应)以捕捉智能体思维链中未明确描述的行为。需透过现象看本质:评估智能体未必知晓正确答案和策略。
分析工具调用指标:大量冗余调用可能表明需要调整分页或令牌限制参数;频繁因参数无效导致工具错误,可能意味着工具需要更清晰的描述或更详实的示例。例如,我们在推出Claude的网页搜索工具时发现,Claude会不必要地在工具的 query 参数后附加 2025,导致搜索结果出现偏差、性能下降——通过优化工具描述,我们成功引导Claude纠正了这一行为。
与智能体协作
甚至可让智能体直接分析结果并优化工具:只需将评估智能体的记录拼接后输入Claude Code,Claude擅长分析记录并批量重构工具(例如,确保新增变更后工具实现与描述的一致性)。
事实上,本文中的大部分建议都源于我们通过Claude Code反复优化内部工具实现的过程。我们的评估基于内部工作环境构建,还原了内部工作流程的复杂性,涵盖真实项目、文档和消息。
我们借助预留测试集确保不会过度拟合“训练型”评估,这些测试集显示,即便与“专家级”工具实现(无论是研究人员手动编写还是Claude生成)相比,我们仍能进一步提升性能。
编写高效工具的原则
本节将我们的经验提炼为编写高效工具的核心指导原则。
为智能体选择合适的工具
工具数量并非越多越好。我们发现一个常见误区:无论工具是否适合智能体,都仅对现有软件功能或API端点进行简单封装。这是因为智能体与传统软件具有截然不同的“功能适配性”——即它们对工具可执行操作的感知方式存在差异。
大语言模型智能体的“上下文”有限(即一次可处理的信息量存在上限),而计算机内存则廉价且充足。以地址簿联系人搜索为例:传统软件可高效地逐个处理联系人列表,逐一检查后再推进;但如果大语言模型智能体使用的工具会返回“所有联系人”,再让其逐令牌读取,就会将有限的上下文空间浪费在无关信息上(类似通过逐页通读地址簿的蛮力方式查找联系人)。对智能体和人类而言,更优、更自然的方式是先定位相关页面(例如按字母顺序查找)。
建议针对特定高影响力工作流程构建少量精心设计的工具,确保工具与评估任务匹配,再逐步扩展。以地址簿场景为例,可实现 search_contacts(搜索联系人)或 message_contact(联系联系人)工具,而非 list_contacts(列出所有联系人)工具。
工具可整合多项功能,在底层处理多个独立操作(或API调用)。例如,工具可在响应中补充相关元数据,或在单次调用中完成常用的多步骤任务。
示例:
- 无需分别实现
list_users(列出用户)、list_events(列出事件)和create_event(创建事件)工具,可设计schedule_event(安排事件)工具,整合查找可用时间和创建事件的功能。 - 无需实现
read_logs(读取日志)工具,可设计search_logs(搜索日志)工具,仅返回相关日志条目及周边上下文。 - 无需分别实现
get_customer_by_id(通过ID获取客户)、list_transactions(列出交易)和list_notes(列出备注)工具,可实现get_customer_context(获取客户上下文)工具,一次性整合客户近期所有相关信息。
确保每个工具都具备清晰、独特的用途。工具应能支持智能体像人类一样,在获取相同底层资源的情况下拆分并解决任务,同时减少原本需通过中间输出消耗的上下文。
过多工具或功能重叠的工具会分散智能体的注意力,阻碍其采用高效策略。谨慎、有选择地规划工具的构建(或不构建),能带来显著成效。
对工具进行命名空间划分
AI智能体可能会访问数十个MCP服务器和数百种不同工具(包括其他开发者提供的工具)。当工具功能重叠或用途模糊时,智能体可能会困惑于该选择哪一个。
命名空间划分(将相关工具归类到通用前缀下)有助于明确大量工具间的边界——MCP客户端有时会默认执行此操作。例如,按服务(如 asana_search、jira_search)或资源(如 asana_projects_search、asana_users_search)对工具进行命名空间划分,能帮助智能体在合适的时机选择正确的工具。
我们发现,前缀式命名空间与后缀式命名空间的选择,对工具使用评估结果具有显著影响。不同大语言模型的表现存在差异,建议根据自身评估结果选择命名方案。
智能体可能出现调用错误工具、参数错误、调用不足或工具响应处理不当等问题。通过选择性实现名称反映任务自然拆分的工具,可同时减少加载到智能体上下文的工具数量和描述信息,并将智能体的计算压力从上下文转移至工具调用本身,从而降低智能体的整体出错风险。
工具返回有意义的上下文
同理,工具实现应确保仅向智能体返回高价值信息,优先考虑上下文相关性而非灵活性,避免返回底层技术标识符(例如:uuid、256px_image_url、mime_type)。name(名称)、image_url(图片链接)、file_type(文件类型)等字段更可能直接为智能体的后续操作和响应提供参考。
智能体对自然语言名称、术语或标识符的处理能力,远优于晦涩的编码标识符。我们发现,仅需将任意字母数字组合的UUID转换为更具语义、更易理解的表述(甚至采用0索引ID方案),就能显著提升Claude在检索任务中的准确性,减少幻觉现象。
某些情况下,智能体可能需要同时处理自然语言和技术标识符输出(例如,search_user(name='jane') → send_message(id=12345))。可通过在工具中添加简单的 response_format 枚举参数实现这一需求,让智能体自主控制工具返回“简洁”或“详细”响应(见下文示例)。
还可添加更多格式以提升灵活性,类似GraphQL中可精确选择所需信息的机制。以下是控制工具响应详细程度的ResponseFormat枚举示例:
enum ResponseFormat {
DETAILED = "detailed", // 详细模式
CONCISE = "concise" // 简洁模式
}
详细工具响应示例(206个令牌):
● I'll search slack for recent bug reports and use the detailed format to see which channel IDs and threads to
investigate further.
● slack - search (MCP)(query: "bug", sort: "timestamp", sortDir: "desc", limit: 100, responseFormat:
"detailed")
↓ Search results for: "bug"
═════ Result 1 of 89 ═════
Channel: #dev (C1234567890)
From: @jane.doe (U123456789)
Time: 2024-01-15 10:30:45 UTC
TS: 1705316445.123456
Text: Found a critical bug in the login flow.
═════ Result 2 of 89 ═════
Channel: DM with @john.smith
From: @john.smith (U987654321)
Time: 2024-01-14 15:22:18 UTC
TS: 1705247738.234567
Text: The bug report for issue #123 is ready for review
Files: bug-report-123.pdf
...
简洁工具响应示例(72个令牌):
● I'll search slack for recent bug reports and use the concise format to read as many messages as possible.
● slack - search (MCP)(query: "bug", sort: "timestamp", sortDir: "desc", limit: 100, responseFormat: "concise")
↓ Search: "bug" (89 results)
1. #dev - @jane.doe: Found a critical bug in the login flow. [Jan 15]
2. DM - @john.smith: The bug report for issue #123 is ready for review [Jan 14]
...
Slack线程及回复通过唯一的 thread_ts 标识,该字段是获取线程回复的必需参数。thread_ts 及其他ID(channel_id、user_id)可从“详细”模式的工具响应中获取,以支持后续需这些参数的工具调用;“简洁”模式仅返回线程内容,不含ID信息。上述示例中,“简洁”模式的令牌消耗仅为“详细”模式的约1/3。
工具响应结构(如XML、JSON、Markdown)也会影响评估性能,不存在“万能”方案。这是因为大语言模型基于下一个令牌预测训练,对与训练数据匹配的格式表现更优。最优响应结构因任务和智能体而异,建议根据自身评估结果选择。
优化工具响应的令牌效率
优化上下文质量固然重要,控制工具响应返回给智能体的上下文数量也同样关键。
对于可能消耗大量上下文的工具响应,建议结合分页、范围选择、过滤和/或截断功能,并设置合理的默认参数值。在Claude Code中,我们默认将工具响应限制为25,000个令牌。尽管智能体的有效上下文长度未来可能会增长,但对上下文高效型工具的需求将长期存在。
若选择截断响应,需向智能体提供明确指引。例如,可直接鼓励智能体采用更高效的令牌策略,如在知识检索任务中进行多次小型定向搜索,而非单次宽泛搜索。同样,若工具调用出错(如输入验证失败),可通过提示工程优化错误响应,提供具体、可操作的改进建议,而非模糊的错误代码或追踪信息。
截断工具响应示例:
● 我会帮你查找Stripe上的所有交易记录,并为你提供汇总信息。
● stripe - transactions_search(MCP)(limit: 5000, responseFormat: "concise")
↓ ## 交易搜索结果
找到 **2,847条匹配你查询的交易记录**。
结果已截断,显示前3条:
| 日期 | 描述 | 金额 | 分类 |
|------------|---------------------|------------|----------|
| 2024-01-15 | 来自Acme Corp的付款 | +$5,200.00 | 收入 |
| 2024-01-14 | 来自TechStart的付款 | +$3,100.00 | 收入 |
| 2024-01-13 | 来自Cloud Co.的付款 | +$3,100.00 | 收入 |
**所有2,847条结果的汇总:**
- 总收入:$458,291.00
- 日期范围:2024年1月1日 - 1月15日
## 如需优化结果,你可以:
- **搜索特定商家**:使用 `transactions_search(payee: "Acme Corp")` 仅查看Acme Corp的交易
- **按金额范围筛选**:使用 `transactions_search(minAmount: 1000, maxAmount: 5000)`
- **获取下一页结果**:使用 `transactions_search(query: <查询内容>, page: 2)`
无效错误响应示例:
● 好的,我会从John的个人资料中获取他的联系信息。
● asana - user_info(MCP)(userId: "john.doe@acme.corp")
↓ {
"error": {
"code": "RESOURCE_NOT_FOUND",
"status": 422,
"message": "无效值",
"details": {
"field": "userId",
"value": "john.doe@acme.corp",
"type": "invalid_value"
}
}
}
有效错误响应示例:
● 好的,我会从John的个人资料中获取他的联系信息。
● asana - user_info(MCP)(userId: "john.doe@acme.corp")
↓ 工具响应:
# 资源未找到:`userId`无效
## 错误摘要
你对`/api/user/info`的请求失败,原因是`userId`值`john.doe@acme.corp`不存在或格式错误。
## 有效的用户ID示例
- `1928298149291729`
- `9381719375914731`
## 获取用户ID的方法
- 调用`user_search()`接口
工具截断和错误响应能引导智能体采用更高效的工具使用行为(如使用过滤或分页功能),或提供正确格式的工具输入示例。
对工具描述进行提示工程优化
这是提升工具性能最有效的方法之一:对工具描述和规格进行提示工程优化。由于这些内容会加载到智能体的上下文的,因此能系统性引导智能体形成高效的工具调用行为。
编写工具描述和规格时,可设想如何向团队新成员介绍该工具。考虑你可能隐含的上下文信息——专业查询格式、特定术语定义、底层资源间的关系——并将其明确化。通过清晰描述(并通过严格的数据模型强制执行)预期输入和输出,避免歧义。尤其需注意,输入参数的命名应明确无歧义:例如,用 user_id 替代模糊的 user 作为参数名。
借助评估,可更精准地衡量提示工程的效果。即使是对工具描述的微小优化,也可能带来显著性能提升。在对工具描述进行精准改进后,Claude Sonnet 3.5在SWE-bench Verified评估中实现了最先进性能,错误率大幅降低,任务完成度显著提升。
工具定义的其他最佳实践可参考我们的开发者指南。若为Claude构建工具,建议进一步了解工具如何动态加载到Claude的系统提示词中。此外,若为MCP服务器编写工具,工具注释需明确披露哪些工具需要开放世界访问权限或会执行破坏性操作。
展望未来
要为智能体构建高效工具,我们需要将软件开发实践从可预测的确定性模式,转向非确定性模式。
通过本文所述的迭代式、评估驱动型流程,我们发现了工具成功的共性模式:高效工具需具备明确的设计目标、合理利用智能体上下文、支持多样化工作流程组合,并能让智能体直观地解决现实世界任务。
未来,智能体与世界交互的具体机制可能会不断演进——从MCP协议的更新到底层大语言模型的升级。通过系统化、评估驱动的智能体工具改进方法,我们能确保随着智能体能力的提升,其使用的工具也能同步迭代发展。
致谢
本文由Ken Aizawa撰写,感谢以下同事提供的宝贵支持:研究团队(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)。
¹ 不包括对底层大语言模型本身的训练优化。
附录:PDF工具包说明(SKILL.md)
YAML前置信息
name: pdf
description: 综合PDF工具包,支持文本和表格提取、文档合并/拆分及表单填写功能。
概述
本指南涵盖使用Python库和命令行工具进行的核心PDF处理操作。高级功能、JavaScript库及详细示例见 ./reference.md;如需填写PDF表单,请阅读 ./forms.md 并遵循相关说明。
快速入门
from pypdf import PdfReader, PdfWriter
# 读取PDF文件
reader = PdfReader("document.pdf")
print(f"页数:{len(reader.pages)}")
# 提取文本
text = ""
for page in reader.pages:
text += page.extract_text()
PDF处理高级参考(reference.md)
本文档包含核心技能指南中未涵盖的高级PDF处理功能、详细示例及其他库。
pypdfium2库(Apache/BSD许可证)
概述
pypdfium2是PDFium(Chromium的PDF库)的Python绑定,擅长快速PDF渲染、图像生成,且可作为……
PDF表单填写指南(forms.md)
如需填写PDF表单,请先检查PDF是否包含可填写表单字段:在本文档所在目录运行脚本 python scripts/check_fillable_fields <文件.pdf>,根据结果选择“可填写字段”或“不可填写字段”对应的操作说明。
可填写字段
若PDF包含可填写表单字段,在本文档所在目录运行脚本:python scripts/extract_form_field_info.py <输入.pdf> <输出.json>。
更多推荐


所有评论(0)