ARTICLE · 1161344
【LangGraph 源码精读】第 00 期|用了半年 LangGraph,90% 的人连架构都没搞懂!
用了半年LangGraph,90%的人连它的架构都没搞懂:6层架构、8大包、一次invoke的完整链路(30篇源码精读·全局地图)
30篇源码精读系列·第00篇(全局地图)。你用LangGraph做了好几个项目,能熟练写State、加Node、连Edge。但如果面试官问你:LangGraph内部有几层架构?一次invoke从输入到输出经过了多少步?Checkpoint到底存了什么?并行执行为什么不会数据冲突?很多人答不上来。会用和懂架构是两回事。这篇是全局地图,先把架构搞清楚,后面30篇源码精读逐个区域深挖。
一、开头:会用LangGraph,和懂LangGraph架构,是两回事
很多人用LangGraph做了好几个项目,能熟练地写State、加Node、连Edge、配Checkpoint,跑通了ReAct Agent、多Agent协作、人机交互。
但如果问你这几个问题,你能答上来吗?
- ● LangGraph内部有几层架构?每层负责什么?
- ● 一次app.invoke()从输入到输出,完整经过了多少步?
- ● Checkpoint到底存了什么?6个字段分别是什么?
- ● 两个节点并行执行,为什么状态更新不会冲突?
- ● prebuilt包为什么不依赖langgraph核心?反过来依赖不会循环吗?
- ● LangGraph的执行引擎为什么叫Pregel?和Google的Pregel论文有什么关系?
很多人答不上来。会用API和懂底层架构是两回事。 懂架构才能在遇到诡异bug时定位根因,才能做深度定制,才能在面试时讲清楚"为什么"而不只是"怎么用"。
这篇是30篇LangGraph源码精读系列的第00篇——全局地图。在逐行啃源码之前,先把整体架构搞清楚。后面30篇就是在这张地图上逐个区域深挖。
二、LangGraph在LangChain生态中的位置
LangGraph不是孤立的框架,它是LangChain生态中的"编排层"。搞清楚它在生态中的位置,才能理解它为什么这样设计。
| LangGraph | 有状态图运行时,Agent的编排和执行引擎 | ||
一句话:LangChain负责"和模型对话",LangGraph负责"让Agent跑起来"。
为什么这样分层? 因为"和模型对话"和"让Agent跑起来"是两个完全不同的问题。模型对话需要处理Prompt、Token、工具调用格式;Agent运行需要处理状态、循环、持久化、并发。LangChain早期把两者混在一起,导致Agent能力弱、不可控。LangGraph独立出来,专注做"运行时",这是它能成为Agent编排标准的关键原因。
面试关联: 面试官问"LangGraph和LangChain什么关系",不要只说"LangGraph是LangChain的一部分"。要说清"LangChain是模型层,LangGraph是编排层,两者解决不同问题,LangGraph依赖LangChain的消息类型但运行时是独立的"——这才是有深度的回答。
三、6层架构总览
LangGraph内部可以清晰地分为6层,从下到上依次是:
| 用户API层 | ||||
| 编译层 | ||||
| 执行引擎层 | ||||
| 持久化层 | ||||
| 传输层 | ||||
| 基础设施层 |
依赖方向:上层依赖下层,下层不依赖上层。 这是经典的分层架构设计——上层可以调用下层的接口,下层不知道上层的存在。这样做的好处是:每一层可以独立替换、独立测试、独立演进。比如你可以不用StateGraph(第6层),直接用Pregel(第4层);也可以不用PostgresSaver,自己实现一个CheckpointSaver。
执行引擎层(第4层)是核心中的核心。 其他层都围绕它服务:用户API层是它的入口,编译层把图编译成它能执行的格式,持久化层保存它的状态,传输层输出它的执行过程,基础设施层提供并发和重试。搞懂了执行引擎层,就搞懂了LangGraph的70%。
面试关联: "LangGraph的架构分几层?"这道题的标准答案就是这6层。重点讲清第4层执行引擎是核心,以及为什么要分层(可替换、可测试、可演进)。
四、8大包结构与职责
LangGraph是一个Monorepo(单体仓库),包含8个独立可安装的Python包。每个包有自己的版本号和依赖管理。
| langgraph | ||||
| langgraph-checkpoint | ||||
| langgraph-checkpoint-postgres | ||||
| langgraph-checkpoint-sqlite | ||||
| langgraph-prebuilt | ||||
| langgraph-sdk | ||||
| langgraph-cli | ||||
| scheduler-kafka |
最巧妙的设计:prebuilt包不依赖langgraph核心,而是langgraph核心依赖prebuilt。
这看起来反直觉——预构建组件(如create_react_agent)应该依赖核心才对,为什么反过来?
原因:避免循环依赖。 create_react_agent内部需要用到StateGraph来构建图,如果prebuilt依赖langgraph核心,而langgraph核心在某些地方又需要引用prebuilt的组件(比如在编译时自动注入ToolNode),就会形成循环依赖:prebuilt → langgraph → prebuilt。
解决方案:prebuilt只依赖底层的checkpoint接口和langchain-core,不依赖langgraph核心。 create_react_agent需要的StateGraph,通过"依赖注入"的方式传入,而不是直接import。langgraph核心在需要使用prebuilt组件时,直接import prebuilt(因为prebuilt不依赖langgraph,所以不会循环)。
这就是经典的"依赖倒置原则"——高层模块不依赖低层模块,两者都依赖抽象。prebuilt和langgraph核心都依赖checkpoint这个抽象接口,而不是互相依赖。
面试关联: "LangGraph的Monorepo有几个包?prebuilt为什么不依赖核心?"这道题能答上来,说明你真的读过源码,而不只是用过API。重点讲清"避免循环依赖"和"依赖倒置原则"。
五、核心执行引擎:Pregel BSP三阶段模型
Pregel执行引擎是LangGraph的心脏,基于Google Pregel论文的BSP(批量同步并行)模型。这是LangGraph区别于其他Agent框架的最核心设计。
5.1 三个核心概念
| Channel | ||
| PregelNode | ||
| Super-step |
5.2 Super-step三阶段
每个Super-step分为三个阶段,严格按顺序执行,阶段之间有同步屏障:
| Plan(计划) | |||
| Execute(执行) | |||
| Update(更新) |
最关键的设计:Execute阶段节点之间完全隔离。
每个节点拿到的是Super-step开始时的状态快照(不是引用),节点执行期间修改的是本地副本,其他节点完全看不到。节点的输出先缓冲起来,不立即写入全局状态。只有所有节点都执行完后,才在Update阶段按确定的顺序统一合并。
为什么要这样设计?因为这是并行安全的唯一保证。 如果节点执行期间可以直接修改全局状态,两个节点同时修改同一个字段就会产生数据竞争,结果不可预测。而"状态副本+确定序合并"保证了:同样的输入,永远产生同样的输出,结果100%可复现。
代价是什么? 节点在Execute阶段看不到其他节点的更新。如果两个节点有数据依赖(B需要A的输出),它们不能在同一个Super-step执行,必须分两个Super-step(A先执行,下一个Super-step B再执行)。这就是为什么顺序图的每个节点对应一个Super-step。
面试关联: "LangGraph的并行执行为什么不会数据冲突?"这是高频面试题。标准答案就是"状态副本+确定序合并"——Execute阶段每个节点有独立副本,Update阶段按确定顺序合并。能讲清这个,说明你真的懂Pregel模型。
六、一次invoke的完整链路(从输入到输出)
以最简单的顺序图 START -> A -> B -> END 为例,追踪一次app.invoke(input)的完整执行过程。这12步是理解LangGraph执行流程的关键。
关键点:每个Super-step结束都有一个Checkpoint。 对于顺序图,每个节点对应一个Super-step,所以有多少个节点就有多少个Checkpoint(加上初始Checkpoint)。这就是时间旅行的基础——你可以回到任意一个Checkpoint重新执行。
执行终止的判断条件是什么? 不是"到达END节点",而是"没有待执行节点且所有Channel版本无变化"。END本质上是一个"不订阅任何Channel的虚拟节点",到达END意味着没有新的Channel更新,自然就没有待执行节点,执行终止。
面试关联: "一次invoke的完整流程是什么?"这道题考察你对执行流程的整体理解。能讲清12步(特别是Super-step的Plan/Execute/Update三阶段和Checkpoint的创建时机),说明你对LangGraph的执行流程有深入理解。
七、Channel系统:状态的底层存储
Channel是LangGraph中最核心但也最容易被忽略的概念。你在State里定义的每个字段,底层都对应一个Channel。不理解Channel,就不可能真正理解LangGraph。
| LastValue | |||
| BinaryTreeAggregate | |||
| Topic | |||
| DeltaChannel(beta) |
Channel的4个核心职责:
- 1. 存储当前值
- 2. 接收更新,根据reducer合并
- 3. 管理版本号(每次更新版本+1)
- 4. 支持序列化和反序列化(用于Checkpoint)
版本号是整个执行引擎的"心跳"。 每个Super-step结束后,Pregel检查所有Channel的版本号——如果没有任何Channel的版本号变化,说明没有新的更新,执行终止。版本号还用于判断节点是否需要重新执行(versions_seen记录每个节点看到的Channel版本,如果节点看到的版本和当前版本不一致,说明该节点需要重新执行)。
为什么用Channel而不是直接用字典? 因为字典不支持:并行安全(并发写冲突)、版本管理(无法知道谁更新了)、增量更新(只能整体替换)、序列化(需要手动处理)、时间旅行(无法回溯历史)。Channel系统是LangGraph支持并行执行、Checkpoint、时间旅行的基础,没有Channel,这些功能都实现不了。
面试关联: "LangGraph的State和Channel是什么关系?"标准答案:"State是用户层面的状态定义,每个State字段底层对应一个Channel。Channel负责存储值、管理版本号、处理reducer合并、支持序列化。Channel是LangGraph支持并行执行和Checkpoint的基础。"
八、Checkpoint系统:持久化的四大能力
Checkpoint是LangGraph区别于其他Agent框架的核心特性。一个Checkpoint就是状态在某个Super-step边界的完整快照。没有Checkpoint,就没有持久执行、人机交互、时间旅行。
8.1 Checkpoint数据结构(6个字段)
8.2 Checkpoint赋予的四大能力
| 持久执行 | |||
| 人机交互 | |||
| 时间旅行 | |||
| 部分失败恢复 |
最容易搞错的点:Super-step是持久化的最小单位,不是节点。
一个Super-step中所有并行节点都执行完后才创建Checkpoint。如果其中一个节点失败,这个Super-step没有Checkpoint,恢复时整个Super-step重新执行。这就是为什么"节点必须幂等"——因为节点可能被重新执行。
很多人以为"每个节点执行完就保存Checkpoint",这是错的。对于顺序图(一个Super-step只有一个节点),看起来像是每个节点一个Checkpoint,但对于并行图(一个Super-step有多个节点),是所有节点都执行完才保存一个Checkpoint。
面试关联: "Checkpoint存了什么?中断恢复后从哪里继续?"这是高频题。标准答案:Checkpoint存6个字段(channel_values/channel_versions/versions_seen/tasks/parent_config/metadata);中断恢复后整个节点重新执行(不是从断点继续),因为Super-step是持久化最小单位,节点必须幂等。
九、30篇源码精读与架构模块对应关系
这篇是全局地图,后面30篇源码精读在这张地图上逐个区域深挖。以下是30篇与架构模块的对应关系:
| 执行引擎层 | |||
| 用户API层+编译层 | |||
| 持久化层(Checkpoint) | |||
| 高级功能 | |||
| 预构建组件 | |||
| Store+分布式 | |||
| 设计哲学与总结 | |||
| 合计 | 30篇 |
阅读顺序建议: 先读执行引擎层(01-06),这是核心;再读持久化层(12-17),这是LangGraph最有差异化的部分;然后读用户API层和高级功能;最后读设计哲学。不建议按编号顺序从01读到30,因为预构建组件(23-25)依赖对执行引擎的理解。
十、这张架构图能帮你答哪些面试题
整理了LangGraph架构相关的10道高频面试题,每道题在这篇架构图中都能找到答案:
这10道题能答上来,LangGraph架构层面的面试就稳了。 后面30篇源码精读会把每道题的答案深入到源码层面。
十一、本期小结
LangGraph架构全景,核心就6句话:
- 1. LangGraph是LangChain生态的"编排层",LangChain负责和模型对话,LangGraph负责让Agent跑起来。它构建在LangChain的消息类型和Runnable协议之上,Deep Agents等高层框架构建在LangGraph之上。两者分层是因为"模型对话"和"Agent运行"是两个不同问题。
- 2. 内部6层架构:用户API层→编译层→执行引擎层→持久化层→传输层→基础设施层。 上层依赖下层,下层不依赖上层,每层可独立替换和测试。执行引擎层(第4层)是核心中的核心,其他层都围绕它服务。搞懂执行引擎层就搞懂了LangGraph的70%。
- 3. Monorepo包含8个独立包,最巧妙的设计是prebuilt不依赖langgraph核心,而是langgraph核心依赖prebuilt——这是为了避免循环依赖,体现了依赖倒置原则:两者都依赖checkpoint抽象接口,而不是互相依赖。
- 4. Pregel BSP三阶段模型是心脏:Plan→Execute→Update。 Plan确定待执行节点,Execute并行执行(每个节点有独立状态副本,互不影响),Update按确定序合并更新(无数据竞争、结果可复现)。"状态副本+确定序合并"是并行安全的关键,也是LangGraph最核心的设计。
- 5. 一次invoke经过12步,每个Super-step结束创建一个Checkpoint。执行终止的条件是"没有待执行节点且所有Channel版本无变化",不是"到达END"。Channel版本号是整个执行引擎的"心跳"。
- 6. Checkpoint赋予四大能力:持久执行、人机交互、时间旅行、部分失败恢复。 Checkpoint包含6个字段,Super-step是持久化的最小单位(不是节点),所以中断恢复后整个节点重新执行,节点必须幂等。
十二、下一期预告
下一期(源码01),执行引擎层第一篇,也是30篇中最核心的一篇:
LangGraph源码精读01:用了半年LangGraph,你知道它的心脏是Google的Pregel吗?BSP模型、Super-step三阶段、从论文到实现逐段讲解
全局地图已经画好,从下一期开始逐个区域深挖。第一站就是心脏——Pregel执行引擎。
你觉得LangGraph最复杂的模块是哪个?评论区聊聊,我优先写你最关心的。
本文为《LangGraph源码精读30篇》系列第00篇(全局地图)。内容基于LangGraph v1.2.11源码结构梳理,版本更新后部分细节可能变化。如有错漏欢迎指正。