跳转至

第 8 章 Workflow 编排设计

在前面的章节里,我们已经分别讨论了 Agent 的系统视角、基本架构、Prompt 控制层、Planning 机制和 Tool Use 执行层。到这里,一个更高层的问题自然会出现:当任务不再是单步推理或单次工具调用,而是跨越多个阶段、多个动作、多个条件判断时,系统究竟靠什么保持稳定推进?

很多团队会本能地把这个问题全部交给 Agent 自主处理,认为只要模型足够强,它就能自己想清楚阶段、顺序、失败恢复和终止条件。但这在工程上通常是不成立的。复杂任务之所以复杂,不只是因为它需要推理,而是因为它需要结构。Workflow 的意义,正是在这里出现。

本章要讨论的,不是把 Workflow 作为 Agent 的替代品,而是把它理解为 Agent 可控落地的主干结构。它负责给不确定性划边界,让系统知道哪些阶段是固定的,哪些动作是开放的,哪些失败可以重试,哪些节点必须停下来。

flowchart TB
    A["Workflow 主干阶段"] --> B["阶段门禁 / 校验"]
    B --> C["Agent 阶段内判断"]
    C --> D["工具执行"]
    D --> E["状态更新"]
    E --> F{"进入下一阶段?"}
    F -- "是" --> A
    F -- "否 / 失败" --> G["重试 / 回退 / 人工介入"]

8.1 为什么 Agent 需要编排

只要任务开始跨越多个步骤,编排问题就不可避免。因为系统不仅要关心“下一步做什么”,还要关心“当前处于哪个阶段”“哪些动作应该先发生”“失败后回到哪里”“什么时候可以宣布完成”。这些问题如果完全依赖模型临场决定,很快就会变成调试噩梦。

首先,多步骤任务需要阶段边界。一个代码修复 Agent 和一个企业工单处理 Agent,虽然具体场景不同,但都会自然出现类似的阶段划分:收集信息、分析问题、执行动作、验证结果、生成输出。阶段边界的价值在于,它让系统知道当前重点是什么,以及哪些动作在这一阶段是合理的。

其次,高风险动作需要门禁。只要任务里存在写操作、外部副作用或跨系统联动,系统就必须知道哪些动作不能在没有前置条件时发生。编排提供的正是这种“先满足条件,再开放动作”的结构化控制。

再次,长任务需要可恢复和可观测。一个可能运行数分钟、数小时甚至跨越人工审批的任务,不可能只靠一次模型调用维持一致性。它需要阶段状态、任务 ID、中间产物、重试记录和错误恢复点。没有编排,长任务几乎无法被稳定管理。

从这个角度看,Workflow 的价值不是替 Agent 思考,而是把那些不应该依赖即兴判断的结构性问题,从模型层拿回系统层。

工程提示

只要系统开始需要回答“现在做到哪一步了”,编排问题通常就已经存在了,只是有没有被正式设计而已。

8.2 状态机驱动的编排

状态机是最经典、也最容易落地的一种 Workflow 形式。它的核心思想很直接:系统定义一组明确状态,以及状态之间允许发生的转换。每次执行动作、收到事件或通过校验后,任务从一个状态进入下一个状态。

状态机特别适合阶段明确、门禁清晰的任务。例如:

  • 文档处理任务中的“上传 -> 解析 -> 提取 -> 审核 -> 发布”。
  • 工单处理任务中的“接收 -> 分类 -> 分析 -> 执行 -> 回执”。
  • 代码修复任务中的“分析 -> 修改 -> 测试 -> 生成说明”。

它的最大优势是可控。因为系统能够明确知道当前在哪个阶段、下一步允许做什么、什么条件下必须停止、什么条件下可以重试。对高风险任务来说,这种明确性非常重要。

状态机的缺点则在于灵活性有限。当任务路径高度动态、分支组合太多、阶段依赖很难枚举时,纯状态机可能会膨胀得很快,维护成本随之上升。因此,状态机更适合承担“稳定主干”,而不是替代所有局部决策。

