跳到正文
北京时间
原文
Anthropic:Newsroom·· 2025-09-11精选AI 评分75

Anthropic 讲解如何为 Agent 编写高效工具

Writing effective tools for agents — with agents

AI 导读

Anthropic 发布方法论文章,讲解如何为 MCP 和 Agent 场景编写高效工具,核心是用 Claude Code 协作完成原型搭建、评测运行和工具自动优化。

推荐理由

Anthropic 官方沉淀的工具编写方法,给出评测驱动流程和命名、上下文、token 效率等具体原则,可迁移到自己的 MCP 工具开发。

正文 · AI 翻译

模型上下文协议(MCP)可以让 LLM 智能体拥有多达数百个工具,以解决现实世界的任务。但我们如何让这些工具发挥最大效用?

在本文中,我们介绍在各种智能体 AI 系统中提升性能的最有效技术1。

我们首先介绍如何:

  • 构建并测试你的工具原型
  • 借助智能体为你的工具创建并运行全面的评估
  • 与 Claude Code 等智能体协作,自动提升你的工具性能

最后,我们总结在此过程中发现的编写高质量工具的关键原则:

  • 选择合适的工具来实现(以及不实现)
  • 为工具划分命名空间,以界定清晰的功能边界
  • 从工具向智能体返回有意义的上下文
  • 优化工具响应以提升 token 效率
  • 对工具描述和规范进行提示工程
This is an image depicting how an engineer might use Claude Code to evaluate the efficacy of agentic tools.

构建评估可以让你系统地衡量工具的性能。你可以使用 Claude Code 针对该评估自动优化你的工具。

什么是工具?

在计算领域,确定性系统在给定相同输入时每次都会产生相同的输出,而非确定性系统——例如智能体——即使起始条件相同,也可能产生不同的响应。

当我们传统地编写软件时,我们是在确定性系统之间建立一种契约。例如,像 getWeather(“NYC”) 这样的函数调用,每次被调用时都会以完全相同的方式获取纽约市的天气。

工具是一种新型软件,它体现的是确定性系统与非确定性智能体之间的契约。当用户问“我今天该带伞吗?”,智能体可能会调用天气工具、根据常识回答,甚至先询问澄清位置。有时,智能体可能会产生幻觉,甚至无法理解如何使用某个工具。

这意味着在为智能体编写软件时,我们需要从根本上重新思考方法:我们不应像为其他开发者或系统编写函数和 API 那样来编写工具和 MCP 服务器,而需要为智能体设计它们。

我们的目标是通过使用工具来追求各种成功策略,扩大智能体能够有效解决广泛任务的范围。幸运的是,根据我们的经验,对智能体最“符合人体工程学”的工具,最终对人类来说也出乎意料地直观易懂。

如何编写工具

在本节中,我们介绍如何与智能体协作,既编写工具,也改进你提供给它们的工具。首先快速搭建工具原型并在本地测试。接下来,运行全面评估以衡量后续改动。与智能体并肩工作,你可以重复评估和改进工具的过程,直到你的智能体在现实世界任务中取得强劲表现。

构建原型

如果不亲自上手,很难预判哪些工具对 agent 来说用起来顺手、哪些不顺手。先从快速搭建一个工具原型开始。如果你用 Claude Code 来编写工具(可能是一次性完成),给 Claude 提供工具所依赖的任何软件库、API 或 SDK(可能包括 MCP SDK)的文档会很有帮助。对 LLM 友好的文档通常可以在官方文档站点的扁平 llms.txt 文件中找到(这是我们 API 的)。

将你的工具封装进 本地 MCP server 或 Desktop extension(DXT),就能在 Claude Code 或 Claude Desktop 应用中连接并测试你的工具。

要将本地 MCP server 连接到 Claude Code,请运行 claude mcp add <name> <command> [args...]。

要将本地 MCP server 或 DXT 连接到 Claude Desktop 应用,请分别前往 Settings > Developer 或 Settings > Extensions。

工具也可以直接传入 Anthropic API 调用中进行程序化测试。

亲自测试这些工具,找出任何粗糙之处。收集用户的反馈,以便对你期望工具支持的用例和提示词建立直觉。

运行评估

接下来,你需要通过运行评估来衡量 Claude 使用你的工具的效果如何。先从生成大量基于真实世界用法的评估任务开始。我们建议与 agent 协作,帮助分析结果并确定如何改进你的工具。可在我们的 工具评估 cookbook 中查看这一流程的端到端示例。

This graph measures the test set accuracy of human-written vs. Claude-optimized Slack MCP servers.

我们内部 Slack 工具的留出测试集表现

生成评估任务

借助早期原型,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)行为来提升 LLM 的有效智能。

如果你使用 Claude 运行评估,可以开启交错思考以获得类似的“开箱即用”功能。这将帮助你探查智能体为何调用或不调用某些工具,并突出工具描述和规范中需要改进的具体方面。

