Founder Park 2025-09-12 18:03 北京
Anthropic 官方指南:如何为 AI 智能体构建高效工具?
- 核心是为不确定的、会推理的 AI 设计直观易用的工具,而不是像传统编程那样只考虑输入输出。
- 工具好不好,要靠系统性的评估来验证。评估场景必须接近真实世界,足够复杂,才能发现真正的问题。
- 与其提供一堆零散的 API 功能,不如创建一个能处理多步骤任务的强大工具,这能极大减轻 AI 的推理负担。
- 工具的名称、描述和参数定义是 AI 理解其用途的唯一途径。清晰、准确的描述是提升工具调用成功率最有效的方法之一。
超 13000 人的「AI 产品市集」社群!不错过每一款有价值的 AI 应用。
邀请从业者、开发人员和创业者,飞书扫码加群:
进群后,你有机会得到:
最新、最值得关注的 AI 新品资讯;
不定期赠送热门新品的邀请码、会员码;
最精准的AI产品曝光渠道
智能体的效能取决于我们为其提供的工具。我们将分享如何编写高质量的工具和评估,以及您如何可以利用 Claude 来为自己优化工具,从而提升性能。模型上下文协议 (MCP) 可以为大语言模型 (LLM) 智能体提供数百种工具,以解决现实世界的任务。但我们如何使这些工具的效能最大化呢?在这篇文章中,我们描述了在多种智能 AI 系统中提升性能最有效的技术。我们首先会介绍您如何能够:
- 构建并测试您的工具原型创建并运行针对智能体工具的全面评估与像 Claude Code 这样的智能体协作,自动提升您工具的性能
- 选择合适的工具进行实现(以及不实现)通过命名空间为工具定义清晰的功能边界从工具向智能体返回有意义的上下文为提升 Token 效率而优化工具响应对工具描述和规范进行提示工程
01
什么是工具?
在计算领域,确定性系统在给定相同输入时每次都会产生相同的输出,而非确定性系统——例如智能体——即使在起始条件相同的情况下也可能生成不同的响应。当我们传统地编写软件时,我们是在确定性系统之间建立一种契约。例如,一个像getWeather(“NYC”) 这样的函数调用,每次被调用时都会以完全相同的方式获取纽约市的天气。工具是一种新型软件,它反映了确定性系统与非确定性智能体之间的契约。当用户问“我今天应该带伞吗?”,智能体可能会调用天气工具,根据常识回答,甚至可能先问一个关于地点的澄清问题。偶尔,智能体可能会产生幻觉,甚至无法理解如何使用某个工具。这意味着在为智能体编写软件时,我们需要从根本上重新思考我们的方法:我们不应像为其他开发者或系统编写函数和 API 那样编写工具和 MCP 服务器,而需要为智能体量身设计它们。我们的目标是通过使用工具来追求多种成功的策略,从而扩大智能体在解决广泛任务方面的有效范围。幸运的是,根据我们的经验,对智能体来说最“顺手”的工具,最终对人类而言也出人意料地直观易懂。02
如何编写工具
在本节中,我们描述了您如何可以与智能体协作,既编写工具又改进您提供给它们的工具。首先,快速搭建一个工具原型并在本地进行测试。接下来,运行一次全面的评估以衡量后续的变更。与智能体并肩工作,您可以重复评估和改进工具的过程,直到您的智能体在真实世界任务中取得优异的性能。构建原型如果不亲自动手,很难预料哪些工具智能体会觉得顺手,哪些不会。首先,快速搭建一个工具原型。如果您正在使用 Claude Code 来编写工具(可能是一次性完成),为 Claude 提供您的工具将依赖的任何软件库、API 或 SDK(可能包括 MCP SDK)的文档会很有帮助。大语言模型友好的文档通常可以在官方文档网站的纯文本llms.txt 文件中找到(这是我们的 API 的文档)。将您的工具包装在本地 MCP 服务器或桌面扩展 (DXT) 中,将允许您在 Claude Code 或 Claude 桌面应用中连接并测试您的工具。- 要将您的本地 MCP 服务器连接到 Claude Code,运行
claude mcp add <name> <command> [args...]。要将您的本地 MCP 服务器或 DXT 连接到 Claude 桌面应用,请分别导航至设置 > 开发者或设置 > 扩展。- 安排下周与 Jane 开会,讨论我们最新的 Acme Corp 项目。附上我们上次项目规划会议的纪要,并预订一间会议室。客户 ID 9182 报告称,他们的一次购买尝试被收费三次。找到所有相关的日志条目,并确定是否有其他客户受到同一问题的影响。客户 Sarah Chen 刚刚提交了取消请求。准备一份挽留方案。确定:(1) 他们离开的原因,(2) 哪种挽留方案最具吸引力,以及 (3) 在提出方案前我们应注意的任何风险因素。
- 安排下周与 jane@acme.corp 开会。在支付日志中搜索
purchase_complete 和 customer_id=9182。通过客户 ID 45892 查找取消请求。2025 附加到工具的 query 参数上,这会使搜索结果产生偏差并降低性能(我们通过改进工具描述将 Claude 引导到了正确的方向)。与智能体协作您甚至可以让智能体为您分析结果并改进您的工具。只需将您评估智能体的交互记录连接起来,然后粘贴到 Claude Code 中。Claude 是分析交互记录和一次性重构大量工具的专家——例如,确保在进行新更改时,工具的实现和描述保持自洽。事实上,本文中的大部分建议都来自于与 Claude Code 反复优化我们内部工具实现的过程。我们的评估是在我们内部工作空间之上创建的,反映了我们内部工作流程的复杂性,包括真实的项目、文档和消息。我们依靠留出测试集来确保我们不会对我们的“训练”评估过拟合。这些测试集显示,即使是相比于“专家”实现的工具——无论是我们的研究人员手动编写的还是由 Claude 自己生成的——我们也能获得额外的性能提升。在下一节中,我们将分享我们从这个过程中学到的一些经验。03
编写高效工具的原则
在本节中,我们将我们的学习经验提炼为几个编写高效工具的指导原则。为智能体选择合适的工具更多的工具并不总能带来更好的结果。我们观察到的一个常见错误是,有些工具仅仅是对现有软件功能或 API 端点的简单封装——无论这些工具是否适合智能体。这是因为智能体相对于传统软件有其独特的“可供性”——也就是说,它们感知可以利用这些工具采取的潜在行动的方式是不同的。大语言模型智能体的“上下文”是有限的(即它们一次能处理的信息量有限),而计算机内存则廉价且丰富。考虑在一个地址簿中搜索联系人的任务。传统软件程序可以高效地存储和逐一处理联系人列表,检查完一个再移至下一个。然而,如果一个大语言模型智能体使用一个返回所有联系人的工具,然后必须逐个 Token 地阅读每个联系人,它就在不相关的信息上浪费了其有限的上下文空间(想象一下通过从头到尾阅读每一页来在地址簿中查找联系人——即通过暴力搜索)。更好、更自然的方法(对智能体和人类都适用)是首先跳到相关的页面(也许是按字母顺序查找)。我们建议构建少数几个精心设计的工具,针对特定的高影响力工作流程,这些工作流程与您的评估任务相匹配,并以此为基础进行扩展。在地址簿的例子中,您可能会选择实现一个Contactss 或 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 工具,该工具一次性汇编客户所有近期和相关的信息。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 个 Token):thread_ts 标识,这是获取话题回复所必需的。thread_ts 和其他 ID(channel_id, user_id)可以从“详细”的工具响应中获取,以启用需要这些 ID 的进一步工具调用。“简洁”的工具响应只返回话题内容,不包括 ID。在这个例子中,使用“简洁”的工具响应,我们大约使用了 ⅓ 的 Token。甚至您的工具响应结构——例如 XML、JSON 或 Markdown——也会对评估性能产生影响:没有一种万能的解决方案。这是因为大语言模型是基于下一个 Token 预测进行训练的,它们往往在处理与其训练数据格式相匹配的格式时表现更好。最佳的响应结构会因任务和智能体的不同而大相径庭。我们鼓励您根据自己的评估选择最佳的响应结构。为提升 Token 效率优化工具响应优化上下文的质量很重要。但优化工具响应中返回给智能体的上下文数量也同样重要。我们建议对任何可能占用大量上下文的工具响应,实施分页、范围选择、过滤和/或截断的某种组合,并设置合理的默认参数值。对于 Claude Code,我们默认将工具响应限制在 25,000 个 Token。我们预计智能体的有效上下文长度会随着时间增长,但对上下文高效工具的需求将持续存在。如果您选择截断响应,请务必用有帮助的指令来引导智能体。您可以直接鼓励智能体采取更节省 Token 的策略,比如在一个知识检索任务中进行多次小范围、有针对性的搜索,而不是一次宽泛的搜索。同样,如果一个工具调用引发错误(例如,在输入验证期间),您可以通过提示工程设计您的错误响应,以清晰地传达具体且可操作的改进建议,而不是模糊的错误代码或回溯信息。这是一个截断工具响应的例子:user 的参数,而是尝试用一个名为 user_id 的参数。通过您的评估,您可以更有信心地衡量提示工程的影响。即使是对工具描述的微小改进也能带来显著的性能提升。在我们对工具描述进行精确改进后,Claude Sonnet 3.5 在 SWE-bench Verified 评估中取得了最先进的性能,大幅降低了错误率并提高了任务完成率。您可以在我们的开发者指南中找到其他关于工具定义的最佳实践。如果您正在为 Claude 构建工具,我们还建议您阅读有关工具是如何被动态加载到 Claude 的系统提示中的内容。最后,如果您正在为 MCP 服务器编写工具,工具注解有助于揭示哪些工具需要访问开放世界或会进行破坏性更改。