原文: English original · Anthropic 官方

构建高效的 agent

我们曾与数十个来自不同行业、致力于构建大语言模型(LLM)agent 的团队合作。实践一再表明,最成功的实现采用的是简单、可组合的模式,而不是复杂的框架。

过去一年里,我们与数十个来自不同行业、致力于构建大语言模型(LLM)agent 的团队展开了合作。实践一再表明,最成功的实现并未使用复杂的框架或专用库,而是采用简单、可组合的模式。

本文将分享我们在服务客户和亲自构建 agent 的过程中积累的经验,并为开发者提供构建高效 agent 的实用建议。

什么是 agent?

“Agent”有多种定义方式。有些客户将 agent 定义为能够长期独立运行,并使用各种工具完成复杂任务的全自主系统;另一些客户则用这个词描述约束更明确、按照预定义 workflow 执行的实现。在 Anthropic,我们将这些不同形态统称为 agentic 系统,但会从架构上明确区分 workflow 与 agent:

  • workflow 是通过预定义代码路径编排 LLM 和工具的系统。
  • agent 则是由 LLM 动态决定自身执行过程和工具使用方式,并自主掌控任务完成方法的系统。

下文将详细探讨这两类 agentic 系统。在附录 1“实践中的 agent”中,我们还会介绍两个客户认为这类系统特别有价值的应用领域。

何时使用 agent,何时不该使用

使用 LLM 构建应用时,我们建议先寻找尽可能简单的解决方案,只在确有需要时增加复杂度。这可能意味着完全不构建 agentic 系统。Agentic 系统往往以延迟和成本换取更好的任务表现,因此你应当判断这种取舍何时值得。

需要更高复杂度时,对于定义明确的任务,workflow 能提供可预测性和一致性;而当系统需要大规模实现灵活、由模型驱动的决策时,agent 是更好的选择。不过,对许多应用而言,结合检索与上下文示例来优化单次 LLM 调用,通常已经足够。

何时以及如何使用框架

目前有许多框架可以简化 agentic 系统的实现,包括:

这些框架简化了调用 LLM、定义和解析工具、串联多次调用等常见的底层任务,让开发者能够轻松上手。然而,它们往往会引入额外的抽象层,遮蔽底层 prompt 和响应,使调试更加困难。框架也容易诱使开发者增加复杂度,即使更简单的方案已经足够。

我们建议开发者从直接使用 LLM API 开始:许多模式只需几行代码即可实现。如果确实使用框架,也应确保自己理解其底层代码。对内部机制做出错误假设,是客户常见的问题来源。

一些实现示例可参阅我们的 cookbook

构建模块、workflow 与 agent

本节将介绍我们在生产环境中观察到的常见 agentic 系统模式。我们会从基础构建模块——增强型 LLM——讲起,并逐步提高复杂度,从简单的组合式 workflow 一直讲到自主 agent。

构建模块:增强型 LLM

Agentic 系统的基础构建模块,是通过检索、工具和记忆等能力增强的 LLM。当前的模型可以主动使用这些能力,包括自行生成搜索查询、选择合适的工具,以及决定保留哪些信息。

增强型 LLM

我们建议重点关注实现中的两个方面:根据具体用例定制这些能力,并确保它们为 LLM 提供易用、文档完善的接口。实现这些增强能力的方法很多,其中一种是采用我们最近发布的 Model Context Protocol。开发者只需实现一个简单的客户端,即可接入不断扩大的第三方工具生态。

在本文余下部分,我们假定每次 LLM 调用都能使用这些增强能力。

workflow:prompt 串联

Prompt 串联会把任务拆解为一系列步骤,每次 LLM 调用都处理上一次调用的输出。你可以在任何中间步骤加入程序化检查(见下图中的“gate”),以确保整个过程仍沿着正确方向推进。

Prompt 串联 workflow

何时使用这种 workflow: 当任务能够轻松、清晰地拆解为固定子任务时,这种 workflow 最为合适。其主要目标是以延迟换取更高准确率,让每次 LLM 调用面对的任务都更简单。

适合使用 prompt 串联的例子:

  • 先生成营销文案,再将其翻译成另一种语言。
  • 先编写文档大纲,检查大纲是否符合特定标准,再根据大纲撰写文档。

workflow:路由

路由会对输入进行分类,并将其导向专门的后续任务。这种 workflow 可以实现关注点分离,并构建更具针对性的 prompt。如果不使用这种 workflow,针对某类输入所做的优化可能会损害其他输入的表现。

路由 workflow

何时使用这种 workflow: 当复杂任务包含多个适合分别处理的明确类别,且 LLM 或传统分类模型或算法能够准确完成分类时,路由会很有效。

适合使用路由的例子:

  • 将不同类型的客户服务请求(一般问题、退款申请、技术支持)导向不同的下游流程、prompt 和工具。
  • 将简单或常见的问题路由给 Claude Haiku 4.5 等规模更小、成本更低的模型,将困难或少见的问题路由给 Claude Sonnet 4.5 等能力更强的模型,从而优化整体表现。

