【LangGraph】源码剖析(一):从 StateGraph 到 Pregel——图计算引擎驱动的 Agent 框架
【LangGraph】源码剖析一从 StateGraph 到 Pregel——图计算引擎驱动的 Agent 框架写在前面如果你用过 LangChain你一定知道 LangGraph——它是 LangChain 生态中最核心的 Agent 编排框架GitHub 上拥有超过12 万 Star被 Replit、Uber、LinkedIn、GitLab 等公司用于生产环境。但你是否想过LangGraph 的运行时到底是怎么工作的为什么它叫Graph而不是ChainStateGraph 和普通 DAG 有什么区别Pregel 又是什么今天起我将用4 篇文章带你从源码层面彻底搞懂 LangGraph 的每一个核心机制。这是第一篇——从 StateGraph 到 Pregel理解 LangGraph 的架构全貌。 文章目录 一、LangGraph 是什么不是什么️ 二、五层架构从 API 到 Checkpoint 的分层设计 三、StateGraph不是 DAG是带状态的图⚡ 四、PregelLangGraph 的灵魂——BSP 执行模型 五、源码目录结构Python 包的精巧布局 六、一条消息的完整旅程从 invoke 到输出⚖️ 七、LangGraph vs OpenClaw两种 Agent 工程哲学 八、系列预告 一、LangGraph 是什么不是什么1.1 LangGraph 不是什么很多人对 LangGraph 有一个误解它就是一个画流程图的工具——把几个节点连起来定义一下条件边跑起来就完事了。这种理解太浅了。如果只是画流程图那 Mermaid 一个 while 循环就够了为什么需要 3 万行代码LangGraph 也不是 LangChain 的简单扩展。LangChain 的核心抽象是 Chain链式调用而 LangGraph 的核心抽象是Graph图计算。两者的本质区别在于Chain 是线性的、串行的、无状态的Graph 是非线性的、可并行的、有状态的。1.2 LangGraph 是什么LangGraph 是一个基于 Pregel 图计算模型的、有状态的 Agent 编排框架。这句话里有三个关键词关键词含义为什么重要Pregel 图计算模型运行时基于 Google Pregel / BSP 范式天然支持并行、Checkpoint、断点续跑有状态通过 Channel Reducer 管理状态状态不是简单的 dict而是可合并的、可恢复的Agent 编排面向 LLM Agent 的图编排条件边、循环、人机交互、子图嵌套1.3 LangGraph 解决的五个核心问题问题LangGraph 的解法Agent 如何循环图天然支持循环边不需要递归或 while多 Agent 如何并行BSP 模型下同层节点自动并行状态如何管理Channel Reducer读写解耦自动合并执行如何恢复每个 Superstep 自动 Checkpoint人如何介入interrupt_before / interrupt_after Command️ 二、五层架构从 API 到 Checkpoint 的分层设计LangGraph 的源码可以清晰地分为五层每层职责明确层与层之间通过接口解耦2.1 API 层graph/这是用户直接接触的层。StateGraph和MessageGraph是两个核心构建器用户通过它们定义节点、边和状态模式。compile()方法将构建器转化为可执行的CompiledGraph支持invoke()、stream()、ainvoke()等调用方式。关键设计StateGraph 是构建器不是运行时。你不能直接执行一个 StateGraph必须先compile()成 CompiledGraph。这个编译过程会做很多事情——验证图的合法性、生成节点路由表、绑定 Channel 和 Reducer、注入 Checkpointer 等。2.2 Pregel 层pregel/这是 LangGraph 的灵魂。Pregel类是核心运行时引擎它管理 Actor节点函数和 Channel状态通道的执行。PregelLoop_loop.py实现了 BSP 执行循环——每个 Superstep 包含 Compute、Barrier、Write、Checkpoint 四个阶段。关键文件main.pyPregel 主类stream()/invoke()的入口_loop.pyBSP 循环的核心实现_algo.py任务调度算法决定哪些节点在下一个 Superstep 执行_call.py节点函数的调用逻辑_write.py写入 Channel 的逻辑_read.py读取 Channel 的逻辑_checkpoint.pyCheckpoint 保存与恢复_runner.py异步执行器_retry.py失败重试逻辑2.3 Channel 层channels/Channel 是 LangGraph 最精妙的设计之一。它不是简单的状态字典而是一个读写解耦的消息通道——节点写入 Channel 时写入的不是最终值而是一个更新指令Channel 内部的 Reducer 决定如何将更新指令合并为最终状态。七种 Channel 类型Channel 类型行为典型用途LastValue只保留最后一个值新值覆盖旧值当前步骤、最终答案BinaryOperatorAggregate用二元操作符合并所有值消息列表追加operator.add、计数器累加Topic发布-订阅模式值按主题分组多生产者-多消费者场景AnyValue接受任意值不做合并透传、调试EphemeralValue只在当前 Superstep 可见不持久化临时中间结果NamedBarrierValue命名屏障等待所有写入者就绪同步点UntrackedValue写入但不追踪变更不触发下游更新的元数据2.4 Checkpoint 层checkpoint/每个 Superstep 结束后PregelLoop 会将完整的 Channel 状态和待执行任务保存为 Checkpoint。这意味着断点续跑如果执行中断可以从最后一个 Checkpoint 恢复时间旅行可以回溯到任意历史 Checkpoint人机交互interrupt暂停执行用户输入后从 Checkpoint 恢复三种 Checkpoint 实现MemorySaver内存存储开发调试用SqliteSaverSQLite 持久化单机部署用PostgresSaverPostgreSQL 持久化生产环境用2.5 Managed 层managed/Managed Values 是一种特殊的 Channel——它们不是由节点写入的而是由框架自动管理的。比如InjectedState自动注入当前状态、InjectedStore自动注入长期记忆存储。这些值在 Checkpoint 中不保存每次执行时重新生成。 三、StateGraph不是 DAG是带状态的图3.1 为什么不是 DAGDAG有向无环图是大多数工作流框架的基础抽象——Airflow、Prefect、Dagster 都是 DAG。但 DAG 有一个致命的限制不能有环。而 Agent 的核心特征恰恰是循环——LLM 思考 → 调用工具 → 观察结果 → 继续思考这个循环是 Agent 的灵魂。LangGraph 的 StateGraph 打破了这个限制——它允许图中有环也就是允许节点之间形成循环依赖。这不是hack而是设计选择Agent 的执行本质上是一个迭代收敛过程而不是一个线性流水线。3.2 StateGraph 的三要素fromlanggraph.graphimportStateGraph,START,ENDfromtypingimportAnnotatedfromtyping_extensionsimportTypedDictimportoperator# 1. 定义 State带 Reducer 的状态模式classAgentState(TypedDict):messages:Annotated[list,operator.add]# Reducer: 追加而非覆盖next_step:str# LastValue: 覆盖# 2. 定义节点函数defthink(state:AgentState)-dict:# 返回部分状态更新Reducer 自动合并return{messages:[思考中...],next_step:act}defact(state:AgentState)-dict:return{messages:[执行工具调用],next_step:think}# 3. 构建图graphStateGraph(AgentState)graph.add_node(think,think)graph.add_node(act,act)graph.add_edge(START,think)graph.add_conditional_edges(think,lambdas:s[next_step])graph.add_edge(act,think)# 循环边DAG 不允许StateGraph 允许appgraph.compile()# 编译为可执行图resultapp.invoke({messages:[],next_step:think})这段代码展示了 StateGraph 的三个核心要素State状态模式用 TypedDict 定义每个字段可以绑定 Reducer如Annotated[list, operator.add]。没有 Reducer 的字段默认使用 LastValue Channel覆盖。Node节点函数接收当前 State返回部分状态更新。注意节点返回的不是完整 State而是更新指令——只有需要修改的字段。Edge边包括普通边add_edge和条件边add_conditional_edges。条件边根据当前 State 决定路由到哪个节点这是实现 Agent 循环的关键。3.3 compile() 做了什么compile()不是简单的打包——它做了大量工作步骤说明验证图合法性检查是否有孤立节点、是否有不可达节点生成路由表为每个节点计算出边映射——条件边的路由函数编译为查找表绑定 Channel为 State 的每个字段创建对应的 Channel 实例绑定 Reducer将Annotated[type, reducer]中的 reducer 绑定到 Channel注入 Checkpointer如果传入了checkpointer包装每个 Superstep 的保存逻辑生成 CompiledGraph返回一个可执行的对象支持 invoke / stream / ainvoke⚡ 四、PregelLangGraph 的灵魂——BSP 执行模型4.1 什么是 PregelPregel 是 Google 在 2010 年提出的大规模图计算框架核心思想是BSPBulk Synchronous Parallel整体同步并行。在 Pregel 模型中图计算被组织为一系列Superstep超步每个 Superstep 包含三个阶段Compute每个活跃节点并行执行计算Barrier所有节点到达同步屏障Write将计算结果写入 Channel / 发送消息LangGraph 借鉴了这个模型并增加了第四个阶段——Checkpoint。4.2 为什么 LangGraph 选择 Pregel你可能会问Agent 编排又不是大规模图计算为什么要用 Pregel答案在于 Pregel 模型的三个天然优势优势一天然支持并行。在同一个 Superstep 中所有就绪的节点可以并行执行。如果你的 Agent 有搜索和代码生成两个独立步骤它们可以在同一个 Superstep 中并行运行性能直接翻倍。优势二天然支持 Checkpoint。每个 Superstep 结束后所有 Channel 的状态是一致的因为 Barrier 保证了同步。这意味着你可以在每个 Superstep 结束时保存一个完整的 Checkpoint而不用担心状态不一致的问题。优势三天然支持循环。Pregel 的 Superstep 是一个循环——如果当前 Superstep 产生了新的任务就进入下一个 Superstep。这与 Agent 的思考-行动-观察循环完美匹配。4.3 Superstep 的四阶段详解阶段做什么核心文件Compute并行执行所有就绪节点每个节点读取 Channel、返回写入指令_call.py_runner.pyBarrier等待所有节点执行完毕异步场景下是 await_loop.pyWrite将写入指令应用到 ChannelReducer 合并状态更新_write.pychannels/*.pyCheckpoint保存完整快照检查终止条件决定下一个 Superstep 的任务_checkpoint.py_algo.py4.4 终止条件PregelLoop 在以下情况下终止没有新任务当前 Superstep 没有产生任何新的待执行节点达到步数限制recursion_limit默认 25防止无限循环遇到 interruptinterrupt_before/interrupt_after暂停执行节点抛出异常且没有配置重试 五、源码目录结构Python 包的精巧布局langgraph/ ├── graph/ # Layer 1: API 层 │ ├── state.py # StateGraph 构建器 │ ├── message.py # MessageGraph消息专用 │ ├── _node.py # 节点定义与包装 │ ├── _branch.py # 条件边Branch实现 │ └── ui.py # UI 组件 ├── pregel/ # Layer 2: Pregel 运行时 │ ├── main.py # Pregel 主类invoke/stream 入口 │ ├── _loop.py # BSP 循环核心 │ ├── _algo.py # 任务调度算法 │ ├── _call.py # 节点调用逻辑 │ ├── _write.py # Channel 写入逻辑 │ ├── _read.py # Channel 读取逻辑 │ ├── _checkpoint.py # Checkpoint 保存/恢复 │ ├── _runner.py # 异步执行器 │ ├── _retry.py # 失败重试 │ ├── _executor.py # 线程/进程池 │ ├── _validate.py # 图验证 │ ├── _io.py # 输入输出处理 │ ├── _config.py # 运行时配置 │ ├── _messages.py # 消息处理 │ ├── _tools.py # 工具节点 │ ├── _utils.py # 工具函数 │ ├── debug.py # 调试模式 │ ├── protocol.py # 协议定义 │ ├── remote.py # 远程图执行 │ └── types.py # 类型定义 ├── channels/ # Layer 3: Channel 层 │ ├── base.py # Channel 基类 │ ├── last_value.py # LastValue Channel │ ├── binop.py # BinaryOperatorAggregate │ ├── topic.py # Topic Channel │ ├── any_value.py # AnyValue Channel │ ├── ephemeral_value.py # EphemeralValue Channel │ ├── named_barrier_value.py # NamedBarrierValue │ └── untracked_value.py # UntrackedValue ├── checkpoint/ # Layer 4: Checkpoint 层 │ ├── base.py # BaseCheckpointSaver │ ├── memory.py # MemorySaver │ ├── sqlite.py # SqliteSaver │ └── postgres.py # PostgresSaver ├── managed/ # Layer 5: Managed Values │ ├── base.py # ManagedValue 基类 │ └── ... ├── func/ # 函数式 API ├── stream/ # 流式输出 ├── utils/ # 工具函数 ├── types.py # 全局类型定义 ├── constants.py # 常量 ├── config.py # 配置 ├── errors.py # 异常定义 └── runtime.py # 运行时上下文 六、一条消息的完整旅程从 invoke 到输出当你调用app.invoke({messages: [你好]})时背后发生了什么步骤做什么核心文件1. invoke()入口方法将输入包装为初始 Channel 状态graph/state.py2. stream()底层都是 streaminvoke 只是收集所有输出pregel/main.py3. PregelLoop 启动创建初始任务列表START 节点初始化 Channelpregel/_loop.py4. Superstep 1: Compute执行 START → 第一个节点返回写入指令pregel/_call.py5. Superstep 1: Barrier等待节点执行完毕pregel/_loop.py6. Superstep 1: Write将写入指令应用到 ChannelReducer 合并pregel/_write.py7. Superstep 1: Checkpoint保存快照计算下一个 Superstep 的任务pregel/_checkpoint.py8. Superstep 2…N重复步骤 4-7直到没有新任务pregel/_loop.py9. 返回结果从 Channel 中读取最终状态返回给用户pregel/_io.py⚖️ 七、LangGraph vs OpenClaw两种 Agent 工程哲学维度LangGraphOpenClaw语言PythonTypeScript核心抽象Graph图计算Gateway消息网关运行时模型Pregel / BSPAgent Loop双层循环状态管理Channel ReducerSession Memory并行策略Superstep 内天然并行Lane Queue 串行化持久化Checkpoint快照JSONL Session 文件消息通道无纯计算框架25 原生通道工具系统Tool Node函数注册Tool Policy Sandbox设计哲学加法提供丰富的抽象和组合减法框架做到极致的薄适用场景复杂多步骤 Agent 编排个人 AI 助手 / 多平台接入一句话总结LangGraph 是Agent 的操作系统内核——它提供图计算原语让你自由组合OpenClaw 是Agent 的应用框架——它提供完整的网关、通道、技能生态开箱即用。 八、系列预告接下来 3 篇我们将深入 LangGraph 的核心机制篇目核心内容第二篇Channel 与 Reducer——状态管理的七种武器第三篇PregelLoop 深度拆解——BSP 循环的源码级实现第四篇Checkpoint 与人机交互——断点续跑与时间旅行 总结速查卡LangGraph 核心概念概念一句话解释StateGraph带状态的图构建器允许循环边compile() 后可执行Pregel核心运行时基于 Google Pregel / BSP 模型Superstep一次完整的计算-同步-写入-检查点周期Channel读写解耦的状态通道7 种类型覆盖所有场景Reducer状态合并函数如operator.add追加、lambda x,y: y覆盖Checkpoint每个 Superstep 的完整快照支持断点续跑和时间旅行BSPBulk Synchronous Parallel整体同步并行计算模型五层架构速查层职责核心文件API用户接口图构建graph/state.pyPregel运行时引擎BSP 循环pregel/main.py_loop.pyChannel状态通道读写解耦channels/*.pyCheckpoint持久化断点续跑checkpoint/*.pyManaged框架自动管理的值managed/*.py一句话总结LangGraph 的灵魂是 Pregel——它把 Agent 编排问题转化为图计算问题用 BSP 模型实现天然并行、天然 Checkpoint、天然循环。StateGraph 是用户接口Channel 是状态管道Reducer 是合并策略Checkpoint 是安全网。理解了 Pregel你就理解了 LangGraph 为什么能做其他框架做不到的事。参考链接LangGraph GitHub 仓库LangGraph 官方文档LangGraph Pregel 文档A Deep Dive of LangGraph MechanismsLangGraph State Management in Practice