WithAI.Design

5分钟阅读

Anthropic AI:与 Agent 共创:为 Agent 打造高效工具

Anthropic AI:与 Agent 共创:为 Agent 打造高效工具

用智能体打造高效工具:与AI协作编写工具的完整指南

让AI成为你的开发伙伴,打造真正智能的工具生态

模型上下文协议(MCP)能够为大语言模型智能体提供数百种工具,以解决现实世界中的任务。但我们如何让这些工具发挥最大效能?本文将分享我们在各种AI智能体系统中提升性能的最有效技术。

通过建立评估体系,你可以系统化地衡量工具性能。使用Claude Code可以基于这些评估自动优化你的工具。

什么是工具?

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

传统软件开发是在确定性系统之间建立契约。例如,像 getWeather("NYC") 这样的函数调用,每次被调用时都会以完全相同的方式获取纽约市的天气信息。

工具是一种新型软件,它反映了确定性系统与非确定性智能体之间的契约。当用户询问”今天我需要带伞吗?“时,智能体可能会调用天气工具、根据常识回答,甚至首先提出关于位置的澄清问题。偶尔,智能体可能会出现幻觉,甚至无法掌握如何使用工具。

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

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

如何编写工具

在本节中,我们将描述如何与智能体协作来编写和改进你提供给它们的工具。

首先快速建立工具原型并在本地进行测试。接下来,运行全面的评估来衡量后续更改。与智能体协同工作,你可以重复评估和改进工具的过程,直到你的智能体在现实任务中表现出色。

构建原型

如果不亲自动手,很难预测智能体会觉得哪些工具符合人体工程学,哪些不会。首先快速建立你的工具原型。

如果你使用 Claude Code 来编写工具(可能一次性完成),为Claude提供工具所依赖的任何软件库、API或SDK(包括可能的 MCP SDK)的文档会很有帮助。

LLM友好的文档通常可以在官方文档站点的扁平 llms.txt 文件中找到(这是我们的 API文档)。

将你的工具包装在本地MCP服务器桌面扩展(DXT)中,将允许你在Claude Code或Claude桌面应用中连接和测试你的工具。

要将本地MCP服务器连接到Claude Code,运行 claude mcp add <名称> <命令> [参数...]。要将本地MCP服务器或DXT连接到Claude桌面应用,分别导航到 设置 > 开发者设置 > 扩展

工具也可以直接传递到 Anthropic API 调用中进行编程测试。

自己测试工具以识别任何粗糙边缘。收集用户反馈,围绕你期望工具支持的用例和提示建立直觉。

运行评估

接下来,你需要通过运行评估来衡量Claude使用你的工具的效果。首先基于真实世界用途生成大量评估任务。我们建议与智能体协作帮助分析结果并确定如何改进工具。

在我们的工具评估指南中查看这个端到端的过程。

我们内部Slack工具的保留测试集性能

生成评估任务

使用你的早期原型,Claude Code可以快速探索你的工具并创建数十个提示和响应对。提示应该受到真实世界用途的启发,并基于真实的数据源和服务(例如,内部知识库和微服务)。

我们建议避免使用过于简单或肤浅的”沙盒”环境,这些环境无法用足够的复杂性来压力测试你的工具。

强大的评估任务可能需要多个工具调用——可能达到数十个。以下是一些强大任务的示例:

  • 安排下周与Jane开会讨论我们最新的Acme Corp项目。附上我们上次项目规划会议的笔记并预订会议室。
  • 客户ID 9182报告称他们在一次购买尝试中被收取了三次费用。查找所有相关的日志条目,并确定是否有其他客户受到相同问题的影响。
  • 客户Sarah Chen刚刚提交了取消请求。准备保留优惠。确定:(1)他们离开的原因,(2)什么保留优惠最有吸引力,以及(3)在提供优惠前我们应该注意的任何风险因素。

以下是一些较弱任务的示例:

  • 安排下周与 [email protected] 的会议。
  • 在支付日志中搜索 purchase_completecustomer_id=9182
  • 查找客户ID 45892的取消请求。