workflow:并行化

有时可以让多个 LLM 同时处理一项任务,再通过程序汇总它们的输出。这种并行化 workflow 主要有两种形式:

  • 分段: 将任务拆分为相互独立、可并行执行的子任务。
  • 投票: 多次执行同一任务,以获得多样化的输出。

并行化 workflow

何时使用这种 workflow: 如果拆分后的子任务可以并行执行以提高速度,或者需要从多个视角出发、进行多次尝试以提高结果可信度,并行化就很有效。对于涉及多项考量的复杂任务,让每次 LLM 调用分别处理一个考量因素,通常表现更好,因为模型可以集中注意力处理每个具体方面。

适合使用并行化的例子:

  • 分段:
    • 实现防护机制:一个模型实例负责处理用户查询,另一个实例负责筛查不当内容或请求。相比让同一次 LLM 调用同时承担防护和核心回答任务,这种方式通常表现更好。
    • 自动执行 LLM 性能评测,每次 LLM 调用分别评估模型对给定 prompt 的某一个表现维度。
  • 投票:
    • 审查一段代码中的漏洞,让多个不同的 prompt 分别检查代码,并在发现问题时进行标记。
    • 判断给定内容是否不当,使用多个 prompt 分别评估不同方面,或设置不同的投票阈值,在假阳性与假阴性之间取得平衡。

workflow:编排器与执行器

在编排器与执行器 workflow 中,一个中央 LLM 会动态拆解任务,将子任务委派给执行器 LLM,再汇总它们的结果。

编排器与执行器 workflow

何时使用这种 workflow: 这种 workflow 很适合无法预先判断所需子任务的复杂任务。例如在编码任务中,需要修改多少个文件,以及每个文件要做什么修改,通常都取决于具体任务。虽然这种模式在结构上与并行化相似,但关键区别在于灵活性:子任务并非预先定义,而是由编排器根据具体输入决定。

适合使用编排器与执行器的例子:

  • 每次都需要对多个文件进行复杂修改的编码产品。
  • 需要从多个来源收集并分析潜在相关信息的搜索任务。

workflow:评估器与优化器

在评估器与优化器 workflow 中,一次 LLM 调用负责生成响应,另一次调用则在循环中进行评估并给出反馈。

评估器与优化器 workflow

何时使用这种 workflow: 当我们拥有明确的评估标准,并且迭代改进能够带来可衡量的价值时,这种 workflow 尤其有效。判断它是否适用有两个信号:第一,当人类清楚表达反馈后,LLM 的响应可以得到明确改善;第二,LLM 自身也能提供这种反馈。这类似于人类作者为了写出成熟文稿而经历的反复修改过程。

适合使用评估器与优化器的例子:

  • 文学翻译:负责翻译的 LLM 起初可能未能捕捉某些细微之处,但负责评估的 LLM 可以提出有价值的批评意见。
  • 复杂搜索任务:需要经过多轮搜索和分析才能收集完整信息,由评估器判断是否有必要继续搜索。

agent

随着 LLM 在理解复杂输入、推理与规划、可靠使用工具以及错误恢复等关键能力上日趋成熟,agent 正逐步进入生产环境。Agent 的任务通常始于人类用户发出指令,或与人类用户展开交互式讨论。任务明确后,agent 会自主规划并执行,也可能在需要更多信息或判断时再次询问人类。

执行期间,agent 必须在每一步从环境中获取“真实反馈”(例如工具调用结果或代码执行结果),以评估自身进展。agent 可以在检查点或遇到阻碍时暂停,等待人类反馈。任务通常在完成后终止,但为了保持控制,也常常会设置停止条件,例如最大迭代次数。

Agent 能够处理复杂任务,但实现方式往往很直接。它们通常只是根据环境反馈,在循环中使用工具的 LLM。因此,清晰、周密地设计工具集及其文档至关重要。我们会在附录 2“为工具进行 prompt engineering”中进一步介绍工具开发的最佳实践。

自主 agent

何时使用 agent: agent 适用于开放式问题,这类问题很难或根本无法预先判断所需步骤数量,也无法硬编码一条固定路径。LLM 可能会连续运行许多轮,因此你必须在一定程度上信任它的决策能力。agent 的自主性使其非常适合在可信环境中规模化执行任务。

agent 的自主特性意味着更高的成本,也可能导致错误不断累积。我们建议在沙盒环境中进行充分测试,并配备适当的防护机制。

适合使用 agent 的例子:

以下示例来自我们自己的实现:

Coding agent 的高层执行流程

组合与定制这些模式

这些构建模块并非强制规范,而是开发者可以根据不同用例调整和组合的常见模式。与任何 LLM 功能一样,成功的关键在于衡量表现并持续迭代实现。再次强调:只有在复杂度能够显著改善结果时,才应考虑增加复杂度。

总结

在 LLM 领域,成功并不取决于能否构建最复杂的系统,而在于能否构建真正适合自身需求的系统。从简单的 prompt 开始,通过全面评测加以优化;只有在简单方案无法满足要求时,再加入多步骤 agentic 系统。

