🔬 LangGraph

🔬 DEEP ⭐ 20k+ Python Graph / Pregel

LangGraph — 基于 Pregel 超步模型的有状态图执行框架 · 深度源码分析 · 2026-05-17 18:59

一句话:LangGraph 是唯一采用形式化执行模型(Pregel/BSP)的 Agent 框架——超步模型为并行执行提供正确性保证,Checkpoint/Time Travel 系统是其最大实用优势,支持最健壮的人机协作与错误恢复。
📋 目录 1. 核心架构:Pregel 执行模型 2. StateGraph 构建器模式 3. 编译与执行流程 4. 检查点系统(独有) 5. 状态管理与通道类型 6. Command 控制流原语 7. 多 Agent 模式 8. 人机协作(HITL) 9. 提示工程 10. 错误处理与重试 11. 独有特性总结 12. 关键源码文件 13. 核心类 14. 深度洞察 15. 优势与劣势

1. 🏗️ 核心架构:Pregel 执行模型

LangGraph 的执行引擎灵感来自 Google 的 Pregel 图计算框架,采用 BSP(Bulk Synchronous Parallel) 超步模型:

┌─────────────────────────────────────────────────────┐ │ Pregel 超步循环 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 1. READ │───▶│ 2. COMPUTE│───▶│ 3. WRITE │ │ │ │ 读取通道 │ │ 并行执行节点│ │ 写入通道 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ ┌──────────┐ │ │ │ └─────────│4.CHECKPOINT│◀────────┘ │ │ │ 保存状态快照 │ │ │ └──────────┘ │ │ │ │ │ ▼ │ │ 还有节点?──Yes──▶ 回到 1. READ │ │ │ │ │ No │ │ ▼ │ │ 执行结束 │ └─────────────────────────────────────────────────────┘
关键设计:在同一个超步中,节点并行执行;超步结束时同步——这保证了并行写入的正确合并。这是 LangGraph 区别于所有其他框架的核心差异。
4314
Pregel 引擎行数 (main.py)
1954
超步循环行数 (_loop.py)
1964
StateGraph 行数 (state.py)
8+
通道类型实现

2. 🔧 StateGraph 构建器模式

StateGraph 是图的定义层——用户通过声明式 API 描述节点、边和状态结构:

class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
    """A graph whose nodes communicate by reading and writing to a shared state."""

    def add_node(self, name, func, ...)
    def add_edge(self, start, end)          # 固定转移
    def add_conditional_edges(self, start, path, ...)  # 条件路由
    def compile(self, checkpointer=..., ...) -> CompiledStateGraph

状态定义与 Reducer

状态通过 Annotated 类型 + reducer 函数定义——reducer 决定多个并行节点写入同一 key 时的合并策略:

from typing import Annotated
from typing_extensions import TypedDict
import operator

class State(TypedDict):
    messages: Annotated[list, add_messages]  # reducer: 追加消息
    count: Annotated[int, operator.add]      # reducer: 求和
    name: str                                # 无 reducer: 最后写入覆盖
Reducer 的意义:当两个并行节点同时写入 messages 时,add_messages reducer 将两者合并而非覆盖——这是 Pregel 并行模型的正确性保证。

条件边

def route_by_intent(state):
    if "search" in state["messages"][-1].content:
        return "search_node"
    return "chat_node"

graph.add_conditional_edges("router", route_by_intent)

3. ⚡ 编译与执行流程

用户层
StateGraph 定义 → .compile() → CompiledStateGraph
编译层
Channel 接线(节点读写映射到通道)
Channel ↔ Node 绑定 → Pregel 实例
执行层
Pregel 超步循环 → .invoke() / .stream() / .ainvoke() / .astream()

编译过程

graph = StateGraph(State)
graph.add_node("think", think_fn)
graph.add_node("act", act_fn)
graph.add_edge("think", "act")
graph.add_edge("act", END)

# 编译:将声明式图定义转换为可执行的 Pregel 实例
compiled = graph.compile(checkpointer=SqliteSaver("db.sqlite"))