每个评估提示都应该与可验证的响应或结果配对。你的验证器可以简单到对真实响应和采样响应进行精确字符串比较,也可以复杂到 enlist Claude来判断响应。

避免过于严格的验证器,这些验证器会因格式、标点符号或有效的替代表述等虚假差异而拒绝正确的响应。

对于每个提示-响应对,你还可以选择指定你期望智能体在解决任务时调用的工具,以衡量智能体在评估期间是否成功掌握每个工具的用途。但是,因为可能有多个有效路径来正确解决任务,尽量避免过度指定或过度拟合策略。

运行评估

我们建议通过直接的LLM API调用以编程方式运行评估。使用简单的智能体循环(包装交替的LLM API和工具调用的 while 循环):每个评估任务一个循环。

每个评估智能体应该被赋予单个任务提示和你的工具。在评估智能体的系统提示中,我们建议指导智能体不仅输出结构化响应块(用于验证),还要输出推理和反馈块。

指导智能体在工具调用和响应块之前输出这些内容,可能通过触发思维链(CoT)行为来提高LLM的有效智能。

如果你使用Claude运行评估,可以开启交错思维以获得类似的”开箱即用”功能。

这将帮助你探究智能体为什么调用或不调用某些工具,并突出显示工具描述和规范中需要改进的具体领域。

除了顶级的准确性,我们还建议收集其他指标,如单个工具调用和任务的总运行时间、工具调用的总数、总令牌消耗以及工具错误。

跟踪工具调用可以帮助揭示智能体追求的常见工作流程,并为工具整合提供一些机会。

我们内部Asana工具的保留测试集性能

分析结果

智能体是你发现问题和提供反馈的有用伙伴,从矛盾的工具描述到低效的工具实现和令人困惑的工具模式。但是,请记住,智能体在反馈和响应中省略的内容通常比包含的内容更重要。

LLM并不总是言如其意。观察你的智能体在哪里受阻或困惑。通读评估智能体的推理和反馈(或CoT)以识别粗糙边缘。

审查原始记录(包括工具调用和工具响应)以捕捉智能体CoT中未明确描述的任何行为。读懂字里行间的含义;记住你的评估智能体不一定知道正确的答案和策略。

分析你的工具调用指标。大量冗余的工具调用可能表明需要适当调整分页或令牌限制参数;大量无效参数的工具错误可能表明工具可以使用更清晰的描述或更好的示例。

当我们推出Claude的网络搜索工具时,我们发现Claude不必要地将 2025 附加到工具的 query 参数中,使搜索结果产生偏差并降低性能(我们通过改进工具描述将Claude引导到正确的方向)。

与智能体协作

你甚至可以让智能体分析你的结果并为你改进工具。只需将评估智能体的记录连接起来并粘贴到Claude Code中。

Claude是分析记录和一次性重构大量工具的专家——例如,确保在做出新更改时工具实现和描述保持自一致。

事实上,本文中的大部分建议都来自使用Claude Code反复优化我们的内部工具实现。

我们的评估是建立在我们内部工作空间之上的,反映了我们内部工作流程的复杂性,包括真实项目、文档和消息。我们依赖保留测试集来确保我们没有过度拟合我们的”训练”评估。

这些测试集显示,即使超出了”专家”工具实现所实现的性能,我们还可以提取额外的性能改进——无论这些工具是由我们的研究人员手动编写还是由Claude本身生成。

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

编写高效工具的原则

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

为智能体选择合适的工具

更多的工具并不总是带来更好的结果。我们观察到一个常见错误是工具仅仅包装现有的软件功能或API端点——无论这些工具是否适合智能体。

这是因为智能体与传统软件具有不同的”可供性”——也就是说,它们有不同的方式来感知可以使用这些工具采取的潜在行动。

LLM智能体的”上下文”有限(即它们一次可以处理的信息量有限),而计算机内存便宜且丰富。考虑在地址簿中搜索联系人的任务。

