AI 智能体编排最佳实践:处理故障、审批与重试
本指南介绍 AI 智能体编排的工作原理,比较集中式、去中心化和分层式架构,并介绍在生产环境中处理故障、审批和重试的七项最佳实践。

让多个智能体同时处理同一个项目,听起来效率极高:一个负责规划工作,另一个负责设计,第三个编写代码。它能一直顺利运作,直到出问题为止。而且,失败发生的频率往往比你预想的更高。
要防止这些失败,需要精心设计工作流。下面我们就来剖析是什么让编排后的工作流变得不可靠,并探讨确保生产环境可靠性的编排最佳实践。
什么是 AI 智能体编排?
AI 智能体编排是指协调多个 AI 智能体、模型和工具来完成多步骤任务。但仍然需要某个人(或某个东西)来决定哪个智能体先运行、它接收哪些信息,以及它完成后接下来会发生什么。这就是编排器的职责——它可以是充当管理者的 AI 智能体,也可以是由软件控制的执行层。
简单来说,编排层会将目标拆解为更小的任务,跟踪依赖关系,将执行工作委派给合适的智能体,管理共享上下文,并整合各项输出。
AI 智能体编排的工作原理:深入执行引擎
我们来看看在你向编排器分配任务后会发生什么。
来看 Perplexity 的 Computer 研讨会中的一个示例:利用来自 Salesforce、Snowflake、电子邮件、日历和近期新闻的信息,构建一个客户情报仪表板。
- 理解目标并规划工作。编排器从所需的结果出发,将其分解为具有明确依赖关系的任务。在我们的仪表板示例中,这包括从不同来源收集信息,并将其转化为最终交付成果。规划器会确定哪些步骤依赖于其他步骤,哪些步骤可以独立运行。
- 将任务路由给合适的智能体。编排器会识别出依赖条件已满足的任务,并将工作委派给专门的智能体或模型。存在依赖关系的任务则会等待其前置任务完成。Perplexity Computer 使用多个前沿模型,将工作流的不同部分路由到适合相应任务的系统。这也使独立的工作能够并行运行。
- 在受控环境中执行工具调用。智能体通过工具与其环境交互,例如网页搜索、API、已连接的应用程序、文件操作或代码执行。执行层负责运行这些操作,并将结果返回给智能体。
- 在智能体之间传递结果和上下文。当一个智能体完成任务后,下游的下一个智能体需要相关输出才能继续。交接记录可能包含任务 ID、输出引用、模式版本和来源元数据。编排器负责协调这些交接,同时维护后续步骤所需的上下文。重要的是,智能体无需在自己的上下文窗口中承载其他所有智能体的完整工作历史。
- 将执行状态与智能体上下文分开记录。当智能体开始、完成任务或任务失败时,执行引擎会更新一份持久化的工作流记录,其中包含任务状态、执行尝试、输出引用和剩余工作。借助这份记录,编排器可以跟踪进度并在中断后恢复,而无需依赖 LLM 根据对话历史重建工作流。
- 验证结果并决定下一步。任务返回后,编排层会检查其输出是否符合预期约定,以及下一项任务的依赖条件是否已满足。如果发现问题,工作流可以返回到之前的步骤进行修正,或者暂停。否则,工作流将继续推进直至完成。
看似简单的 AI 智能体编排背后,有许多环节在同时运转。你如何组织智能体之间的协调,决定了你对执行过程有多大的控制力。当然,所有这些协调都会带来额外开销,因此并不总是值得。
何时应使用 AI 智能体编排?
当任务的不同部分需要不同的专业能力、独立的工作可以并行运行,或者你无法预先确定下一步时,可以考虑采用多智能体编排。
因此,编排在以下三种场景中很有帮助:
- 任务需要不同的专业分工。例如,一个编程项目可能会受益于分别负责规划、设计、开发和审查的智能体。
- 独立任务可以并行运行。与其让一个智能体按顺序完成所有工作,不如让多个智能体同时工作,并将结果返回给编排器。
- 问题是开放式的。智能体可能需要探索不同的方法、做出决策并相互协作,而不是遵循预定义的顺序。
除此之外,编排只是一种代价高昂的潮流。更多的智能体也意味着更多的协调工作,并可能带来更高的 token 成本。
“我通常会从最简单的方案入手,再逐步扩展。如果我们清楚具体步骤且这些步骤可以重复,那可能就是一个工作流。只有当多个智能体承担不同的职责、拥有不同的权限或服务于不同的用户时,我才认为有理由引入它们。”Josh Spilker(AirOps 搜索营销负责人)说道。
即便如此,也要权衡收益与额外的模型调用、交接、延迟和故障点。
AI 智能体编排架构及其权衡
组织智能体协调的常见方式有三种:集中式、去中心化和分层式编排。选择合适的架构归结为一个问题:由谁控制工作,智能体之间又如何相互协调?
集中式编排
在集中式编排中,由一个编排器管理整个流程。它负责拆解任务、将工作委派给专业智能体、跟踪其进度,并整合它们的结果。
权衡:集中式协调更便于跟踪执行情况,并在单一控制点应用通用规则。然而,编排器可能成为瓶颈,而且除非系统支持恢复,否则它一旦发生故障就可能中断整个工作流。
去中心化编排
在去中心化编排中,智能体之间更直接地进行协调,而不是依赖一个管理者做出所有决策。它们可以交换消息、读取共享状态,并自主确定下一步行动。
权衡:智能体无需等待中央规划器即可运行,因此这种方式适用于探索性工作和独立贡献。但当智能体之间出现分歧、更新共享信息或需要达成一致结果时,协调就会变得更加困难。
分层式编排
分层式编排将管理者模式扩展到多个层级。顶层编排器将职责委派给下级编排器,再由下级编排器协调各自的专业智能体组。
设想一个涉及销售、财务和法务团队的企业工作流。顶层编排器可以将每条工作线委派给特定领域的协调器。随后,这些协调器会管理各自的专业智能体,并汇报整合后的结果。
当工作流范围过广、单个编排器难以有效管理时,这种结构会很有帮助。
权衡:层级结构让团队能够划分协调职责,并有可能在单个分支内处理故障。然而,它会引入更多交接环节、更复杂的状态管理以及更高的运营开销。局部恢复还取决于检查点和执行状态的实现方式。
这些架构的对比如下:
评估标准 | 集中式 | 去中心化 | 分层式 |
执行归属 | 由一个编排器控制委派 | 智能体通过对等节点或共享状态进行协调 | 职责分布在各个编排层级 |
状态一致性 | 更容易通过单一控制点进行协调 | 需要显式同步和冲突处理 | 需要在分支内部及分支之间进行协调 |
故障隔离 | 中央控制器可能成为关键依赖 | 单个智能体可以独立发生故障,但共享基础设施仍然至关重要 | 如果设计时考虑了恢复机制,故障可能会被限制在分支内部 |
策略执行 | 通用控制措施可集中执行 | 策略必须在各参与方之间一致执行 | 控制措施可在全局和领域层面应用 |
运维复杂度 | 通常较低 | 协调复杂度较高 | 多个编排层带来更高的复杂度 |
顺序执行、并行执行和基于交接的执行
还有一个区别值得了解。架构决定由谁来协调智能体,执行模式则决定它们的任务如何推进。
以下是三种执行模式:
- 顺序工作流:智能体按预定义的顺序工作,一个智能体的结果成为另一个智能体的输入。
- 并行执行:相互独立的智能体同时工作。
- 基于交接的执行:随着任务推进,控制权在各专业智能体之间转移。当另一个智能体更适合处理下一步时,这种模式很有用,但每次交接都必须保留继续执行所需的信息。
这些模式并不互斥,也不与编排架构一一对应。目标是选择最简单的结构,既能支持工作流的依赖关系和协调需求,又能将运维开销控制在可接受的范围内。
常见的 AI 智能体编排故障
编排中任何环节都可能出错,从简单的疏忽到复杂的阻碍因素。有时,某个智能体看似正确地完成了工作,整个工作流却失败了。我们借鉴从业者的经验,整理了导致编排工作流不可靠的一些常见错误,请多加留意:
- 有损的智能体交接。编排器将一份概要计划传递给专业智能体,但概要中遗漏了约束条件、依赖关系或实现细节。
- 过早的扇入执行。下游智能体在所有上游任务完成之前就开始汇总结果。
- 非确定性的共享状态更新。并行智能体在没有明确定义合并语义的情况下写入相同的状态键。根据框架处理更新的方式,这可能导致写入丢失、数据重复、输出依赖执行顺序或变更冲突。
- 检查点与副作用不一致。某个任务执行了外部操作,但在工作进程发生故障之前,其成功执行的结果未被持久记录。恢复时,编排器看到一个未完成的任务,于是重新运行它。
- 人工审批恢复竞态。暂停和恢复执行会带来其自身的同步问题。
- 委派循环与重试放大。由于职责重叠、依赖关系循环或完成条件不明确,智能体反复将工作交给彼此。
- 误把指令层面的控制当作执行安全。编排器可以告诉智能体不要访问某些资源或执行敏感操作,但模型指令无法强制执行操作系统权限、网络限制或授权边界。Perplexity 的安全工程研究指出了为什么智能体在追求合法目标时可能越过安全边界,即使没有恶意指令也是如此
请注意这些故障之间的差异有多大。过早的调度器状态转换或含糊不清的外部写入都可能导致错误的结果,但它们源自执行生命周期的不同环节。这就是为什么可靠的编排不仅仅需要改进提示词或增加重试。
提升生产环境可靠性的 7 个 AI 智能体编排最佳实践
1. 定义明确的任务契约、验收标准和停止条件
目标模糊、完成定义不清,往往会导致智能体生成的结果令人失望。解决方案是使用提示词契约(即智能体的工作范围):在执行开始之前,就目标、约束条件、输出格式和失败条件达成一致。
例如,对于负责修复间歇性失败的集成测试的智能体,可以这样定义契约:
- 目标:找出并修复结账 API 集成测试不稳定的原因。
- 输入:测试源代码、CI 失败日志、近期提交和相关应用程序代码。
- 约束条件:不得禁用测试、放宽断言或修改无关的应用程序行为。
- 预期输出:代码补丁、根本原因说明和测试执行结果。
- 验收标准:之前失败的测试连续 10 次运行均通过,且相关回归测试套件通过。
- 失败条件:无法确定根本原因、修复引入了回归问题,或所需的测试环境不可用。
但还有一个重要部分:智能体应该在什么时候停止?
智能体不应因为尚未产生令人满意的结果就无限地迭代下去。要定义什么算作成功完成、何时返回部分完成的任务,以及何时因无法满足某项要求而停止。设置最大委派深度和迭代次数上限或执行预算,以免未解决的任务变成无休止的循环。
回到我们的 CI 示例。你可以定义以下停止条件:
- 成功:修复连续 10 次通过测试运行,并通过相关回归测试套件。
- 迭代上限:智能体最多可尝试两种候选修复方案。
- 执行预算:即使问题仍未解决,智能体也必须在 60 分钟后停止。
- 委派上限:智能体可以将工作委派给一个专业智能体,且不得再进一步委派给子智能体。
- 部分完成:如果两次尝试都失败或达到时间上限,智能体将返回其发现、尝试过的更改和测试结果。
- 执行受阻:如果测试环境不可用,智能体将停止并报告阻碍因素,而不是声称成功。
2. 保持编排器精简,并强制执行结构化交接
有时开发者给编排器分配了太多职责,它不再协调专业智能体,而是开始自己编写代码、调试或进行详细审查。这会造成瓶颈:编排器将上下文预算耗费在实现细节上,延迟了委派,并模糊了对结果的责任归属。
因此,让编排器各司其职,并通过引用具体工件来强制执行交接:原始任务、相关输入、输出工件、执行状态以及任何未解决的问题。
来看这个例子:status: completed 指的是分配给该智能体的工作,而不是整个工作流。由于测试仍处于 pending 状态,编排器不应批准最终结果。
{
"task_id": "fix-42",
"status": "completed",
"artifact_ref": "patch-17",
"test_status": "pending",
"blockers": []
}3. 持久化工作流状态并控制上下文增长
智能体的对话历史并不能可靠地记录工作流进度。当其上下文窗口被填满时,自动压缩可能会丢弃重要细节。而如果某个工作进程崩溃,下一个智能体需要知道哪些步骤实际上已经完成。
例如,如果编码智能体生成了一个补丁后崩溃,下一个工作进程应检索已保存的工件,并从记录的工作流状态继续执行。但如果该智能体还触发了一次外部 CI 运行,编排器必须先单独核对该运行,然后才能重复该操作
因此,要将执行状态与智能体的工作上下文分开。将任务状态、执行尝试、已完成步骤和工件引用保存在持久存储中。同时,只加载与智能体当前任务相关的指令、输入和结果,而不是把整个执行历史都塞进它的上下文窗口。
4. 设计能感知故障的重试机制和可恢复的工具执行
假设你的 CI 智能体触发了一次测试运行,但 API 请求超时了。是测试运行未能启动,还是 CI 服务已将其加入队列却丢失了响应?
超时并不一定意味着操作失败。因此,在决定下一步之前,你需要区分不同的错误:
- 暂时性错误(429、503):使用有上限的指数退避和抖动进行重试,并在提供 Retry-After 时遵循该值。
- 验证或权限错误(400、403):停止或纠正根本问题,而不是重复相同的请求。
- 结果不明确(可能已写入后超时):在再次尝试之前,先检查该操作是否已成功。
注意:即使是可重试的错误也需要设限。为每次工具调用设置超时,限制重试次数和总重试时间,并强制执行整体工作流截止时间,以免嵌套的智能体不断重启同一操作。如果某个依赖项反复失败,请使用断路器暂时停止请求。
对于具有外部副作用的操作,为每个逻辑操作分配一个稳定的幂等键,并在各次重试中重复使用。如果 API 支持服务器端去重,它就能识别重复请求,而不会将操作执行两次。如果不支持,请使用关联 ID 或其他权威引用查询外部系统。
当你无法确定发生了什么时,请停止并上报。
以下是我们 CI 智能体重试逻辑的示例,以伪代码表示:
op_id = get_or_create_operation_id(
task_id=task_id,
patch_id=patch_id,
action="start_ci_run"
)
try:
return ci.start_run(commit, request_id=op_id)
except TimeoutError:
run = ci.find_by_request_id(op_id)
if run:
return run
if ci.supports_idempotency:
return bounded_retry(
lambda: ci.start_run(commit, request_id=op_id)
)
raise NeedsReconciliation(op_id)代码说明:该示例假设 CI API 支持按请求 ID 查找运行。request_id 只有在提供方明确保证幂等性时才能防止重复。bounded_retry() 仅为示意性伪代码。在生产环境中,重试应同时受单个操作的重试预算(最大尝试次数或已用时间)和整体工作流截止时间的限制。
对于跨多个服务的较长工作流,可以考虑使用 Saga 模式,在后续步骤失败时协调补偿操作。但请记住,补偿并不总是等于完整回滚。你可以撤销数据库更新,但无法撤回已发送的电子邮件。
5. 以明确的资源预算路由和并行化工作
这里需要平衡两件事:每个任务需要多少模型能力,以及可以同时运行多少个任务。只要任一方面出错,就可能导致智能体争抢共享的 API 配额,或只依赖昂贵的推理模型。
在模型选择方面,应根据任务复杂度匹配模型能力和推理强度——这一点很简单,却常被忽视。请注意,你既可以自行配置路由规则并评估模型,也可以使用能为你处理模型选择的编排平台。
例如,Perplexity Computer 的强度模式(Effort Mode)可让你选择任务值得投入多少工作量,而无需手动选择模型。选择 Light、Standard、High 或 Ultra,Perplexity 就会自动选择负责编排的模型及其推理级别。随后,该编排器会将子任务委派给辅助智能体,这些智能体可以使用来自不同提供商的模型。
Perplexity 会从质量和成本两方面评估模型配置,优先选择能提供相当结果但成本更低的选项。如果你希望自行选择模型和推理级别,也可以使用自定义(Custom)控制项。
在并行度方面,上限应取决于你的基础设施和外部依赖项。验证共享 API 的请求速率限制和 Token 速率限制,然后在逐步提高并发量的情况下对工作流进行负载测试。观察吞吐量是否提升,或者请求是否开始排队、变慢或返回 429 错误。
为了让资源消耗保持可预测,请强制执行资源限制和调度控制:
- 控制并发和请求速率:限制每项服务的进行中调用数量,并将超额工作加入队列。请记住,仅靠并发上限无法强制执行每分钟请求数或每分钟 Token 数限制。
- 跟踪 Token 和成本预算:统计整个工作流(包括子智能体)的用量,并在剩余预算不足时停止启动新工作。
- 严格执行截止时间:设置任务和工作流的时间限制,并在支持的情况下将取消操作传递给正在运行的智能体。
- 遵循依赖关系:仅在下游任务所需的输入可用时才启动它们,而不是同时启动所有智能体。
6. 强制执行审批并隔离智能体执行
切勿让模型自行判断其操作是否安全。相反,应为智能体授予最小权限,并在应用程序代码中强制执行基于风险的审批规则。如果智能体会执行代码,请将执行过程与宿主环境隔离,并限制其对文件、网络和凭据的访问。这样,即使智能体出错或执行了不安全的代码,也能限制造成的损害。
“我对过于复杂的多智能体系统持怀疑态度,尤其是当智能体互相审查和批准对方的工作时。最终可能会有多个智能体自信地把同一个错误传递下去,却没有任何人真正发现它。”Spilker 提醒道。
对于需要人工审批的操作,请暂停执行并保存所提议的确切操作:
- 其参数
- 其目标资源
- 其提交或状态版本
- 审核者的决定
此外,还要定义审批被拒绝、过期或需要上报时会发生什么。这对于可恢复的框架至关重要,因为恢复被中断的节点时,会从该节点的开头重新执行代码。中断之前的任何副作用都可能再次发生。
因此,如果审批被拒绝或过期,请求就会关闭。如果目标提交、参数或权限在执行前发生变化,请使该审批失效并重新申请审批。
Spilker 也不认同将完全自主的端到端智能体视为目标的观点。“在我看来,更好的方法是构建几个专注的智能体,让它们职责清晰、权限明确,并在合适的环节引入人工审核。这样你依然能获得效率,同时又不会放弃完全的控制权。”他总结道。
7. 独立验证输出并测试恢复行为
你是否遇到过智能体实际失败了却报告成功的情况?这即便不让人恼火,也足够烦人,而且修复起来并不快,因为智能体的最终消息不一定会告诉你问题出在哪里。
要进行排查,请追踪执行期间发生的情况,并独立验证结果。因此,让我们花些时间来隔离并解决问题。
追踪工作流以确定问题所在
在调试智能体的提示词之前,先捕获完整的执行路径。你需要一条追踪记录,将同一工作流运行下的智能体调用、工具调用、错误和重试关联起来。
OpenTelemetry 的 GenAI 语义约定提供了一种描述这些操作的标准化方式。例如,invoke_workflow 表示工作流执行,invoke_agent 表示智能体调用,execute_tool 表示工具调用。每项操作都可以记录为一个包含其耗时、状态和相关元数据的 span。
这一步能为你提供执行路径的追踪记录,便于你找出智能体在哪里出了问题。
invoke_agent generate_patch OK
execute_tool start_ci_run OK run_id=9812
execute_tool get_ci_result TIMEOUT
agent_response: "Success"执行追踪示意。
独立审查输出
尽可能使用程序化检查。根据 JSON 架构验证输出,运行单元测试和集成测试,检查所需工件是否存在,并查询外部系统以确认操作确实已成功。
对于需要主观判断、因而无法通过程序化检查评估的输出,可以引入一个独立的审查智能体。一种方法是采用实现者–审查者–解决者循环:由一个智能体生成工件,一个具有全新上下文的审查者找出问题,再由解决者在重新运行验证之前处理这些问题。
你仍需在可能的情况下验证审查者的发现;如果你使用基于 LLM 的评分器进行重复评估,还要以人工审核过的示例为基准校准它们的判断。
注入故障以测试恢复能力
到目前为止,你已经追踪了智能体执行的操作,并检查了它们的输出是否正确。但如果 worker 在任务执行到一半时崩溃,或者 API 在接受请求后超时,会发生什么?出人意料的是,你的工作流可能在正常情况下运行良好,却在恢复过程中失败。
要测试这一点,可以在测试环境中有意注入故障:
- 模拟 API 超时
- 在外部写入与检查点之间让 worker 崩溃
- 返回格式错误的工具输出
- 使审批过期
每次测试后,检查执行追踪记录,查看哪些步骤已运行、工作流从何处恢复,以及是否有操作被重复或跳过。然后审查实际结果。
假设你的 CI 智能体发送请求以启动一次测试运行,但 API 响应超时。智能体进行重试,收到成功响应,并报告成功。一切看起来都很正常,直到你检查 CI 服务时才发现创建了两次测试运行,而不是一次。
因此,你既应验证工作流记录的状态,也应验证外部系统中的实际变更。只有当工作流达到预期状态且没有产生意外副作用时,恢复测试才应判定为通过。
将你发现的故障加入回归测试,以免日后的变更再次引入这些问题。
归根结底,成功意味着工作流通过了所需的检查,并且其外部结果已经过验证。
AI 智能体编排常见问题
为什么彼此孤立的 AI 智能体在企业规模下会失效?
彼此孤立的智能体可以各自正确完成任务,但组合在一起却会产生不一致的结果。设想一个销售智能体在 10:00 获取客户条款,一个定价智能体在 10:05 使用更新后的价格计算报价,而一个法务智能体在检查一份于 10:07 发生变更的合同。每个智能体所依据的都是不同时间点的业务快照,因此它们的输出可能相互矛盾。
在企业规模下,这一问题会更加突出,因为智能体需要与多个系统交互,这些系统各自独立更新、以不同的权限运行,而且不一定共享上下文或执行状态。
如何防止 AI 智能体陷入无限重试循环?
在多个层级设置限制:工具调用的最大重试次数、智能体的最大迭代次数、委派深度,以及整个工作流的截止时间。重试前先对故障进行分类。对于暂时性的 429 响应,如果提供了 Retry-After,请遵循该值;否则,请使用带抖动的有界指数退避。
出现验证错误或权限错误后,应停止重试未作更改的请求。如果某个下游服务反复失败,熔断器可以防止智能体产生额外负载。
崩溃后如何恢复 AI 智能体工作流?
恢复机制取决于你使用的运行时。在 LangGraph 中,PostgresSaver 等持久化检查点器会将图状态存储在某个 thread_id 下,使执行能够从持久化的状态继续。在 Temporal 中,另一个 worker 可以通过重放事件历史来重建工作流。在重放过程中,它会复用先前记录的活动结果。
如果在工作流仍在运行时重新部署应用,已保存的状态和执行历史可能会变得不兼容。Temporal 通过 Worker Versioning 和工作流修补(patching)来解决这一问题。对于基于检查点的系统,在推出不兼容的变更之前,应规划好 schema 迁移,并针对现有的已保存状态测试恢复过程。
如何测试 AI 智能体编排的可靠性?
多次运行相同的代表性任务,并区分 pass@k(k 次尝试中是否至少有一次成功)与 pass^k(k 次尝试是否全部成功)
按任务类别和工作流版本衡量结果,而不是依赖单一的汇总成功率。跟踪首次尝试成功率、多次重复运行之间的一致性、p95 延迟、每个已完成任务的成本,以及需要人工干预的比例。报告成功率时,应同时给出样本量和不确定性区间。