除了顶层准确率,我们还建议收集其他指标,例如单个工具调用和任务的总运行时间、工具调用总数、总 token 消耗量以及工具错误。跟踪工具调用有助于揭示智能体常用的工作流程,并为工具整合提供一些机会。

This graph measures the test set accuracy of human-written vs. Claude-optimized Asana MCP servers.

我们内部 Asana 工具的留出测试集表现

分析结果

智能体是你发现问题的得力伙伴,能就各种问题提供反馈,从相互矛盾的工具描述到低效的工具实现以及令人困惑的工具 schema。不过请记住,智能体在反馈和响应中省略的内容往往比包含的内容更重要。LLM 并不总是言如其意。

观察你的智能体在哪些地方卡住或困惑。通读评估智能体的推理和反馈(或 CoT)以找出粗糙之处。查看原始记录(包括工具调用和工具响应),以捕捉智能体 CoT 中未明确描述的任何行为。读懂言外之意;记住你的评估智能体不一定知道正确答案和策略。

分析你的工具调用指标。大量冗余的工具调用可能表明有必要对分页或 token 限制参数进行一些合理调整;大量因无效参数导致的工具错误可能表明工具可以使用更清晰的描述或更好的示例。当我们发布 Claude 的网络搜索工具时,我们发现 Claude 会不必要地在工具的 query 参数后附加 2025,从而偏置搜索结果并降低性能(我们通过改进工具描述将 Claude 引导到了正确方向)。

与智能体协作

你甚至可以让智能体分析你的结果并为你改进工具。只需将评估智能体的记录拼接起来,粘贴到 Claude Code 中即可。Claude 是分析记录并一次性重构大量工具的专家——例如,确保在进行新更改时工具实现和描述保持自洽。

事实上,本文中的大部分建议都来自我们使用 Claude Code 反复优化内部工具实现的过程。我们的评估建立在内部工作区之上,模拟了内部工作流的复杂性,包括真实项目、文档和消息。

我们依靠留出的测试集来确保没有对“训练”评估过拟合。这些测试集表明,我们能够获得超出“专家”工具实现所达到的额外性能提升——无论这些工具是由我们的研究人员手动编写,还是由 Claude 本身生成。

在下一节中,我们将分享从这个过程中学到的一些经验。

编写高效工具的原则

在本节中,我们将把所学提炼为编写高效工具的一些指导原则。

为智能体选择合适的工具

更多工具并不总是带来更好的结果。我们观察到的一个常见错误是,工具仅仅封装了现有软件功能或 API 端点——无论这些工具是否适合智能体。这是因为智能体相对于传统软件具有不同的“可供性”——也就是说,它们感知自己可以用这些工具采取的潜在行动的方式不同。

LLM 智能体的“上下文”有限(也就是说,它们一次能处理的信息量是有限的),而计算机内存廉价且充足。考虑在通讯录中搜索联系人的任务。传统软件程序可以高效地存储和处理联系人列表,逐个检查每个联系人,然后再继续。

然而,如果 LLM 智能体使用的工具返回所有联系人,然后必须逐个 token 地读取每一个,它就是在把有限的上下文空间浪费在无关信息上(想象一下通过从上到下阅读每一页来在通讯录中搜索联系人——也就是暴力搜索)。更好、更自然的方法(对智能体和人类都是如此)是先跳到相关页面(也许按字母顺序找到它)。

我们建议构建少量经过深思熟虑的工具,针对特定的高影响力工作流,与你的评估任务相匹配,并在此基础上扩展。在通讯录的案例中,你可以选择实现一个 search_contacts 或 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 工具,它可以一次性汇编客户所有近期且相关的信息。

确保你构建的每个工具都有清晰、独特的目的。工具应当使智能体能够以与人类大致相同的方式细分和解决任务(在获得相同底层资源的情况下),同时减少原本会被中间输出消耗的上下文。

工具过多或工具重叠也会分散智能体对高效策略的追求。对你构建(或不构建)的工具进行仔细、有选择性的规划,确实能带来回报。

为工具设置命名空间

你的 AI 智能体可能会访问数十个 MCP 服务器和数百种不同的工具——包括其他开发者提供的工具。当工具在功能上重叠或用途模糊时,智能体可能会搞不清该用哪些工具。

命名空间(将相关工具归组在共同前缀下)有助于在大量工具之间划清界限;MCP 客户端有时会默认这样做。例如,按服务为工具设置命名空间(如 asana_search、jira_search)以及按资源设置命名空间(如 asana_projects_search、asana_users_search),可以帮助智能体在合适的时机选择正确的工具。

我们发现,在基于前缀和基于后缀的命名空间之间做选择,会对我们的工具使用评估产生不小的影响。影响因 LLM 而异,我们鼓励你根据自己的评估来选择命名方案。

智能体可能会调用错误的工具、用错误的参数调用正确的工具、调用的工具过少,或错误地处理工具响应。通过有选择地实现那些名称反映任务自然划分的工具,你可以同时减少加载到智能体上下文中的工具和工具描述数量,并将智能体计算从智能体上下文转移到工具调用本身。这降低了智能体犯错的整体风险。