传统软件程序可以高效地存储和处理联系人列表,一次检查一个,然后再继续。然而,如果LLM智能体使用返回所有联系人的工具,然后必须逐个令牌地阅读每个联系人,它就在无关信息上浪费了有限的上下文空间(想象一下通过从上到下阅读每一页来在地址簿中搜索联系人——即通过暴力搜索)。

更好更自然的方法(对智能体和人类 alike)是首先跳到相关页面(也许按字母顺序找到它)。我们建议构建一些针对特定高影响力工作流程的周到工具,这些工具与你的评估任务匹配,并从此扩展。

在地址簿案例中,你可以选择实现 search_contactsmessage_contact 工具,而不是 list_contacts 工具。

工具可以整合功能,在底层处理潜在的多个离散操作(或API调用)。例如,工具可以使用相关元数据丰富工具响应,或在单个工具调用中处理经常链接的多步任务。

以下是一些示例:

  • 不要实现 list_userslist_eventscreate_event 工具,考虑实现一个 schedule_event 工具,它可以找到可用性并安排事件。
  • 不要实现 read_logs 工具,考虑实现一个 search_logs 工具,它只返回相关的日志行和一些周围上下文。
  • 不要实现 get_customer_by_idlist_transactionslist_notes 工具,实现一个 get_customer_context 工具,它可以一次性编译客户的所有最近和相关信息。

确保你构建的每个工具都有清晰、独特的目的。工具应该使智能体能够以与人类相同的方式细分和解决任务,同时减少原本会被中间输出消耗的上下文。

太多工具或重叠的工具也会分散智能体追求高效策略的注意力。仔细、有选择地规划你构建(或不构建)的工具可以真正获得回报。

为工具命名空间

你的AI智能体可能会获得对数十个MCP服务器和数百种不同工具的访问权限——包括其他开发人员的工具。当工具功能重叠或目的模糊时,智能体可能会困惑该使用哪些工具。

命名空间(在公共前缀下分组相关工具)可以帮助划分大量工具之间的边界;MCP客户端有时默认这样做。

例如,按服务(例如 asana_searchjira_search)和按资源(例如 asana_projects_searchasana_users_search)为工具命名空间,可以帮助智能体在正确的时间选择正确的工具。

我们发现选择基于前缀和后缀的命名空间对我们的工具使用评估有重要影响。效果因LLM而异,我们鼓励你根据自己的评估选择命名方案。

智能体可能会调用错误的工具,用错误的参数调用正确的工具,调用太少的工具,或者错误地处理工具响应。通过有选择地实现名称反映任务自然细分的工具,你可以同时减少加载到智能体上下文中的工具和工具描述的数量,并将智能体计算从智能体的上下文卸载回工具调用本身。

这降低了智能体犯错的总体风险。

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

同样,工具实现应注意只向智能体返回高信号信息。它们应该优先考虑上下文相关性而不是灵活性,并避免低级技术标识符(例如:uuid256px_image_urlmime_type)。

nameimage_urlfile_type 这样的字段更有可能直接告知智能体的下游行动和响应。

智能体也往往比处理隐晦的标识符更成功地处理自然语言名称、术语或标识符。我们发现,仅仅将任意的字母数字UUID解析为更具语义意义和可解释性的语言(甚至是从0开始的ID方案),就能通过减少幻觉显著提高Claude在检索任务中的精确度。

在某些情况下,智能体可能需要灵活性来同时与自然语言和技术标识符输出交互,如果只是为了触发下游工具调用(例如,search_user(name='jane')send_message(id=12345))。

你可以通过在工具中公开一个简单的 response_format 枚举参数来实现这两点,允许你的智能体控制工具返回 "concise"(简洁)还是 "detailed"(详细)响应(下图)。

你可以添加更多格式以获得更大的灵活性,类似于GraphQL,你可以选择想要接收的确切信息片段。

这是一个控制工具响应详细程度的ResponseFormat枚举示例:

ResponseFormat {
    DETAILED = "detailed",
    CONCISE = "concise"
}

这是一个详细工具响应的示例(206个令牌):