# 执行
result = compiled.invoke({"messages": [...]})

流式输出

# 事件流
for event in compiled.astream({"messages": [...]}, stream_mode="values"):
    print(event)

# 支持的 stream_mode:
# "values"    — 每步后的完整状态
# "updates"   — 每步的状态增量
# "messages"  — LLM token 流
# "custom"    — 自定义事件

4. 💾 检查点系统(独有)

LangGraph 拥有所有框架中最复杂的检查点系统——这是其最大的实用优势:

BaseCheckpointSaver (抽象基类) ├── InMemorySaver ── 开发/测试 ├── SqliteSaver ── 轻量持久化 ├── AsyncPostgresSaver ── 生产 PostgreSQL(异步) ├── PostgresSaver ── 生产 PostgreSQL(同步) └── 自定义实现

检查点内容

📦 Channel Values
完整状态快照
每个通道的当前值——完整的 State 副本
📋 Versions
版本追踪
每个通道的版本号——用于检测冲突与增量更新
⏳ Pending Writes
待写入
被中断节点的未提交写入——支持恢复
🏷️ Metadata
元数据
时间戳、来源、步数——用于审计和调试

时间旅行(Time Travel)

# 获取线程的所有检查点历史
history = list(graph.get_state_history(config))

# 从特定检查点回放
graph.invoke(
    None,
    {**config, "configurable": {"checkpoint_id": checkpoint_id}}
)

# 查看特定检查点的状态
state = graph.get_state(config)
print(state.values)      # 当前状态
print(state.next)        # 下一步要执行的节点
print(state.tasks)       # 待执行任务
独有能力:时间旅行让你可以从任意历史状态重新执行图——用于调试、A/B 测试、错误回放。没有其他框架提供这种级别的状态回溯能力。

5. 🗂️ 状态管理与通道类型

通道类型体系

通道类型行为典型用途
LastValue新值覆盖旧值当前用户输入、最新状态
BinaryOperatorAggregate自定义合并函数 (a,b)→c消息列表、计数器
EphemeralValue不跨步持久化临时计算结果
DeltaChannel增量更新流式数据
NamedBarrierValue同步屏障等待所有并行节点完成
LastValueAfterFinish超步完成后才可读确保一致性读取

消息通道(Message Channel)

from langgraph.graph.message import add_messages

def add_messages(left: list, right: list) -> list:
    """智能消息合并:
    - 追加新消息
    - 按 ID 更新已有消息
    - 通过 RemoveMessage 删除消息
    """
    ...

Context 系统(新特性)

class Context(TypedDict):
    user_id: str
    db_conn: Any

graph = StateGraph(state_schema=State, context_schema=Context)

def node(state: State, runtime: Runtime[Context]) -> dict:
    user_id = runtime.context["user_id"]  # 只读,运行作用域
    return {"result": process(state, user_id)}
Context vs State:Context 是不可变的、运行作用域的数据——与 State 不同,它不会被节点修改,也不会被检查点持久化。适合注入依赖(数据库连接、用户信息等)。

6. 🎯 Command 控制流原语

Command 是 LangGraph 最强大的控制流机制——将多种操作统一为单一对象:

from langgraph.types import Command

# 状态更新 + 路由
Command(update={"key": "value"}, goto="node_name")

# 中断恢复
Command(resume="user_input")

# 上报父图
Command(update={"result": x}, graph=Command.PARENT)

# 组合使用
Command(
    update={"approved": True},
    goto="execute",
    resume=None,
    graph=None
)
🔄
update
更新状态——等价于节点的返回值
➡️
goto
跳转到指定节点——覆盖边定义的路由
⏸️
resume
从中断点恢复——传递用户输入
⬆️
graph=Command.PARENT
上报到父图——子图与父图通信

7. 🤖 多 Agent 模式

LangGraph 支持多种多 Agent 协作模式:

