工作流里某个节点失败了,整条流程该停还是继续?
简化版
没有统一答案,要按节点配置失败策略:结果是后续步骤必需的(比如生成回复的大模型节点),失败就停止整条流程;结果是可选的(比如顺手记一条工单的接口),失败就继续,把「失败 + 原因」作为这个节点的输出写进上下文,让下游能判断;有合理默认值的判断(比如表达式求值出错),可以用默认值兜底。不管停还是继续,都要做到三件事:失败的那一步在步骤日志里有记录,运行记录回写成失败并写明原因,用户看到的是能看懂的错误而不是一个笼统的报错。整次运行失败后是否允许重试,要规定只有失败状态才能重试、重试次数有上限,并在重试前重新读取可能已经修正的配置。
详细版
| 策略 | 做法 | 适合的节点 | 风险 |
|---|---|---|---|
| 停止(stop) | 抛出异常,整次运行记为失败 | 结果被后续节点必需 | 一个可选步骤失败也会拖垮整条流程 |
| 继续(continue) | 把 {success: false, error: …} 作为输出继续走 | 可选的旁路动作(通知、记录) | 下游如果不检查,会拿着失败结果往下算 |
| 默认值(default) | 出错时用配置好的默认结果 | 有安全默认值的判断 | 默认值选错会把流程带进错误分支 |
节点执行
├─ 成功 → 写步骤日志(成功)→ 输出写回上下文
└─ 失败 → 看失败策略
stop → 写步骤日志(失败 + 原因)→ 运行记为失败,停止
continue → 写步骤日志(成功,输出是失败对象)→ 继续
default → 用默认结果当输出 → 继续
完整版教学
一、为什么不能一刀切
一条流程里的节点重要程度并不一样。拿一条客服流程来说:检索资料、生成回复是主干,没有它们就没有结果;清洗文本是加工,失败了用原文也能凑合;最后调内部接口记一条工单是旁路,接口挂了,回复本身照样有用。
开始 → 检索 → 生成回复 → 清洗 → 判断 → [记工单] → 结束
主干 主干 加工 主干 旁路
如果任何失败都停,旁路接口一挂,用户就拿不到本来已经生成好的回复;如果任何失败都继续,主干节点失败后下游会拿着空值往下算,最后给出一个看起来正常、实际错误的结果。所以失败策略要跟着节点走,配在节点上,而不是整个引擎一个开关。
二、停止:什么时候必须停
结果被后续步骤必需时必须停。判断方法很简单:把这个节点的输出去掉,后面的节点还能产出有意义的结果吗?不能,就停。
停的时候要注意三件事。第一,异常信息要改写成人能看懂的话,比如「大模型节点执行失败:请先在 AI 模型配置中填写可用 API Key」,而不是一段堆栈。第二,停在哪一步要能查到:这一步的步骤日志记为失败,带上错误原因和耗时。第三,引擎不要把异常直接抛给调用方,而是回写运行记录的状态和原因再正常返回,否则库里会留下一条永远「运行中」的记录。执行主循环怎么组织,见「工作流执行引擎怎么按连线执行?条件分支和死循环怎么处理?」。
记忆钩子:停,也要停得明白——哪一步、什么原因、运行记录是什么状态,三样都要落库。
三、继续:失败本身也是一种输出
旁路节点失败时继续,但不能假装成功。正确做法是把失败包装成一个结构化的结果写进上下文:
{"success": false, "error": "Read timed out after 10000 ms"}
这样下游节点有机会判断:后续的连线可以写 ticketResult.success == true 才走某个分支;结束节点汇总时也能说明「回复已生成,工单记录失败」。步骤日志里这一步可以记为「成功」(节点按策略处理完了),但输出里清清楚楚是失败对象,排查时一眼能看出接口没调通。
继续策略最常见的坑是下游不检查:接口返回失败对象,下一步把它当正常数据拼进 Prompt,模型就会基于一段错误信息生成内容。
四、默认值:判断出错时走安全的一边
条件判断节点的表达式也可能出错,比如变量类型和预期不一致。这时可以配一个默认结果:出错就当作 false(或 true)继续。关键在于默认值要选安全的那一边:
| 判断 | 出错时默认 | 理由 |
|---|---|---|
| 是否需要人工复核 | true | 多一次人工复核,好过漏掉一个高风险请求 |
| 是否自动发送给客户 | false | 宁可不发,也别发出一段没校验过的内容 |
| 是否需要记录工单 | false | 工单是旁路,少记一条影响小 |
如果找不到安全的默认值,就应该配成停止。默认值的另一个要求是:日志里要能看出「这次是走了默认值」,否则会以为判断逻辑本身算出了这个结果。
五、节点级的超时和重试
外部调用最常见的失败是超时。每个调外部接口或模型的节点都应该有自己的超时,比如 HTTP 节点默认 10 秒,模型调用整次 60 秒,别让一个卡住的调用把整条流程挂住。
节点内自动重试要谨慎:只读的查询可以重试;有副作用的调用(写工单、发消息、扣款)重试前要确认接口是幂等的,否则一次超时可能变成两张工单。重试次数和间隔也要有上限,比如最多 2 次、间隔 1 秒和 2 秒:
单次超时 10 秒,最多重试 2 次,退避 1 秒、2 秒
最坏耗时 = 10 × 3 + 1 + 2 = 33 秒
这个数字要和整条流程的超时预算放在一起看,几个节点都这样重试,流程总耗时会迅速失控。
六、整次运行失败后的重试
节点层面处理不了的失败,最终会让整次运行落到失败状态。是否允许用户手动重试、怎么重试,也要设计:
| 规则 | 原因 |
|---|---|
| 只有失败状态才能重试 | 运行中的重试会导致同一任务被执行两遍 |
| 重试次数有上限 | 配置本身有问题时,反复重试只是浪费调用 |
| 重试前重新读取配置 | 上一次可能就是因为配置错误失败,管理员改过之后应使用新配置 |
| 写结果前清掉上一次的半成品 | 否则会出现新旧结果混在一起 |
重试沿用原来那条记录还是新建一条,取决于是否需要保留每次尝试的历史;沿用原记录时要把错误原因、开始和结束时间一起重置。
七、失败要能被定位
失败处理的最终目的是让人能快速找到原因。一次失败的运行至少要能回答:
哪次运行失败? 运行记录:状态、错误原因、总耗时
失败在哪一步? 步骤日志:节点名、状态为失败的那一条
这一步当时看到什么? 步骤日志:执行前的完整上下文
如果是模型的问题? 模型调用日志:最终 Prompt、返回内容、token
这三层记录串起来,从「这次运行失败了」到「第 3 步的 Prompt 里资料是空的」只需要几次点击。
八、常见误区与追问
- 误区:节点失败就应该停止整条流程。 旁路节点失败时停止,会让已经生成的主结果也交付不了。
- 误区:继续执行就是把失败吞掉。 继续要把失败包装成结构化结果写进上下文,下游才能判断。
- 误区:默认值随便选一个。 默认值要选安全的一边,找不到安全默认值就应该停止。
- 误区:节点失败直接把异常抛给调用方最省事。 运行记录会停在「运行中」,失败原因也没有落库。
- 误区:有副作用的节点超时就自动重试。 接口不幂等时,一次超时可能变成两次写入。
- 追问:怎么判断一个节点该配停止还是继续? 去掉它的输出,看后续节点还能不能产出有意义的结果,不能就停止。
- 追问:重试为什么要重新读配置? 上一次失败可能就是配置问题,管理员修正后,重试应该用新配置而不是旧的。
九、加强记忆
节点失败记「三种策略、三样落库」:结果被后续必需的节点失败就停止,可选的旁路节点失败就继续并把 {success: false, error} 写进上下文,有安全默认值的判断出错就走默认值,策略配在节点上而不是整个引擎一个开关。无论哪种,失败的那一步写进步骤日志,运行记录回写失败和原因,用户看到人能读懂的提示,引擎不把异常直接抛出去。外部调用配节点级超时,有副作用的调用重试前先确认幂等。整次运行失败后,只有失败状态能重试、次数有上限、重试前重读配置、写结果前清掉半成品。
项目实战落地
项目里怎么做的
《AI企业流程编排系统》把失败策略配在节点的 config_json 里:
- HTTP 节点:
failStrategy默认stop,抛出「HTTP节点执行失败:……」让整次运行失败;配成continue时把{"success": false, "error": …}作为输出继续往下走;超时timeoutMs默认 10000;示例客服流程里「记录客服工单」这一步就配了continue,请求的是演示地址,失败了也不中断流程; - 条件节点:表达式求值抛异常时,
failStrategy为stop就中断,否则用配置里的defaultResult(默认false); - 大模型节点:调用失败时先写一条失败的 AI 调用日志,再抛出「大模型节点执行失败:……」;模型调用整次超时 60 秒;
- 步骤日志一定落库:
executeStep在finally里补上耗时并插入步骤日志,成功写输出,失败写错误原因; - 运行记录回写失败:
execute捕获任一节点的异常后调用finishRun记为失败并写入error_message,不再向外抛,页面拿到的是这条运行记录。
《AI Agent智能会议纪要辅助系统》处理的是整个任务的失败:转写任务任何一步失败都落到 FAILED 并记下原因;只有失败且重试次数没到上限的任务才出现「重试」按钮,重试时重新取当前启用的转写模型配置(上次失败可能就是配置问题),重新执行时先清掉上一次写入的片段再写。
为什么这样取舍
- 工单节点配 continue:演示环境里没有真实的内部工单系统,配成失败继续,示例流程才能完整跑通,这一步的输出里能看到失败原因。
- 失败也返回运行记录:页面拿到的是「请先填写流程的初始参数:customerQuestion」这种具体的话,而不是一个笼统的报错。
面试官还会追问
- 大模型节点没配 API Key 时,会往 AI 调用日志里写一条失败记录吗?为什么?
- 工具节点配置了一个后端没有实现的工具编码,执行时会报错吗?
- 流程运行失败时,工作台的对话区里用户看到的是什么?请求本身异常时又显示什么?
学完《AI企业流程编排系统》,上面这些追问你都会迎刃而解。