这是一个简洁工具响应的示例(72个令牌):

Slack线程和线程回复由唯一的 thread_ts 标识,这些是获取线程回复所必需的。thread_ts 和其他ID(channel_iduser_id)可以从 "detailed" 工具响应中检索,以启用需要这些ID的进一步工具调用。"concise" 工具响应只返回线程内容并排除ID。

在这个例子中,我们使用 "concise" 工具响应节省了约⅓的令牌。

甚至你的工具响应结构——例如XML、JSON或Markdown——都会对评估性能产生影响:没有一刀切的解决方案。这是因为LLM是在下一个令牌预测上训练的,并且往往在与其训练数据匹配的格式上表现更好。

最优响应结构因任务和智能体而异。我们鼓励你根据自己的评估选择最佳响应结构。

为令牌效率优化工具响应

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

我们建议为任何可能消耗大量上下文的工具响应实现分页、范围选择、过滤和/或截断的某种组合,并提供合理的默认参数值。

对于Claude Code,我们默认将工具响应限制为25,000个令牌。我们期望智能体的有效上下文长度会随着时间的推移而增长,但对上下文高效工具的需求仍然存在。

如果你选择截断响应,请确保用有用的指导来引导智能体。你可以直接鼓励智能体追求更令牌高效的策略,例如进行许多小而有针对性的搜索,而不是对知识检索任务进行单一、广泛的搜索。

同样,如果工具调用引发错误(例如,在输入验证期间),你可以提示设计你的错误响应,以清晰传达具体和可操作的改进,而不是不透明的错误代码或回溯。

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

这是一个无用的错误响应示例:

这是一个有用的错误响应示例:

工具截断和错误响应可以引导智能体走向更令牌高效的工具使用行为(使用过滤器或分页),或者给出正确格式化工具输入的示例。

提示设计你的工具描述

我们现在来到改进工具的最有效方法之一:提示设计你的工具描述和规范。因为这些被加载到你的智能体上下文中,它们可以共同引导智能体走向有效的工具调用行为。

在编写工具描述和规范时,想想你会如何向团队中的新成员描述你的工具。考虑你可能隐式带来的上下文——专业化的查询格式、利基术语的定义、底层资源之间的关系——并将其明确化。

通过清晰描述(并用严格的数据模型强制执行)预期的输入和输出来避免歧义。特别是,输入参数应该明确命名:不要使用名为 user 的参数,尝试使用名为 user_id 的参数。

通过你的评估,你可以更自信地衡量提示设计的影响。即使对工具描述的小改进也能产生显著的改善。

在我们对工具描述进行精确改进后,Claude Sonnet 3.5在 SWE-bench Verified 评估中实现了最先进的性能,显著降低了错误率并提高了任务完成度。

你可以在我们的开发指南中找到工具定义的其他最佳实践。

如果你正在为Claude构建工具,我们还建议阅读关于工具如何动态加载到Claude的系统提示中的内容。

最后,如果你正在为MCP服务器编写工具,工具注解有助于披露哪些工具需要开放世界访问或进行破坏性更改。

展望未来

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

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

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

致谢

由Ken Aizawa撰写,得到了来自研究(Barry Zhang, Zachary Witten, Daniel Jiang, Sami Al-Sheikh, Matt Bell, Maggie Vo)、MCP(Theo Chu, John Welsh, David Soria Parra, Adam Jones)、产品工程(Santiago Seira)、市场营销(Molly Vorwerck)、设计(Drew Roper)和应用AI(Christian Ryan, Alexander Bricken)同事的宝贵贡献。

¹除了训练底层LLM本身。

想要了解更多?

通过Anthropic Academy的课程掌握API开发、模型上下文协议和Claude Code。完成课程后获得证书。探索课程


微信扫一扫关注公众号,获取更多AI开发干货与最新资讯!

想获取更多 AI 辅助设计和设计灵感趋势? 欢迎关注我的公众号(设计小站):sjxz00。 *原文:https://www. anthropic. com/engineering/writing-tools-for-agents

标签