🎯 Supervisor(监督者)
集中式
中心节点通过 add_conditional_edges 路由到工作节点
graph.add_conditional_edges(
    "supervisor",
    lambda s: s["next_agent"]
)
🐝 Swarm(蜂群)
去中心化
Agent 通过 Command(goto="other_agent") 互相交接
def transfer_to_b(state):
    return Command(goto="agent_b")
🏗️ Hierarchical(层级)
嵌套
子图编译后作为父图的节点——多层委托
parent.add_node("team", sub_graph)
📡 Map-Reduce(映射归约)
并行
Send() API 实现动态扇出/扇入
def route(state):
    return [Send("worker", {"t": t})
            for t in state["tasks"]]

Send API(动态并行扇出)

from langgraph.types import Send

def route_to_workers(state):
    """动态决定并行执行路径——运行时才知道有多少任务"""
    return [
        Send("worker_node", {"task": task})
        for task in state["tasks"]
    ]

graph.add_conditional_edges("planner", route_to_workers)

# 所有 worker 完成后,结果通过 reducer 合并
# 然后继续执行后续节点
Send 的独特价值:并行度在运行时决定——不像固定边在编译时确定。这对于任务数量未知的场景(如"分析这 N 封邮件")至关重要。

8. 🧑‍💻 人机协作(HITL)

LangGraph 提供了所有框架中最健壮的人机协作实现——基于检查点中断:

graph = builder.compile(
    checkpointer=SqliteSaver("db.sqlite"),
    interrupt_before=["human_review"],  # 在节点执行前暂停
    interrupt_after=["ai_response"],    # 在节点执行后暂停
)

# 第一步:执行到中断点
result = graph.invoke({"messages": [...]}, config)

# 查看当前状态
state = graph.get_state(config)
print(state.values)  # 当前状态
print(state.next)    # 下一步: ["human_review"]

# 第二步:人工审查/修改后继续
# 方式1:直接继续
graph.invoke(None, config)

# 方式2:修改状态后继续
graph.invoke(
    Command(update={"approved": True}),
    config
)

# 方式3:人工修改消息后继续
state = graph.get_state(config)
state.values["messages"][-1].content = "修正后的内容"
graph.invoke(None, config)
中断机制的优势:图在检查点暂停,状态完整保存——你可以安全地修改状态再恢复,也可以多次查看状态而不影响执行。这是最干净的 HITL 模式。

9. 📝 提示工程

LangGraph 是低级图框架——不强制提示模板。图结构本身就是控制流,提示只是节点的实现之一。

设计哲学:"Bring Your Own Prompts"

LangGraph 不提供像 PydanticAI 的 SystemPrompt 或 Agno 的 instructions 参数——节点函数内完全自由定义提示。唯一例外是 create_react_agent 辅助函数提供了默认 ReAct 提示。
# 提示完全由节点函数控制
def my_agent_node(state):
    system_prompt = """你是一个专业的分析师。
    请根据上下文分析用户的问题。"""
    
    response = llm.invoke([
        SystemMessage(content=system_prompt),
        *state["messages"]
    ])
    return {"messages": [response]}

graph.add_node("agent", my_agent_node)

10. 🛡️ 错误处理与重试

节点级错误处理器

def error_handler(state, error):
    """节点级错误回调——可以返回状态更新"""
    return {"error_message": str(error), "status": "failed"}

graph.add_node(
    "risky_node",
    risky_func,
    error_handler=error_handler  # 捕获该节点所有异常
)

重试策略

from langgraph.pregel import RetryPolicy

graph.add_node(
    "api_call",
    call_external_api,
    retry=RetryPolicy(
        max_attempts=3,          # 最大重试次数
        initial_interval=1.0,    # 初始间隔(秒)
        backoff_factor=2.0,      # 退避因子
        max_interval=10.0,       # 最大间隔
    )
)

检查点恢复

# 出错后从上一个检查点恢复
state = graph.get_state(config)
# 修复状态或跳过错误节点
graph.invoke(
    Command(goto="fallback_node"),
    config
)

11. ✨ 独有特性总结

