跳转至

构建高效的 AI 代理

  • 原文链接:https://www.anthropic.com/research/building-effective-agents [42]
  • 发布时间:2024-12-19
  • 作者:Erik Schluntz、Barry Zhang

我们与大量团队合作构建 LLM 代理,最成功的实现往往采用简单可组合模式,而非复杂框架。[42]

过去一年,我们与多个行业的团队合作构建 LLM 代理。最成功的实现并非依赖复杂框架或专用库,而是使用简单、可组合的模式。[42]

本文分享我们与客户合作、以及自己构建代理的经验,并为开发者提供可操作建议。[42]

什么是代理?

“Agent” 有不同定义。有些客户认为代理是长时间独立运行、使用多种工具完成复杂任务的自主系统;另一些则用它描述遵循预定义流程的实现。在 Anthropic,我们将这些都归类为 agentic systems,但强调 workflowsagents 的关键架构差别:[42]

  • Workflows:LLM 与工具通过预设代码路径编排。
  • Agents:LLM 动态决定过程与工具使用方式,自主控制任务完成路径。

下文将分别介绍两类系统。在附录 1(“实践中的代理”)中,我们也会展示两个客户价值显著的应用领域。[42]

何时(以及何时不)使用代理

构建 LLM 应用时,建议先找到最简单方案,只有在必要时才增加复杂度——这意味着很多时候并不需要代理系统。代理系统常以更高延迟与成本换取更好性能,你需要评估这种权衡是否合理。[42]

当复杂度确实需要时:工作流适合明确任务,具有可预测与一致性;代理适合需要灵活性与大规模模型驱动决策的场景。但对很多应用而言,优化单次 LLM 调用(检索 + in-context 示例)通常已经足够。[42]

何时以及如何使用框架

有很多框架可简化代理系统实现,例如:[42]

这些框架简化了 LLM 调用、工具定义解析、链式调用等底层工作。然而它们也可能引入抽象层,掩盖提示与响应细节,增加调试难度,并诱导过度复杂化。[42]

建议开发者先直接使用 LLM API:许多模式只需几行代码即可实现。如果使用框架,务必理解底层逻辑;对“框架在做什么”的错误假设是常见问题来源。[42]

可参考我们的 cookbook 示例。[42]

构建块、工作流与代理

本节介绍我们在生产中常见的 agentic 模式。从基础构建块“增强型 LLM”开始,逐步提升复杂度,从可组合工作流到自主代理。[42]

基础构建块:增强型 LLM

agentic 系统的基础构建块是“增强型 LLM”:在 LLM 上叠加检索、工具与记忆等能力。当前模型可主动使用这些能力——生成搜索查询、选择工具、决定保留哪些信息。[42]

图:增强型 LLM

图注:增强型 LLM。[42]

我们建议关注两点:根据你的场景定制这些能力,以及为 LLM 提供易用且有文档的接口。实现方式很多,其中一种是使用近期发布的 Model Context Protocol,通过 client 实现 接入不断增长的第三方工具生态。[42]

本文后续默认每次 LLM 调用都具备这些增强能力。[42]

工作流:提示链(Prompt chaining)

提示链把任务拆成多个步骤,每次 LLM 调用处理上一步输出。你可对中间步骤加程序化检查(见图中的 “gate”),确保流程不偏离。[42]

图:提示链工作流

图注:提示链工作流。[42]

适用场景: 任务能清晰拆分为固定子任务。核心是用更高延迟换取更高准确性,让每次 LLM 调用更简单。[42]

示例:[42]

  • 先生成营销文案,再翻译成另一种语言。
  • 先写文档大纲,检查是否满足要求,再基于大纲写完整文档。

工作流:路由(Routing)

路由通过分类将输入分发到不同的专门流程,实现职责分离与更专业的提示。若没有路由,针对某类输入的优化可能伤害其他输入效果。[42]

图:路由工作流

图注:路由工作流。[42]

适用场景: 任务存在明显类别,且分类能准确完成(由 LLM 或传统分类器)。[42]

示例:[42]

  • 将客服请求(一般问题、退款、技术支持)分发到不同流程、提示与工具。
  • 将简单/常见问题路由到更小、更便宜模型(如 Claude Haiku 4.5),将复杂问题路由到更强模型(如 Claude Sonnet 4.5)。

工作流:并行化(Parallelization)

LLM 可以同时处理任务并汇总输出。并行化主要有两种形式:[42]

  • 分段(Sectioning):把任务拆成独立子任务并行处理。
  • 投票(Voting):对同一任务多次运行以获取不同视角。

图:并行化工作流

图注:并行化工作流。[42]

适用场景: 子任务可并行以提升速度,或需要多角度/多次尝试以提高可信度。复杂任务常在每个维度由独立调用处理时效果更好。[42]

示例:[42]

  • 分段
  • 一个模型处理用户请求,另一个负责安全审核,往往优于同一次调用兼顾两者。
  • 自动化评测中,不同调用分别评估不同维度。
  • 投票
  • 代码安全审查,多个提示共同检查漏洞。
  • 内容合规审查,多提示覆盖不同维度、不同阈值。

工作流:编排者-执行者(Orchestrator-workers)

编排者-执行者模式中,中央 LLM 动态拆解任务,分派给执行 LLM,并综合结果。[42]

图:编排者-执行者工作流

图注:编排者-执行者工作流。[42]

适用场景: 复杂任务,无法预先确定子任务(例如代码修改涉及文件数量与改动方式往往取决于任务)。它与并行化相似,但关键差别是子任务不是预先定义,而由编排者基于输入动态决定。[42]

