LangGraph 中 State、Node、Edge、Checkpointer 与 Thread 的关系
把 LangGraph 的 State、Node、Edge、Checkpoint/Checkpointer 与 Thread 串成一条可执行、可持久化、可恢复的图运行时心智模型,并区分 thread-scoped state 与 cross-thread Store。
[!info] related notes
- 所属 MOC:
- 相关概念: checkpoint、agent-runtime
- 易混淆概念:
- 相关资源: langgraph
LangGraph 中 State、Node、Edge、Checkpointer 与 Thread 的关系
覆盖范围
这篇只回答 LangGraph 最容易混淆的一组核心抽象如何协作:
State
Node
Edge
Checkpoint / Checkpointer
Thread
目标不是背 API,而是建立一条稳定心智模型:
State = 当前知道什么
Node = 当前做什么
Edge = 下一步去哪
Checkpoint = 某个时间点保存下来的 StateSnapshot
Checkpointer = 如何持久化 / 恢复这些快照
Thread = 这些快照属于哪一条连续执行历史
一张图串起来
Graph
┌──────────────┐
│ State │
│ messages │
│ query │
│ results │
└──────┬───────┘
│
▼
[Node A]
│
State Update
│
▼
reducer 合并
│
▼
Conditional Edge
/ \
/ \
[Node B] [Node C]
------------------------------------------------
Thread: thread-123
│
├─ Checkpoint 1 -> StateSnapshot
├─ Checkpoint 2 -> StateSnapshot
├─ Checkpoint 3 -> StateSnapshot
└─ Checkpoint 4 -> StateSnapshot
▲
│
Checkpointer
保存 / 加载
LangGraph 官方把图最核心的三个组成定义为 State、Nodes、Edges;图执行过程中 State 不断演进,而 persistence 层再通过 checkpointer 把 thread 的 graph state 保存为 checkpoints。
State:图当前的共享状态
State 是 Graph 当前数据的结构化快照,也是 Nodes 和 Edges 共同读取的运行上下文。
例如:
class State(TypedDict):
messages: list
query: str
search_results: list
final_answer: str
运行中可能是:
State
├─ messages = [...]
├─ query = "LangGraph 是什么"
├─ search_results = [...]
└─ final_answer = null
Node 通常返回的是 partial update
Node 不要求重新构造完整 State:
def search_node(state: State):
return {
"search_results": search(state["query"])
}
可以理解成:
Old State
+
Node Update
↓
Reducer
↓
New State
Reducer 决定一个字段如何更新
默认情况下,新的值通常覆盖旧值。
如果某个字段需要累积,例如 messages/list,可以为该 state channel 指定 reducer:
旧 messages
+
新 messages
↓
append / merge reducer
↓
新 messages
所以更准确地说:
State 不只是一个 dict/schema,还包括每个 state channel 如何接收更新的合并语义。
State 不等于 LLM Context Window
State 可以包含:
- messages
- tool results
- retry counter
- routing decision
- intermediate artifacts
- business state
真正传给某次 LLM 的内容只是 State 的一个投影。
Graph State
↓ context construction
LLM Input
所以不要把:
State = Prompt / messages
当成完整定义。
Node:执行计算或副作用的单元
Node 本质上是函数:读取当前 State,执行逻辑,然后产生 State update 或控制命令。
Node 可以做:
LLM inference
Tool call
Database query
HTTP request
Pure code computation
Human-in-the-loop interrupt
Business validation
因此:
Node 不等于 LLM Node。
例如:
[plan] = LLM
[search] = Search Tool
[validate] = deterministic code
[persist] = DB write
它们都可以是 Node。
Edge:控制下一步去哪
如果:
Node = computation
那么:
Edge = control flow
Fixed Edge
START
↓
plan
↓
search
↓
answer
↓
END
Conditional Edge
┌→ search
router / state
└→ answer
关键不是“Edge 本身做业务工作”,而是根据当前状态确定后续哪些 Node 被调度。
因此 Agentic routing 常常表现为:
Node 产生 observation / decision
↓
Conditional Edge 根据 state 选择路径
↓
下一 Node
Checkpoint:某个 super-step 边界的 StateSnapshot
Checkpoint 是 thread 在某个时间点的 graph state snapshot。
LangGraph 的图运行采用 super-step 模型:同一 super-step 中可以有多个节点并行执行;完整 checkpoint 通常在 super-step 边界形成。
例如顺序图:
START -> A -> B -> END
可以粗略理解成:
Checkpoint 0: 等待 START
Checkpoint 1: 输入已进入,下一步 A
Checkpoint 2: A 完成,下一步 B
Checkpoint 3: B 完成,Graph 结束
Checkpoint 不是“每个 token 保存一次”,也不应该简单理解成“每次 LLM / Tool 后固定保存一次”;边界由 LangGraph 的 super-step / persistence 语义决定。
一个 StateSnapshot 除了 state values,通常还包含:
- next:下一批要执行的节点
- config:thread_id / checkpoint_id / namespace
- metadata:step、writes 等执行信息
- parent checkpoint
- pending tasks / interrupts 等
所以 checkpoint 不只是“一个 state dict”。
Checkpointer:持久化 Thread State 的基础设施
Checkpointer 是实现 checkpoint 保存、读取、历史查询与恢复的 persistence backend / interface。
Graph
↓
Checkpointer
↓
Checkpoint History
启用 checkpointer 后,LangGraph 可以支持:
- conversation continuity
- Human-in-the-loop interrupt / resume
- failure recovery
- state history
- replay / time travel
- 从历史 checkpoint fork 新轨迹
典型配置:
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
graph = builder.compile(checkpointer=checkpointer)
config = {
"configurable": {
"thread_id": "thread-123"
}
}
graph.invoke(input_state, config)
InMemorySaver 只适合实验;进程重启后数据会消失。生产环境通常使用持久化 saver,例如 PostgresSaver。
Thread:一条连续 Graph 执行历史的身份
这里的 Thread 不是 OS Thread,也不是 Python / Java Thread。
更准确的理解是:
Thread 是 LangGraph persistence 中用于关联一系列 runs 和 checkpoints 的执行历史标识。
例如:
thread_id = conversation-42
Run 1
User: 我叫 Sean
↓
Checkpoint ...
Run 2
User: 我叫什么?
↓
同一个 thread_id
↓
加载之前累计的 graph state
因此一个 Thread 可以包含多个 Run 的累计 State 历史:
Thread
├─ Run 1
│ ├─ Checkpoint A
│ └─ Checkpoint B
│
└─ Run 2
├─ Checkpoint C
└─ Checkpoint D
Checkpointer 使用 thread_id 来保存和恢复对应的 checkpoints。
Thread 与 State 的区别
State
= 这一时刻有哪些数据
Thread
= 这一系列状态快照属于哪条连续执行历史
所以:
Thread != State
Thread contains / identifies checkpoint history
Checkpoint contains StateSnapshot
Checkpointer、Checkpoint、Thread 三者不要混
Thread
= identity / history container
Checkpoint
= 某个时间点的 StateSnapshot
Checkpointer
= 保存与加载这些 StateSnapshot 的机制
类比 Git:
thread ≈ 一条持续工作的历史上下文
checkpoint ≈ 一个历史快照
checkpointer ≈ 保存 / 查询快照的存储机制
只是类比,不要把 LangGraph checkpoint 直接等同于 Git commit。
Thread-scoped Memory 与 Long-term Store
LangGraph 当前 persistence 模型明确区分两类持久化:
Checkpointer
→ Graph State snapshots
→ scope = 一个 Thread
→ short-term / thread-scoped memory
Store
→ application-defined data
→ scope = 跨 Thread
→ long-term / cross-thread memory
例如:
放 State / Checkpointer
当前对话 messages
当前任务执行到哪里
本轮 tool result
pending interrupt
retry count
放 Store
用户长期偏好
跨会话事实
用户 profile
应用共享知识
所以不要把所有“Memory”都塞进 State。
一次执行到底发生了什么
1. invoke(input, thread_id)
↓
2. Checkpointer 加载该 thread 的最近 checkpoint(如存在)
↓
3. 输入被合并 / 应用到 Graph State
↓
4. 当前被调度的 Node 读取 State
↓
5. Node 返回 partial State Update
↓
6. Reducer 将 Update 合并进 State
↓
7. Edge / routing 决定下一批 Node
↓
8. super-step 完成
↓
9. Checkpointer 持久化新的 StateSnapshot
↓
10. 下一 super-step
↓
11. END / interrupt / failure
这条链把五个概念真正串到了一起。
最容易答错的地方
Thread 就是一轮调用
错误。一个 Thread 可以跨多个 Run 累积状态。
Checkpointer 就是长期记忆数据库
不准确。Checkpointer 主要持久化 thread-scoped graph state;跨 thread 的长期业务记忆更适合 Store。
Checkpoint 只保存 messages
错误。Checkpoint 保存的是 Graph 的 StateSnapshot 和执行恢复相关信息,不只是聊天记录。
Node 就是调用 LLM
错误。Node 可以是任意计算或副作用。
Edge 就是 if / else
只说对了一部分。Edge 表达图中的控制流;可以是固定 transition,也可以基于 State 做 conditional routing。
State 是一个全局可随意修改的 dict
不够准确。Node 返回 update,State channel 按 reducer 规则演进;在并行 Node 场景下 reducer 尤其重要。
面试最短回答
LangGraph 是一个有状态的图执行运行时。State 表示图当前共享的数据快照;Node 是读取 State、执行计算或副作用并产生 State update 的执行单元;Edge 描述控制流,决定下一步调度哪个 Node。启用 Checkpointer 后,LangGraph 会把 Thread 的 Graph State 按 checkpoint 持久化,从而支持中断恢复、故障恢复、time travel 和短期记忆。Thread 不是操作系统线程,而是这一系列 Runs 和 Checkpoints 所属的执行历史标识。简单说,State 是数据,Node 是做事,Edge 是去哪,Checkpoint 是快照,Checkpointer 是保存快照的机制,Thread 是这条历史属于谁。
推荐记忆
State = What do we know?
Node = What do we do?
Edge = Where do we go next?
Checkpoint = What did the state look like here?
Checkpointer = How do we persist / restore it?
Thread = Which execution history does it belong to?