换句话说,状态机最好的用法通常不是“控制每一个细节动作”,而是“控制关键阶段与门禁”,把阶段内的局部开放动作继续交给 Agent。

工程提示

状态机适合控制阶段,不适合承载所有智能。如果一个状态机开始细到替每一步推理做决定,系统通常已经在错误层次上建模了。

8.3 DAG 编排与任务依赖

并不是所有任务都天然适合按线性阶段推进。很多现实任务更像一组存在依赖关系的子任务网络:有些步骤必须先做,有些步骤可以并行,有些步骤的结果会共同汇总到后续阶段。这类问题更适合用 DAG,也就是有向无环图的方式表达。

DAG 编排的核心价值在于把“依赖关系”显式化。系统不再只知道先后顺序,还知道哪些步骤之间存在前置条件,哪些步骤可以并行推进。对于以下场景,DAG 特别有用:

  • 需要从多个来源同时收集信息。
  • 某些分析任务彼此独立,可以并行执行。
  • 下游动作依赖上游多个结果汇总。
  • 不同子任务失败后需要局部重跑,而不是整段重来。

例如一个复杂研究型 Agent,可能需要同时检索多个知识源、读取若干文档、运行结构化查询,然后再把这些结果交给后续综合分析。这时如果强行套进线性状态机,往往会丢失很多依赖信息;而 DAG 则能更自然地表达“哪些节点必须完成后才能继续”。

但 DAG 也有代价。它提升了系统表达力,同时也提升了运行时调度复杂度。节点状态、并行控制、失败重试、依赖回收和最终汇总,都需要更严格的运行时支持。因此,DAG 更适合复杂度已经足够高、并行收益确实存在的系统,而不应被滥用到简单任务中。

8.4 事件驱动的编排

除了状态机和 DAG,还有一类非常重要的编排模式是事件驱动。它特别适合那些执行链路长、外部反馈晚、或者中间依赖异步系统回调的任务。

事件驱动的核心不是“先设计所有步骤”,而是让系统围绕关键事件做状态推进。例如:

  • 收到用户提交事件后创建任务。
  • 收到外部审批通过事件后进入下一阶段。
  • 收到工具执行完成事件后启动验证步骤。
  • 收到定时触发事件后继续中断任务。

事件驱动的优势主要体现在长链路任务上。它允许系统把任务切成若干可独立推进的片段,不必把所有执行压在单个同步请求里。对于异步工具、人工审批、定时调度、消息队列和分布式协作系统,这种模式尤其重要。

但事件驱动也会带来更高的系统复杂度。事件顺序、重复投递、丢失处理、幂等消费、状态一致性,都会变成需要正面设计的问题。也正因如此,事件驱动适合那些确实需要异步推进和外部反馈的任务,而不适合为了一点“架构感”而提前引入。

从工程视角看,事件驱动最值得关注的不是“事件很多”,而是“状态是否能在事件之间保持一致并可恢复”。

工程提示

当一个任务需要跨越请求边界、时间边界或人工边界时,事件驱动通常不是可选增强,而是基础设施要求。

8.5 Agent 与 Workflow 的协作边界

Workflow 编排设计里最关键的问题之一,不是采用哪种形式,而是弄清楚哪些逻辑应该由 Workflow 硬编码,哪些逻辑可以交给 Agent 自主判断。

一个相对稳健的原则是:Workflow 决定主干阶段,Agent 决定阶段内动作。

也就是说,系统应尽量把以下内容固化在 Workflow 中:

  • 阶段顺序。
  • 风险门禁。
  • 必经校验。
  • 人工审批节点。
  • 完成与失败的终止条件。

而把以下内容交给 Agent:

  • 当前阶段内先查询哪些信息。
  • 哪个低风险工具更合适。
  • 如何整理阶段内得到的证据。
  • 是否还需要补充一次检索或验证。

这种边界之所以重要,是因为它把“结构性确定问题”和“局部开放判断问题”分开了。前者适合用程序保证稳定,后者适合用 Agent 提供灵活性。

如果把所有事情都交给 Workflow,系统会越来越僵硬,新增一个变体就要改大量逻辑;如果把所有事情都交给 Agent,系统又会缺少稳定主干,最终变得难以预测。工程上真正有效的方案,通常是两者配合,而不是相互替代。

