← [ BACK_TO_NOTES ]

LangGraph 中 State、Node、Edge、Checkpointer 与 Thread 的关系

把 LangGraph 的 State、Node、Edge、Checkpoint/Checkpointer 与 Thread 串成一条可执行、可持久化、可恢复的图运行时心智模型,并区分 thread-scoped state 与 cross-thread Store。

#synthesis #growing #ai #langgraph

[!info] related notes

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?
创建于 2026/9/2 更新于 2026/9/2
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本