切换主题
第 8 章:中断恢复,工作流不是一口气跑到底
真实业务很少像算法题一样一口气跑完。发邮件前要人审核,转账前要确认,合同生成后要法务看一眼。中断恢复解决的就是这类“先停一下,等个结果,再继续”的流程。
本章边界
本章只讲 Graph 如何暂停、保存状态、接收人工或外部输入、继续执行。审批系统本身、复杂权限流不在本章实现。
1. 生活类比:快递到驿站,不是丢了
快递显示“已到驿站”,不是流程失败,而是进入等待状态。你取件后,它才继续完成交付。
Graph 中断也是这个意思:
| 快递流程 | Graph 概念 | 作用 |
|---|---|---|
| 到驿站前暂停 | interruptBefore | 执行到某个节点前先停 |
| 查询快递状态 | getState | 看当前流程停在哪里 |
| 取件并补充信息 | updateState | 写入人工审核结果或外部输入 |
| 继续配送 | invoke / stream | 从中断点继续往下跑 |
2. 最小中断示例
java
CompileConfig config = CompileConfig.builder()
.saverConfig(SaverConfig.builder()
.register(SaverConfig.SaverEnum.MEMORY.getValue(), new MemorySaver())
.build())
.interruptBefore("human_review")
.build();
CompiledGraph app = workflow.compile(config);
RunnableConfig runConfig = RunnableConfig.builder()
.threadId("email-001")
.build();
app.stream(initialState, runConfig).blockLast();
StateSnapshot snapshot = app.getState(runConfig);
RunnableConfig updated = app.updateState(
runConfig,
Map.of("approved", true, "review_comment", "可以发送"),
null
);
app.stream(null, updated).blockLast();这段代码可以翻译成四步:
text
设置中断点 -> 跑到中断点 -> 写入审核结果 -> 继续执行3. 中断恢复流程图
中断恢复离不开两个东西:
- 稳定的
threadId:否则系统不知道你要恢复哪一次运行。 - 可用的 Saver:否则暂停时的状态没地方放。
没有 threadId,像没有取件码;没有 Saver,像驿站没有货架。
4. 适合中断的场景
| 场景 | 为什么要中断 |
|---|---|
| 邮件发送前审核 | AI 可以草拟,人要确认语气和风险 |
| 报销审批 | 金额、票据、权限需要人确认 |
| 高风险工具执行 | Shell、转账、删除数据这类动作不能自动放行 |
| 合同生成 | AI 起草,法务审核后继续归档 |
| 客诉升级 | 模型判断紧急,但最终升级策略需要人工确认 |
中断不是“模型能力不够”,而是工程系统对风险负责。
5. 新手容易误解什么
误解一:中断就是异常。
异常是流程坏了,中断是流程主动停下来等信息。一个是事故,一个是红灯。
误解二:updateState(...) 只是改内存变量。
它是在 checkpoint 基础上更新图状态,并返回后续可继续执行的配置。
误解三:人工介入只是弹窗。
弹窗只是界面。真正重要的是:暂停点、状态保存、审核结果写回、继续执行。
6. 本章小结
中断恢复的工程心法:
text
先保存现场,再等待输入,拿到结果后从现场继续。下一章我们从单个 Agent 走向多个 Agent 的编排。
7. 练习题
- 设计一个“提交报销单 -> 财务审核 -> 打款”的 Graph,并标出中断点。
- 说明为什么中断恢复必须有
threadId和 Saver。 - 给一个高风险工具调用设计人工审批字段:
approved、reviewer、comment、expireAt。
课后源码索引:想验证实现时再打开
| 你想验证的结论 | 源码锚点 |
|---|---|
| 官方等待用户输入示例 | examples/documentation/src/main/java/com/alibaba/cloud/ai/examples/documentation/graph/examples/WaitUserInputExample.java,类 WaitUserInputExample,方法 createGraphWithInterrupt()、executeUntilInterrupt(...)、waitUserInputAndUpdateState(...)、continueExecution(...) |
| 中断点和 Saver 如何配置 | spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/CompileConfig.java,类 CompileConfig,方法 interruptBefore(...)、interruptAfter(...)、saverConfig(...) |
| 图如何读取、更新和判断中断状态 | spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/CompiledGraph.java,类 CompiledGraph,方法 getState(...)、updateState(...)、shouldInterruptBefore(...)、shouldInterruptAfter(...) |
| 内存 checkpoint 如何存取 | spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/MemorySaver.java,类 MemorySaver,方法 get(...)、put(...) |