工程提示

判断一个逻辑该不该进 Workflow,可以问一句:如果模型今天状态差一点,这个逻辑还能不能被允许出错。不能,就尽量别交给 Agent。

8.6 编排中的关键工程问题

一旦 Workflow 进入真实系统,问题很快就不会停留在“怎么画流程图”,而会进入运行时细节。

首先是状态持久化。无论是状态机、DAG 还是事件驱动,系统都必须知道当前任务停在哪里、哪些节点已完成、哪些还未完成、哪些失败了。这些信息如果只停留在内存里,长任务和中断恢复就无法成立。

其次是中断恢复。工具失败、进程重启、人工审批延迟、外部回调迟到,都会让任务在中途停住。系统必须明确恢复点在哪里,恢复后是否需要重跑某一步、局部回滚,还是继续向后推进。

第三是人工审批节点。现实中的高风险动作通常不会完全自动化,因此编排里必须考虑“机器做到这里,人来做最后判断”。审批节点不只是一个 UI 按钮,它还意味着状态冻结、上下文保留、审批结果回流和后续阶段解锁。

第四是失败补偿与回退。不是所有失败都能通过简单重试解决。有些动作已经部分成功,有些外部副作用已经发生,这时系统需要明确补偿策略,而不是假设“失败就当没发生过”。

第五是并发与重复触发。特别是在事件驱动和 DAG 模式下,同一任务可能因为重复消息、并发调度或异常重放而被多次推进。没有幂等和去重控制,Workflow 很容易把一个逻辑正确的系统变成一个执行错误的系统。

这些问题说明,Workflow 编排真正难的地方不在图形表达,而在运行时控制。

8.7 常见反模式

Workflow 最常见的反模式之一,是把所有事情都交给 Agent。系统只负责把目标发给模型,剩下的阶段、顺序、恢复、确认全部让模型自己判断。这样的系统在 Demo 中可能显得灵活,但一旦进入高风险任务,很快就会暴露不可控问题。

第二个反模式是把所有路径都硬编码死。团队为了追求确定性,把大量本应由 Agent 自主处理的局部判断也写进流程,结果系统变得越来越脆,稍有变体就需要改编排逻辑。

第三个反模式是“看起来有 Workflow,但其实没有状态可见性”。表面上系统定义了阶段和节点,实际上运行时看不见当前状态、失败位置、重试记录和中间产物。这类系统一旦出错,排查几乎只能靠猜。

第四个反模式是把 Workflow 和 Prompt 混在一起。试图靠 Prompt 告诉模型“你现在处于第几阶段、接下来只能做什么”,却没有程序层面的门禁和状态限制。这种做法通常会让编排失去刚性。

这些反模式的共同点是:要么高估 Agent 自主性,要么低估结构化控制的成本。真正成熟的编排,不是看起来最灵活,也不是看起来最严格,而是在可控性和灵活性之间找到稳定边界。

工程提示

如果一个 Workflow 设计既不能回答“失败后怎么办”,也不能回答“为什么现在允许做这个动作”,那它大概率还只是一个流程草图。

8.8 本章小结

Workflow 不是 Agent 的替代品,而是 Agent 可控落地的主干结构。状态机适合阶段明确、门禁清晰的任务;DAG 适合依赖关系明确、局部可并行的任务;事件驱动适合长链路、异步和外部反馈密集的任务。不同形式的共同目标,都是把那些不应依赖临场即兴判断的结构性问题,从模型层收回到系统层。

成熟系统通常既不是“纯 Agent”,也不是“纯 Workflow”,而是“Workflow 托底 + Agent 增强”。前者提供阶段、门禁、恢复和审计,后者在局部不确定节点提供灵活判断。只有当两者边界清楚,复杂任务系统才可能既有执行力,也有稳定性。

下一部分将把视角转向另一个经常决定 Agent 上限的问题:Context Engineering。也就是在进入模型之前,系统究竟应该如何组织上下文、筛选信息,并控制长上下文带来的效果衰减。