实现 agent 时,我们遵循三项核心原则:

  1. 保持 agent 设计的简洁性
  2. 优先保证透明度,明确展示 agent 的规划步骤。
  3. 通过完善的工具文档与测试,精心设计 agent-computer interface(ACI,agent 与计算机接口)。

框架可以帮助你快速起步,但随着系统走向生产环境,不妨减少抽象层,改用基础组件构建。遵循这些原则,你就能创建不仅强大,而且可靠、易维护并能赢得用户信任的 agent。

致谢

本文由 Erik S. 和 Barry Zhang 撰写。文章凝聚了我们在 Anthropic 构建 agent 的经验,也吸收了客户分享的宝贵见解,在此深表感谢。

附录 1:实践中的 agent

我们与客户的合作揭示了 AI agent 两个特别有前景的应用方向,体现了上文所述模式的实际价值。这两类应用都说明:当任务既需要对话也需要行动,同时具备明确的成功标准、支持反馈循环并纳入有意义的人类监督时,agent 能创造最大的价值。

A. 客户支持

客户支持将人们熟悉的聊天机器人界面与工具集成带来的增强能力结合起来。它非常适合更开放的 agent,原因如下:

  • 支持服务的交互天然遵循对话流程,同时需要访问外部信息并执行操作;
  • 可以集成工具来获取客户数据、订单历史和知识库文章;
  • 退款或更新工单等操作可以通过程序完成;并且
  • 可以根据用户定义的问题解决标准清晰衡量是否成功。

多家公司已经采用按使用量计费的模式证明了这种方法的可行性,即只对成功解决的问题收费,这也体现出它们对自身 agent 效果的信心。

B. coding agent

软件开发领域已经展现出 LLM 功能的巨大潜力,其能力正在从代码补全演进到自主解决问题。Agent 在这一领域尤其有效,原因如下:

  • 代码解决方案可以通过自动化测试验证;
  • agent 可以利用测试结果作为反馈,反复改进解决方案;
  • 问题空间定义明确且结构清晰;并且
  • 输出质量可以客观衡量。

在我们自己的实现中,agent 现在只需依据拉取请求描述,就能解决 SWE-bench Verified 基准中的真实 GitHub issue。不过,自动化测试虽然有助于验证功能,人类审查对于确保解决方案符合更广泛的系统要求仍然至关重要。

附录 2:为工具进行 prompt engineering

无论你构建哪种 agentic 系统,工具都很可能是 agent 的重要组成部分。工具通过在我们的 API 中指定自身的确切结构和定义,让 Claude 能够与外部服务和 API 交互。如果 Claude 打算调用工具,其响应会在 API 响应中包含一个工具使用块。工具的定义和规范,理应像整体 prompt 一样受到充分的 prompt engineering 重视。

在这篇简短的附录中,我们将介绍如何为工具进行 prompt engineering。

同一种操作通常可以用多种方式表达。例如,编辑文件时可以编写 diff,也可以重写整个文件;生成结构化输出时,可以将代码放在 Markdown 中,也可以放在 JSON 中。在软件工程中,这类差异只是表现形式不同,彼此之间可以无损转换。然而,对 LLM 来说,某些格式的编写难度远高于其他格式。

编写 diff 时,模型必须在写出新代码之前,就知道分块头中有多少行发生变化。与 Markdown 相比,在 JSON 中编写代码还需要额外转义换行符和引号。

关于如何选择工具格式,我们有以下建议:

  • 给模型足够的 token 用于“思考”,避免它在输出过程中陷入无路可走的局面。
  • 采用与模型在互联网自然文本中常见内容相近的格式。
  • 确保格式不存在额外“负担”,例如必须精确统计数千行代码,或对生成的代码进行字符串转义。

一条经验法则是:想想人们会投入多少精力设计 human-computer interface(HCI,人与计算机接口),然后计划投入同等精力打造优秀的 agent-computer interface(ACI)。以下是一些具体思路:

  • 站在模型的角度思考。仅凭描述和参数,工具的用法是否一目了然?还是必须仔细琢磨才能理解?如果你需要认真思考,模型很可能也一样。一份好的工具定义通常会包含用法示例、边界情况、输入格式要求,以及与其他工具之间的明确边界。
  • 如何修改参数名称或描述,让工具的使用方式更加清晰?可以把它当作给团队中的初级开发者编写一份优秀的 docstring。使用大量相似工具时,这一点尤其重要。
  • 测试模型如何使用工具:在我们的 workbench 中运行大量示例输入,观察模型会犯哪些错误,再据此迭代。
  • 对工具进行防错设计(Poka-yoke)。调整参数,使其更难被错误使用。

在为 SWE-bench 构建 agent 时,我们实际投入在优化工具上的时间,比优化整体 prompt 还要多。例如,我们发现,当 agent 离开根目录后,使用相对文件路径的工具会让模型出错。为解决这个问题,我们将工具改为始终要求绝对文件路径,并发现模型能够毫无差错地使用这种方式。