示例:[42]

  • 多文件复杂改动的编码任务。
  • 多来源信息收集与分析的搜索任务。

工作流:评估-优化(Evaluator-optimizer)

评估-优化模式中,一个 LLM 生成结果,另一个负责评估与反馈,形成迭代循环。[42]

图:评估-优化工作流

图注:评估-优化工作流。[42]

适用场景: 有清晰评估标准,且迭代可带来可衡量收益。两大信号是:人类反馈能显著改进 LLM 输出,且 LLM 能提供类似反馈。类似于人类写作的多轮打磨。[42]

示例:[42]

  • 文学翻译:初稿可能漏掉细微语义,评估模型可给出批评。
  • 复杂搜索:需要多轮搜索与分析,评估模型决定是否继续搜索。

代理(Agents)

随着 LLM 在理解复杂输入、推理规划、可靠工具使用与错误恢复上变强,代理开始进入生产。代理从用户指令或对话开始,在明确任务后进行自主计划与执行;过程中会根据环境“真实信号”(工具结果、代码执行)校验进度,并在关键点或受阻时向人类请求反馈。任务完成即结束,也常加入停止条件(如最大迭代次数)以保持控制。[42]

代理可以处理复杂任务,但实现通常并不复杂:本质是 LLM 在环境反馈下使用工具的循环。因此必须谨慎设计工具与文档。附录 2 将进一步讨论工具提示工程。[42]

图:自主代理

图注:自主代理。[42]

适用场景: 开放式问题、无法预估步骤、无法硬编码路径。LLM 需要多轮自主决策,因此必须具备一定信任。代理适合在可信环境中规模化任务。[42]

代理的自主性意味着更高成本与误差叠加风险。建议在沙箱环境中充分测试,并配合合适护栏。[42]

示例:[42]

图:编码代理的高层流程

图注:编码代理的高层流程。[42]

组合与定制这些模式

这些构建块不是规范,而是常见模式,可自由组合以适配场景。成功关键是测量性能并迭代实现。再次强调:只有在显著提升结果时才引入复杂度。[42]

总结

LLM 成功不在于构建最复杂系统,而是构建最适合需求的系统。先从简单提示开始,用全面评测优化,再在简单方案不足时引入多步代理系统。[42]

我们在实现代理时遵循三条原则:[42]

  1. 保持设计 简洁
  2. 强调 透明,显式展示代理规划步骤。
  3. 通过充分 文档与测试,精心设计 agent-computer interface(ACI)。

框架能帮助快速启动,但进入生产后不要害怕降低抽象、使用基础组件。遵循这些原则,你可以构建既强大又可靠、可维护且值得信任的代理。[42]

致谢

本文由 Erik Schluntz 与 Barry Zhang 撰写。我们感谢客户分享的洞见,也感谢在 Anthropic 构建代理的实践经验。[42]

附录 1:实践中的代理

客户实践中有两个尤为有价值的应用领域,体现了上述模式的现实价值。这些应用共同特征是:既需要对话也需要行动,有明确成功标准,支持反馈回路,并能引入有意义的人类监督。[42]

A. 客服支持

客服将熟悉的聊天界面与工具集成结合,天然适合开放式代理:[42]

  • 交互以对话为主,但需要外部信息与操作;
  • 可接入客户数据、订单历史与知识库;
  • 退款、工单更新可程序化完成;
  • 成功可通过用户定义的解决标准衡量。

一些公司采用按成功解决收费的模式,体现对代理有效性的信心。[42]

B. 编码代理

软件开发领域潜力巨大,能力从补全代码进化到自主解决问题。代理之所以有效,是因为:[42]

  • 代码可通过自动化测试验证;
  • 代理可用测试反馈迭代;
  • 问题空间结构化明确;
  • 输出质量可客观衡量。

在我们的实现中,代理已能仅凭 PR 描述解决 SWE-bench Verified 的真实 GitHub issue。但尽管自动化测试可验证功能,人类评审仍不可或缺,以确保方案符合系统整体需求。[42]

附录 2:工具提示工程

无论构建哪类系统,工具都是关键。 Tools 让 Claude 按 API 指定结构与定义与外部服务交互。Claude 响应时如果计划调用工具,会在 API 返回中包含 tool use block。工具定义同样需要提示工程。以下为简要建议:[42]

同一动作可有多种规格方式,例如:编辑文件可以写 diff 或重写全文件;结构化输出可用 Markdown 或 JSON。在传统软件中这只是格式差异,可无损转换,但对 LLM 而言写 diff 更难(需要提前知道 chunk header 行数),JSON 需额外转义换行与引号。[42]

选择工具格式的建议:[42]

  • 给模型足够 token 在输出前思考,避免“写到死角”。
  • 格式尽量接近模型在互联网中常见的文本形式。
  • 避免高“格式负担”,例如需要精确计数数千行或对代码做大量转义。

一个经验法则:像重视人机界面(HCI)一样投入打造良好的 agent-computer interface(ACI)。[42]

  • 把自己放在模型位置:仅看描述与参数,是否容易理解?若人类都要想一想,模型也会困惑。好的工具定义应包含示例用法、边界情况、输入格式要求、与其他工具的清晰边界。
  • 调整参数名与描述让其更直观,把它当作给新人写的 docstring。尤其当工具相似时尤为重要。
  • 测试模型如何使用工具:在 workbench 跑大量示例,观察错误并迭代。
  • 对工具做 Poka-yoke(防错设计),让错误更难发生。

在构建 SWE-bench 代理时,我们花在工具优化上的时间甚至超过总体提示。例如发现模型在 agent 离开根目录后使用相对路径会出错,于是改为强制绝对路径,模型随后几乎不再犯错。[42]