判断该不该用状态机,只问一个问题:执行顺序是需求还是建议?如果某个步骤必须先于另一个步骤发生、某条分支必须被保证、中断后必须能精确恢复,那控制流就是需求,就该用代码(状态机或图)来约束,而不是交给模型每轮临场判断。
为什么不能让模型决定下一步
模型驱动的控制流有两个结构性问题:一是不保证,同一份输入在不同轮次可能走不同分支;二是不可观测,路由逻辑藏在模型的判断里,出问题时你无法回答”它为什么走了这条路”。
更实际的问题是中断恢复。用户中途补充一句、或者流程需要人工审批时,如果”当前处于哪个状态”要靠模型从对话历史里重新推断,就一定会出现漂移。正确的做法是把状态显式持久化——状态机里是一个可序列化的状态字段,图编排里是检查点加线程标识。
判定法:控制流是需求还是建议
| 信号 | 结论 |
|---|---|
| 步骤有严格先后,颠倒会出错 | 用状态机 / 图约束顺序 |
| 分支条件可被明确写成规则 | 写成确定性分支,不让模型选 |
| 需要中途暂停、等待人工或异步回调 | 状态必须持久化,别靠对话历史推断 |
| 失败后要从中断处继续,而不是重来 | 需要检查点与可恢复状态 |
| 分支是开放的,取决于内容理解 | 交给模型判断更合适 |
四种混合形态
- 纯状态机:流程里一次模型调用都没有,只是按规则流转用户输入。这时引入编排框架的序列化和检查点开销是纯负担,用专门的状态机库或直接自己写更合适。
- 状态机为主,节点里嵌智能体:主干顺序和分支由代码定死,个别节点内部是自由智能体。这是生产环境最常见也最稳的形态。
- 智能体为主,用状态驱动它的行为模式:同一个智能体根据持久化状态切换提示词与工具集,适合”同一入口、不同模式”的场景,如引导流程与业务办理的切换。
- 多入口的混合图:不同流程各自是一个入口函数,共享同一个持久化后端与检查点,互不污染状态。适合一个产品里同时存在多种流程。
确定性分支怎么落地
关键点在于:分支函数不必是模型,任何节点都可以返回一个明确的跳转目标。伪代码结构如下:
def classify(state):
kind = detect_kind(state["url"]) # 纯逻辑,零模型调用
return {"goto": "list_flow" if kind == "list" else "detail_flow"}
跳转目标支持单个节点、节点数组(并行扇出)或带参数的发送对象。这样分支就完全在你的掌控里,而不是”模型觉得该去哪”。
中断与恢复的设计要点
- 暂停:在节点内调用中断,运行时会把完整状态写入持久化存储,然后释放资源等待,不占用任何计算。
- 恢复:用同一个线程标识重新调用并传入恢复值,执行从被中断的那一行继续,之前的任务结果会被缓存而不会重跑。
- 并行中断:多个分支同时中断时,所有待处理中断会一起呈现,可以一次性恢复,也可以逐条恢复。
- 用户中途插话:需要明确策略——排队、拒绝、中断当前运行、还是回滚重来。默认是排队,它最安全;追求聊天手感可以选中断,但要能清理未完成的工具调用。
什么时候该退回纯状态机
出现这些信号说明图编排的复杂度没换来收益:流程里几乎没有模型调用;状态转换全是纯 UI 路由;团队里非工程角色需要看懂并维护这套流程图(可视化状态图工具在这件事上明显更好用)。只要有哪怕一次模型调用,检查点带来的恢复能力就值得了。
和已有模式的关系
状态机与自由智能体的取舍,在智能体与工作流怎么选里有更完整的决策框架;涉及人工审批门的部分见智能体人在回路设计;如果流程复杂到需要拆分多个执行单元,控制流仍然应该由代码持有,参见子智能体拆分与上下文隔离。










评论 (0)