为什么生产环境的智能体必须能断点续跑
一句话结论:智能体断点续跑的核心是”每步之后落盘状态、恢复时按 thread_id 回放”——LangGraph 的 checkpointer 在每个节点执行后自动保存快照,中断(甚至进程崩溃)后用同一个 thread_id 重新 invoke,就能从最后一步继续,而不是从头再烧一遍 token 。
跑十分钟以内的玩具智能体可以不关心持久化;一旦任务跑得久、调的 API 贵、失败概率不低,没有 checkpoint 的智能体每次失败都从第 1 步重来,时间和钱都是双倍浪费。断点续跑不是锦上添花,是生产门槛。
LangGraph 的两个持久化原语
LangGraph 把持久化分成两层,别混用:
| 组件 | 存什么 | 作用域 | 典型用途 |
|---|---|---|---|
| Checkpointer | 图状态快照(每节点执行后) | 单线程(thread) | 断点续跑、 HITL 、容错、时间旅行 |
| Store | 应用定义的键值数据 | 跨线程 | 用户偏好、长期事实、共享知识 |
大多数应用两个都用:checkpointer 跟踪当前会话,store 管跨会话的长期记忆。
三步跑通断点续跑
- 编译时挂 checkpointer:开发用
InMemorySaver()(重启即丢),生产必须换PostgresSaver/SqliteSaver。 - 调用时带 thread_id:
config = {"configurable": {"thread_id": "run_123"}},它就是你的持久化游标。 - 恢复时以 None 为输入重新 stream:
graph.stream(None, config)会从该 thread 的最后一个 checkpoint 继续;换一个 thread_id 或漏掉 config,就会静默地从头开始。
from langgraph.checkpoint.sqlite import SqliteSaver
checkpointer = SqliteSaver(conn=sqlite3.connect(".checkpoints"))
graph = workflow.compile(checkpointer=checkpointer)
# 首次运行
for event in graph.stream(initial_state, config, stream_mode="updates"):
print(event)
# 崩溃/中断后恢复:thread_id 必须完全一致
for event in graph.stream(None, config, stream_mode="updates"):
print(event)
中断恢复与人工审批
checkpointer 的孪生能力是 interrupt():节点内调用后,图暂停、状态落盘、控制权交还调用方,可以等几秒也可以等几天,之后用 Command(resume=value) 注入应答继续执行——甚至可能在另一台机器上恢复。这就是人机协作审批的标准实现:智能体到达不可逆操作(转账、删库、发邮件)前暂停,把证据交给人类,批准后从同一行代码继续。 HITL 审批点怎么选位置,见 智能体人机协作(HITL)落地。
三个生产级注意点
- 节点幂等:恢复时 LangGraph 可能重放同一个节点,外部副作用(API 调用、写库、发邮件)必须可安全重复,或包成幂等操作。
- checkpoint 膨胀:长对话会积累大量快照,拖慢恢复并占用存储,要定期清理或设保留策略。
- 时间旅行调试:
graph.get_state_history(config)拿到全部历史快照,可以 fork 到任意一步重放,复现一次糟糕的运行不必重跑整段对话。
图结构本身怎么搭,先读 LangGraph 智能体教程;跨上下文窗口的长时任务整体设计(Harness 模式)见 长时运行智能体怎么搭;规划与执行的衔接参考 智能体 Planning 规划模式,LangChain 基础不牢的话从 LangChain 入门教程 补起。
MemorySaver 为什么不能上生产?
断点续跑和重试有什么区别?
什么时候不需要 checkpoint?
参考来源:LangChain 官方文档 LangGraph Persistence 与 Interrupts 章节(docs.langchain.com)。







评论 (0)