Pregel 执行模型
唯一使用 BSP 超步模型的框架——并行执行的正确性保证
💾
完整检查点/时间旅行
最复杂的状态持久化系统——支持回溯任意历史状态
🧑‍💻
中断式人机协作
最干净的 HITL 模式——检查点暂停→审查→恢复
📡
Send API
运行时动态并行扇出——并行度在执行时才确定
🎯
Command 原语
统一控制流——goto、update、resume、escalate 一体化
🔀
Reducer 状态合并
正确处理并行写入——多个节点同时更新同一状态键
📦
Context Schema
不可变运行作用域数据——与可变 State 分离
🏗️
子图组合
编译后的图可作为其他图的节点——多层抽象

12. 📂 关键源码文件

langgraph/ ├── graph/ │ ├── state.py ── StateGraph 构建器 (1964 行) │ ├── message.py ── 消息通道 + add_messages reducer │ └── _branch.py ── 条件边分支逻辑 ├── pregel/ │ ├── main.py ── Pregel 执行引擎 (4314 行) │ ├── _loop.py ── 超步执行循环 (1954 行) │ ├── _checkpoint.py ── 检查点管理 │ └── _call.py ── 节点执行逻辑 ├── channels/ │ └── *.py ── 通道类型实现 └── checkpoint/ └── *.py ── 持久化后端 (SQLite, Postgres...)

13. 🧱 核心类

职责所在模块
StateGraph图定义构建器——声明节点、边、状态graph/state.py
CompiledStateGraph编译后的可执行图——extends Pregelgraph/state.py
Pregel执行引擎——超步循环驱动pregel/main.py
Command统一控制流原语——goto/update/resume/escalatetypes.py
Send动态并行扇出——运行时创建并行路径types.py
BaseChannel通道抽象基类——状态读写的核心接口channels/
Checkpoint状态快照——用于持久化与恢复pregel/_checkpoint.py
BaseCheckpointSaver检查点存储抽象——SQLite/Postgres 等实现checkpoint/
Runtime运行时上下文——注入不可变依赖graph/state.py
BranchSpec条件边规格——定义路由逻辑graph/_branch.py
StateNodeSpec节点规格——函数、重试、错误处理器graph/state.py

14. 🧠 深度洞察

🎯 为什么 Pregel 模型重要

其他框架(CrewAI、AutoGen、Agno)使用简单循环或临时路由——并行执行时没有正确性保证。LangGraph 的超步模型确保:同一超步内的节点并行执行,写入通过 reducer 合并,然后同步进入下一超步。这是唯一有形式化执行模型的 Agent 框架。

💾 检查点是最大实用优势

Checkpoint/Time Travel 系统不只是持久化——它让 HITL、错误恢复、调试和 A/B 测试变得自然。其他框架要么没有检查点,要么只有简单的状态快照。LangGraph 的检查点包含通道版本、待写入和元数据——足以精确恢复任意中间状态。

⚖️ 严谨性的代价

LangGraph 有最陡的学习曲线和最冗长的 API。StateGraph → compile → Pregel 管线概念沉重,对比 PydanticAI 的 Agent.run() 或 Agno 的 Agent.run()。Command 原语虽强大,但也增加了心智负担。适合需要精确控制流的复杂场景,不适合快速原型。

🎯 Command 是最通用的控制流机制

在所有框架中,Command 是最通用的控制流原语——它统一了状态更新(update)、路由(goto)、中断恢复(resume)和父图上报(graph=PARENT)。其他框架需要不同的 API 完成这些操作,LangGraph 用一个对象搞定。

15. ⚖️ 优势与劣势

✅ 优势

❌ 劣势

🎯 适合场景

✅ 推荐
需要精确控制流的复杂工作流
需要人机协作(审批、审查)
需要状态回溯和调试
并行执行 + 正确性要求
生产环境持久化需求
❌ 不推荐
简单对话机器人
快速原型/概念验证
无需检查点的简单管道
团队不熟悉图论概念
对延迟极度敏感的场景