从工具返回有意义的上下文

同样地,工具实现应注意只向智能体返回高信号信息。它们应优先考虑上下文相关性而非灵活性,并避免使用底层技术标识符(例如: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 枚举参数来同时支持两者,让智能体控制工具返回 “concise” 还是 “detailed” 响应(见下图)。

你可以添加更多格式以获得更大的灵活性,类似于 GraphQL,你可以精确选择想要接收哪些信息。下面是一个用于控制工具响应详细程度的 ResponseFormat 枚举示例:

下面是一个详细工具响应的示例(206 个 token):

This code snippet depicts an example of a detailed tool response.

下面是一个简洁工具响应的示例(72 个 token):

This code snippet depicts a concise tool response.

Slack 线程和线程回复由唯一的 thread_ts 标识,获取线程回复需要用到它。thread_ts 和其他 ID(channel_id、user_id)可以从 “detailed” 工具响应中获取,以便支持需要这些 ID 的后续工具调用。“concise” 工具响应只返回线程内容,不包含 ID。在此示例中,我们使用 “concise” 工具响应时只用了约 ⅓ 的 token。

甚至你的工具响应结构——例如 XML、JSON 或 Markdown——也会对评估性能产生影响:不存在放之四海而皆准的解决方案。这是因为 LLM 是在下一 token 预测上训练的,往往在与其训练数据相匹配的格式上表现更好。最优的响应结构因任务和智能体而异。我们鼓励你根据自己的评估来选择最佳的响应结构。

优化工具响应的 token 效率

优化上下文质量很重要。但优化工具响应中返回给智能体的上下文数量同样重要。

我们建议对任何可能消耗大量上下文的工具响应,实施分页、范围选择、过滤和/或截断的某种组合,并设置合理的默认参数值。对于 Claude Code,我们默认将工具响应限制在 25,000 个 token。我们预计智能体的有效上下文长度会随时间增长,但对上下文高效工具的需求仍将存在。

如果你选择截断响应,务必用有用的指令引导智能体。你可以直接鼓励智能体采用更节省 token 的策略,例如在知识检索任务中进行多次小范围、有针对性的搜索,而不是一次宽泛的搜索。同样,如果工具调用引发错误(例如在输入验证期间),你可以对错误响应进行提示工程,以清晰传达具体且可操作的改进建议,而不是晦涩的错误代码或堆栈跟踪。

以下是一个截断工具响应的示例:

This image depicts an example of a truncated tool response.

以下是一个无帮助的错误响应示例:

This image depicts an example of an unhelpful tool response.

以下是一个有帮助的错误响应示例:

This image depicts an example of a helpful error response.

工具截断和错误响应可以引导智能体采用更节省 token 的工具使用行为(使用过滤器或分页),或提供正确格式化的工具输入示例。

对工具描述进行提示工程

现在我们来到改进工具最有效的方法之一:对工具描述和规范进行提示工程。由于这些内容会被加载到智能体的上下文中,它们可以共同引导智能体采取有效的工具调用行为。

在编写工具描述和规范时,想想你会如何向团队的新员工描述你的工具。考虑你可能隐含带入的上下文——特殊的查询格式、小众术语的定义、底层资源之间的关系——并将其明确化。通过清晰描述(并用严格的数据模型强制执行)预期的输入和输出,避免歧义。特别是,输入参数应无歧义地命名:与其使用名为 user 的参数,不如尝试使用名为 user_id 的参数。

通过评估,你可以更有信心地衡量提示工程的影响。即使对工具描述做微小的改进,也能带来显著的提升。在我们对工具描述做出精确改进后,Claude Sonnet 3.5 在 SWE-bench Verified 评估中取得了最先进的性能,大幅降低了错误率并提高了任务完成率。

你可以在我们的开发者指南中找到有关工具定义的其他最佳实践。如果你正在为 Claude 构建工具,我们还建议阅读有关工具如何动态加载到 Claude 的系统提示中的内容。最后,如果你正在为 MCP 服务器编写工具,工具注解有助于披露哪些工具需要开放世界访问或会做出破坏性更改。

展望未来

要为智能体构建有效的工具,我们需要将软件开发实践从可预测的确定性模式转向非确定性模式。

通过我们在本文中描述的迭代式、评估驱动的过程,我们已经识别出工具成功的一致模式:有效的工具是有意且清晰定义的,审慎地使用智能体上下文,能够在多样化的工作流中组合在一起,并使智能体能够直观地解决现实世界的任务。

未来,我们预计智能体与世界交互的具体机制将不断演进——从 MCP 协议的更新到底层 LLM 本身的升级。通过系统化、评估驱动的方法来改进智能体工具,我们可以确保随着智能体能力的提升,它们所使用的工具也将随之演进。

来源:Anthropic:Newsroom · anthropic.com