24-LangGraphAPI:节点、边与进阶
24 - LangGraph API:节点、边与进阶
本章课程目标:
- 理解 Node(节点) 的定义、职责与常见写法,知道节点为什么是 LangGraph 的最小执行单元。
- 掌握 Edge(边) 的核心类型:普通边、条件边、入口点、条件入口点,建立“图为什么能按规则流转”的直觉。
- 理解 Send、Command、Runtime 上下文 这三类进阶控制能力分别解决什么问题,知道它们和前面学过的
Graph、State、Reducer是怎么接起来的。 - 能运行并理解本章全部案例,为后续更复杂的 LangGraph 工作流、多智能体和高级特性打基础。
学习建议: 这章可以当成 LangGraph 的“控制流”来读:Node 负责做事,Edge 负责决定去哪,Send / Command / Runtime 处理普通边不够用的场景。先跑明白普通边和条件边,再看动态分发、更新并跳转、运行时上下文。读完后能说清“这一步为什么不是固定下一跳”,就抓住了进阶 API 的用处。
官方文档与资源:详见 工具导航与参考资料索引 - LangGraph。
1、Graph API 之 Node(节点)
1.1 定义
在 LangGraph 里,Node(节点) 可以看作:图中的一个可执行步骤。它通常就是一个 Python 函数,可以是同步函数,也可以是异步函数。图运行时,框架会按边的连接关系,依次或并行地调度这些节点执行。
如果说 第 23 章 重点在讲“图里有哪些共享状态”,那本章开始讲的 Node,重点就在讲:状态到了某一站之后,要做什么处理。
Node 不是图上的装饰点,而是三件事的组合:
- 一段明确的处理逻辑
- 一次对当前 State 的读取
- 一次对 State 的局部更新
LangGraph 官方对 StateGraph 的定义里有一句非常核心的话:节点的签名可以写成 State -> Partial<State>。它的意思是:节点通常读取当前状态,然后只返回它想更新的那部分字段,而不是每次都把整份完整状态重新手写一遍。
1.2 节点的作用
Node 是图真正“干活”的地方。前面学过的 Graph、State、Reducer 更偏结构和机制,而节点负责承载具体业务逻辑。真实项目里,下面这些事情通常都写在节点里:
- 调用大模型
- 调用工具或外部 API
- 做检索、重排、格式化
- 做路由判断前的中间计算
- 记录某一步的结果、状态标记或错误信息
这三层关系可以这样看:
- Graph 负责整体流程结构
- State 负责共享数据
- Node 负责每一步具体做什么
1.3 节点函数一般长什么样
根据官方 Graph API 文档,LangGraph 节点常见可以接收三类参数:
state:图当前这一步看到的共享状态config:本次运行的配置与元数据,类型通常是RunnableConfigruntime:运行时对象,可访问context、store、stream_writer等
最常见的节点先从这一种开始记:
1 | def node(state: MyState) -> dict: |
这也是初学者最该先掌握的形态:读 state,返回局部更新 dict。
当你后面开始做更复杂的工作流时,再慢慢加入:
config:适合放thread_id、tags、metadataruntime:适合放模型名、数据库连接、API 密钥、环境配置这类不属于 State 的依赖

图里这三个词的层次建议这样记:
state是“业务数据”config是“本次运行的配置和追踪信息”runtime是“节点执行时可访问的运行环境能力”
config 和 runtime 这两个参数,通常由 LangGraph 运行时通过关键字方式自动注入。大多数场景里,你不需要手动组装它们;节点函数里是否声明这些参数,表达的是“这个节点需要哪些运行时信息”。
节点输出还有一条基本规则:返回增量更新,不要把接收到的整个 State 原样或修改后整份返回出去。
原因在于:
- LangGraph 会把节点返回值当成“本节点对状态的局部更新”
- 然后再按字段对应的 Reducer 规则,把这些更新合并回全局 State
所以更推荐的写法是:
1 | def node(state: MyState) -> dict: |
而不推荐把整份 state 直接修改后再整体 return。因为那样很容易带来两个问题:
- 没配置特殊 Reducer 的字段,会出现本不该被当前节点改动却被一起覆盖的情况
- 配置了 Reducer 的字段,如果节点把“不属于本节点职责的状态”也一并返回,后续合并结果会更难预测
节点只返回自己负责更新的字段。
从代码习惯上看,下面这种写法要尽量避免:
1 | def query_web(state: MyState) -> dict: |
它看起来省事,但问题是:调用者很难判断这个节点到底负责改哪些字段;如果 State 里有 messages、retrieved_docs 这类带 Reducer 的字段,整份返回还可能导致重复合并或覆盖误伤。
更推荐的写法是:
1 | def query_web(state: MyState) -> dict: |
节点函数内部可以读完整 State,但离开节点时只交出自己的增量更新。 这条规则和上一章的 Reducer 是一体的:节点负责产出更新,Reducer 负责合并更新。
1.4 START、END 与入口出口
在学节点时,经常会一起看到 START 和 END。它们不是你自己写的业务节点,而是 LangGraph 内置的两个特殊虚拟节点:
START表示图的入口END表示图的结束
最常见的写法是:
1 | graph.add_edge(START, "node_a") |
这表示:图从 node_a 开始执行,node_a 执行完后流程结束。
如果图的入口出口很明确,也可以用:
set_entry_point(node_id)set_finish_point(node_id)
它们是更简洁的语法糖,底层还是在帮你建立 START -> node、node -> END 这样的边。
1.5 节点设计建议
入门阶段,节点最容易被写成“什么都往里面塞”。但从真实项目角度看,节点更适合遵守下面几条原则:
- 单一职责:一个节点尽量只做一件事
- 输入输出清楚:看函数签名和返回值,就知道它依赖什么、更新什么
- 少依赖外部可变状态:优先通过 State 或 Runtime 传值,而不是偷偷读全局变量
- 便于重试和缓存:如果节点副作用太重,后面配置缓存或重试时会很难控
你可以先把节点理解成“图里的一个小服务”,而不是“图里的一大坨代码”。
1.6 案例:节点定义方式与 add_node
这个案例是第 24 章最基础、也最值得先跑通的 Node 例子。它主要演示三件事:
- 节点就是 Python 函数
- 节点除了最基本的
state参数,还可以借助partial绑定额外参数 add_node(...)时除了传节点函数,还可以顺手挂上retry_policy
【案例源码】案例与源码-3-LangGraph框架/04-node/DefNode.py
这个案例用来建立一个基础直觉:Node 的重点不是“函数怎么写花哨”,而是“如何被图注册、调度、配置”。
1.7 节点缓存(Node Caching)
节点缓存解决的问题很实际:某个节点很贵、很慢,但相同输入经常重复出现,能不能不要每次都重新跑?
LangGraph 要真正命中缓存,通常要看三层:
- 节点声明缓存策略:例如
CachePolicy(key_func=..., ttl=...)。 - 图编译时选择缓存后端:例如
compile(cache=InMemoryCache())。 - 运行时判断是否命中:按
key_func生成缓存键,再根据ttl判断是否过期。
其中 key_func 决定“什么样的输入算同一次结果”,ttl 决定“这份结果能复用多久”。缓存后端可以是内存、Redis、SQLite 等,具体选型要看项目是否需要跨进程、跨机器或持久保存。
入门阶段先记住:节点声明支持缓存,图编译时选择具体缓存后端。

在真实项目里,缓存很适合这些节点:
- 纯计算节点
- 解析、格式化、清洗类节点
- 成本高但输入重复率高的外部调用节点
不太适合直接粗暴缓存的,则通常是:
- 强依赖实时数据的节点
- 带强副作用的节点
- 输入看起来一样,但实际上上下文不同的节点
1.8 案例:节点缓存
这个案例的学习重点不是记住 ttl=8 这个数字,而是看清楚两件事:
cache_policy=CachePolicy(...)是配置在节点上的compile(cache=InMemoryCache())是在图编译时提供缓存后端
换句话说,节点声明“我支持缓存”,图编译时再决定“实际用什么缓存”。
【案例源码】案例与源码-3-LangGraph框架/04-node/Node_Cache.py
1.9 错误处理与重试机制
重试机制解决的是另一个现实问题:节点失败了,是不是应该立刻整个图报错,还是可以重试一下?
LangGraph 用 RetryPolicy 来描述这件事。官方参考文档里,RetryPolicy 主要包含这些常见参数:
max_attempts:最多尝试执行多少次,包含第一次正式执行。initial_interval:第一次重试前先等多久,通常以秒为单位。backoff_factor:每次重试后,等待时间按多少倍增长,用来做退避。max_interval:单次重试等待时间的上限,避免退避时间无限变长。jitter:是否在等待时间上加入一点随机扰动,降低“同时重试把服务再次打爆”的风险。retry_on:指定哪些异常值得重试;不符合条件的异常会直接抛出,而不是继续重试。
其中最关键的不是把参数全背下来,而是先分清楚两层语义:
- 时间策略:多久重试一次,是否退避,是否加抖动
- 异常策略:哪些异常应该重试,哪些异常不该重试
在真实项目里,建议先分清异常类型:
- 网络抖动、临时超时 这类问题通常适合重试
- 参数错误、类型错误、业务逻辑错误 通常不适合盲目重试
所以 retry_on 的价值是:让重试更像工程策略,而不是“失败了就不加区分地再跑一遍”。
1.10 案例:节点重试
这个案例适合重点观察三种情况:
- 默认重试策略是什么效果
- 自定义
retry_on时,如何只对特定异常重试 - 哪些异常会直接失败,不会进入重试流程
【案例源码】案例与源码-3-LangGraph框架/04-node/Node_ExpErrRetry.py
学完 Node 这一节后,你至少应该建立这个认识:节点不只是“一个函数”,它还是图里的一个可配置执行单元,可以挂缓存、挂重试策略,也可以明确入口和出口。
2、Graph API 之 Edge(边)
2.1 定义
如果说 Node 决定“这一站做什么”,那 Edge(边) 决定的就是:这一站做完之后,下一步去哪里。 边不是装饰性的连线,而是图的流程控制规则。
LangGraph 里最基础的两类边是:
- 普通边(Normal Edge):固定从 A 到 B
- 条件边(Conditional Edge):根据当前状态决定下一步去哪
围绕这两类边,又会延伸出:
- 入口点(Entry Point)
- 条件入口点(Conditional Entry Point)
它们共同回答的都是一个问题:这张图到底怎么流转。
1 | flowchart TD |
图注: 普通边固定走向;条件边用函数选下一跳;入口点决定首次进入哪个节点;条件入口点在首跳前就做路由(适合“一进图先分类”)。
2.2 边的作用
很多人最开始会把注意力都放在节点函数本身,觉得“反正每个节点写好就行”。但从工作流角度看,真正决定图长什么样的,往往是边。
下面这些差别,主要由边来决定:
- 是固定顺序执行,还是动态路由
- 是单入口,还是入口就分流
- 是一条线走到底,还是中间多分支汇聚
- 是普通顺序链,还是更接近小型决策系统
所以可以说:Node 让图有处理能力、Edge 让图有流程结构。
2.3 普通边(Normal Edges)
普通边是最容易理解的一种:执行完当前节点后,无条件进入下一个节点。
最典型的写法就是:
1 | builder.add_edge("node_a", "node_b") |
这行代码的意思很简单:node_a 跑完,就去 node_b,没有判断、没有分支。

图注: 左侧为课件示例代码,右侧为线性拓扑;编译时若边指向未注册的节点会报错。
普通边的学习重点不只是会写 add_edge,而是建立一个直觉:图最基础的形态就是一条固定路径。很多复杂图,都是先从普通边搭出来,再逐步加入条件边、Send、Command。
2.4 案例:普通边
这个案例演示的是最基础的线性图:START -> node_a -> node_b -> node_c -> END
重点不是业务逻辑,而是看清楚:当边是固定的,图就像一条声明式的工作流链。
【案例源码】案例与源码-3-LangGraph框架/05-edge/Edge_Normal.py
2.5 条件边(Conditional Edges)
当流程不是“固定从 A 到 B”,而是“做完 A 后,要根据当前状态决定下一步去哪”,就需要条件边。
LangGraph 常见写法是:
1 | graph.add_conditional_edges("node_a", route_fn, mapping) |
这里可以拆成三部分理解:
"node_a":从哪个节点出发做路由route_fn:根据当前状态返回路由结果mapping:把路由结果映射到具体目标节点
比起 API 形式,更应该先抓住这句:
条件边 = 节点执行完后,再根据当前状态决定下一步去哪。
1 | flowchart LR |
2.6 案例:条件边
这两个案例共同说明一件事:条件边是在图层做路由,而不是把所有判断都塞回节点函数内部。
你可以重点观察:
- 一个案例用布尔值或简单条件做分支
- 另一个案例用字符串 key + mapping 做多分支映射
【案例源码】案例与源码-3-LangGraph框架/05-edge/Edge_Conditional.py、Edge_ConditionalV2.py
2.7 入口点与条件入口点
前面的条件边是在“某个节点执行完之后再分支”,而入口点相关能力解决的是另一个问题:图一开始从哪里进入。
最常见的两种情况是:
- 入口点(Entry Point):图总是从同一个节点开始
- 条件入口点(Conditional Entry Point):图启动时,就要先判断输入,再决定从哪个节点开始
可以这样区分:
- 普通入口点:固定起点
- 条件入口点:动态起点
这一点在真实项目里特别有用,因为很多系统刚接到请求时,就需要先做一级路由。比如:
- 问候语走问候处理
- 告别语走结束处理
- 普通问题走问答流程
2.8 案例:入口点与条件入口点
这两个案例分别对应:
- 用
set_entry_point/set_finish_point指定固定入口出口 - 从
START上直接挂条件边,按初始输入决定进入哪条处理链
【案例源码】案例与源码-3-LangGraph框架/05-edge/Edge_EntryPoint.py、Edge_ConditionalEntryPoint.py
2.9 条件边还能构成循环结构
条件边不只能做分支,也能做循环。
例如:
- 某个节点先做一次判断
- 如果条件满足,就继续走下一个处理节点
- 处理完后再回到前一个判断节点
- 直到某个终止条件满足,再走向
END
这类结构在 LangGraph 里很常见,尤其是:
- Agent 的 ReAct 循环
- “检索不够就继续补检索”的循环
- 多步规划执行里的“继续 / 停止”判断
ReAct 就是最典型的例子:输入进入模型节点,模型可能直接输出,也可能先调用工具;工具结果再回到模型节点,由模型继续判断是否已经可以回答。

这类循环之所以适合 LangGraph,是因为它有几个天然难点:
- 下一步不是固定的,模型可能选择工具,也可能直接回答。
- 工具结果需要回写 State,下一轮模型判断要能读到。
- 循环必须有退出条件,否则会一直“模型想一想、工具查一查、再想一想”。
- 线上项目还要能观察当前跑了几轮、卡在哪一步、是否需要人工介入。
但循环结构有一个隐藏风险:如果终止条件设计得不对,图可能一直循环下去。
LangGraph 为此提供了 recursion_limit 这类保护机制。它的作用就是:给图执行设置一个上限,防止工作流无休止地反复调度。
这里的重点不在于死记默认值,而是把循环当成一种需要设计边界的流程结构:
- 条件边可以形成循环
- 循环结构必须认真设计终止条件,例如“没有工具调用了”“评分达标了”“重试次数达到上限了”
- 真实项目里最好配合
recursion_limit这类步数保护,避免图跑飞 - 一旦触发递归限制,应当把它当成流程设计信号,而不是简单把数字调大了事
2.10 边的选型
学完这一节后,重点不在于背“有几种边”,而在于知道什么时候该选哪一种:
| 场景 | 更适合的做法 | 理解方式 |
|---|---|---|
| 步骤固定,先后顺序明确 | 普通边 | 一条声明式流水线 |
| 某一步之后要按状态分流 | 条件边 | 节点后置路由 |
| 图总是从同一个地方开始 | 入口点 | 固定起点 |
| 图一开始就要先分类再进不同流程 | 条件入口点 | 动态起点 |
常见误区是:一看到判断,就把大量 if/else 全写进节点里。更稳的做法是:节点负责处理,边负责流转。 这样图结构更清楚,也更容易可视化和调试。
3、Send、Command 与 Runtime 上下文
3.1 三类问题
学完 Node 和 Edge 之后,你已经能搭出很多正常的图了。但真实项目里很快会遇到三类更复杂的问题:
- 下一步不是固定一个节点,而是一批动态生成的子任务。
- 某个节点不仅要更新状态,还要决定下一跳。
- 某些配置不属于 State,但节点运行时必须拿得到。
Send、Command、Runtime 分别就是在回答这三类问题。
从这一节开始,我们看的就是普通节点、普通边、条件边之外更灵活的控制原语。
3.2 Send:动态分发
Send 主要解决的问题是:上游节点产出了一批任务,任务数量运行时才知道,而你想把这批任务分发给同一个下游节点分别处理。
这正是典型的 Map-Reduce 思路:
- Map:先把大任务拆成很多小任务
- Reduce:小任务各自完成后,再把结果汇总
LangGraph 里,条件边函数可以返回 Sequence[Send]。每个 Send 都包含两部分:
- 目标节点名
- 要传给该节点的那份状态
Send 允许图在运行时动态决定开出多少条分支,而且每条分支可以拿到不同版本的状态。并行分支写回同一状态字段时,通常要在 State 上配置合适的 Reducer(例如列表追加),否则结果难以汇总。
1 | flowchart LR |
这和普通条件边的区别要分清楚:
- 普通条件边:通常决定“下一步走哪一个节点”
- Send:决定“下一步要开出多少个任务,每个任务分别带什么状态去哪个节点”
3.3 案例:Send
这个案例可以用来理解 LangGraph 的并行思维:
- 上游节点先生成一批主题
- 条件边函数把这些主题映射成一组
Send - 下游节点针对每个主题分别生成笑话
- 最后通过 Reducer 把多路结果合并回 State
【案例源码】案例与源码-3-LangGraph框架/06-specialApi/SendDemo.py
从项目角度看,Send 很适合这些场景:
- 文档分片后并行处理
- 多查询并行检索
- 一批候选任务并行评分
- 多个主题、多条记录、多段文本的批量处理
3.4 Command:更新并跳转
如果说条件边只负责“去哪”,那 Command 解决的是另一个很常见的需求:某个节点在做完判断后,既想更新状态,又想直接决定下一步去哪。
Command 可以把状态更新和控制流放到同一次返回里。
最常见的两个参数是:
update:当前节点希望写回 State 的局部更新内容,仍然会按字段对应的 Reducer 规则合并。goto:当前节点执行完后,希望图下一步跳转到哪个节点;也可以直接跳到END结束流程。
一个节点可以:
- 一边返回新的状态更新
- 一边直接告诉图“下一步去哪个节点”
这和条件边的边界要分清楚:
- 条件边:通常更适合“节点做完了,再单独根据状态决定去哪”
- Command:更适合“这个节点本身就是决策点,离开时把状态和去向一起交代清楚”
1 | flowchart LR |
3.5 案例:Command
这个案例特别适合放在“决策节点”语境下理解。你可以重点观察:
- 为什么
decision_agent返回的不是普通字典,而是Command(...) - 为什么它既能写入
messages、current_agent、task_completed - 又能同时用
goto把流程交给下一个节点,或者直接去END
【案例源码】案例与源码-3-LangGraph框架/06-specialApi/CommandDemo.py
在真实项目里,Command 很适合:
- 决策节点
- Agent 交接节点
- 人机闭环中的“继续 / 暂停 / 转人工”节点
- 需要边写日志边转发流程的节点
这里先埋一个后续伏笔:第 25 章会讲 interrupt。图运行到某个节点时暂停,把待审核数据交给图外用户;用户处理完后,再用 Command(resume=...) 把结果送回图内继续执行。Command 不只表达“下一跳去哪”,也会出现在“暂停后恢复”的人机闭环里。
3.6 Runtime:配置与状态分开
前面我们一直在强调 State,但真实项目里并不是所有数据都该放进 State。比如下面这些东西:模型名、API Key、数据库连接、用户环境配置、当前运行的外部依赖对象。
它们通常都不属于“图在节点间流转的业务状态”,而更像是这次运行的静态上下文。这时就更适合放进 Runtime 上下文,而不是硬塞进 State。
官方 Graph API 和 Use the graph API 指南都强调了这一点:运行时配置可以通过 context_schema 声明,并在调用图时通过 context=... 传入。
所以可以把两者的区别记成:
- State:会随着图运行不断变化的共享业务数据
- Runtime Context:本次运行里节点可读、但不应混入业务状态的静态依赖或配置
1 | flowchart LR |
3.7 Runtime 的基本用法
Runtime 上下文通常分三步:
- 定义
context_schema - 创建图时挂到
StateGraph(..., context_schema=...) - 执行图时通过
invoke(..., context=...)传入,节点里用runtime.context读取
这里的 context_schema 就是一份运行时配置的结构声明。
Runtime 的价值就是把“配置”和“状态”拆开。拆开之后,State 更干净,节点测试更轻松,不同环境、不同模型、不同依赖的切换成本也更低。
3.8 案例:Runtime Context
这个案例重点看三件事:
ContextSchema是怎么定义的StateGraph(..., context_schema=ContextSchema)是怎么把运行时上下文挂到图上的- 节点里怎么通过
runtime.context.xxx读取配置
【案例源码】案例与源码-3-LangGraph框架/06-specialApi/RuntimeContextDemo.py
3.9 图执行时,外部能看到什么
前面讲 Runtime 时提到了 stream_writer。顺着这条线再往外看:图的最终结果,不一定只能等到 invoke() 全部结束后才能拿到。
因为 LangGraph 图本身实现了 Runnable 接口,所以也支持:stream()、astream()。
这意味着你可以在图执行过程中逐步拿到中间信息。常见模式有下面几类:
values:每一步输出当前完整状态updates:每一步只输出增量更新custom:输出节点内部通过runtime.stream_writer(...)主动写出的自定义数据messages:在调用 LLM 的节点中,流式拿到消息片段或 tokendebug:输出更完整的调试信息
真实项目里经常会遇到这些需求:
- 前端希望边跑边展示当前步骤
- LLM 生成时希望 token 级别流式输出
- 长流程执行时,希望知道现在卡在哪个节点
- 调试复杂图时,希望观察每一步到底更新了什么
因此,invoke() 更像“等整张图跑完再拿结果”,stream() 更像“边跑边看图内部发生了什么”。
3.10 Send、Command、Runtime 怎么区分
Send、Command、Runtime 容易混,可以用下面这张表来记:
| 能力 | 它解决的问题 | 理解方式 |
|---|---|---|
| Send | 动态开出多路子任务 | 运行时并行分发 |
| Command | 节点离场时同时更新状态并指定下一跳 | 决策节点的“一次性交代” |
| Runtime | 给节点注入不属于 State 的配置与依赖 | 配置和状态分离 |

- Send:一件事拆成很多小事并行去做
- Command:这个节点现在就决定接下来谁来接手
- Runtime:这次运行需要的环境配置别塞进 State
章节思考题:
一个真实工作流里,怎么判断某段逻辑该放 Node 还是 Edge?
参考思路: 做业务处理、调用模型、检索、转换数据,放 Node;决定下一步去哪,放 Edge 或控制对象。把处理和流转混在一起,图会很快失去可读性。
条件边和
Command都能影响下一跳,它们的区别在哪里?参考思路: 条件边把路由逻辑放在图结构外侧,更适合清晰分支;
Command让节点返回状态更新的同时指定下一跳,更适合节点处理结果本身就决定控制流的场景。选择时看路由逻辑属于图,还是属于节点结果。Send适合解决什么问题?什么时候不该用?参考思路: 它适合运行时动态拆出多路子任务,比如对多个文档、多个查询并行处理。如果任务数量固定、顺序明确,用普通边或并行结构可能更清楚。
Runtime Context 为什么不应该塞进 State?
参考思路: Runtime 放配置、依赖和执行环境,比如客户端、用户上下文、模型参数;State 放业务流转数据。混在一起会导致状态不可序列化、难恢复,也让业务数据和运行环境耦合。
为什么循环图需要设计退出条件和步数保护?
参考思路: Agent / ReAct / 自我修正流程天然可能反复执行,如果没有清晰退出条件,图会一直调度下去。
recursion_limit是最后一道保护,但真正可靠的设计还要在 State 中记录重试次数、评分结果或工具调用状态,让条件边能稳定走向END。
本章小结:
- Node 是 LangGraph 的最小执行单元,可以理解为被图调度的 Python 函数;除了最常见的
state -> dict形式,还可以结合缓存、重试策略、config、runtime使用。 - Edge 决定流程怎么流转。普通边适合固定路径,条件边适合状态驱动分支,入口点和条件入口点则决定图从哪里开始。
- Send、Command、Runtime 是三种常用进阶能力:Send 适合动态并行分发,Command 适合决策节点,Runtime 适合把配置和状态拆开。
- 这一章的重点在于建立一个完整认知:节点负责处理,边负责流转,State 负责共享数据,进阶控制原语负责让图在运行时更灵活。 学完本章后,你应当能够分清 Node 和 Edge 的职责,知道普通边、条件边、入口点、条件入口点分别适合什么场景,并理解
Send、Command、Runtime三个进阶能力各自解决什么问题。
建议下一步:
建议先按顺序跑一遍 04-node、05-edge、06-specialApi 目录下全部案例,再进入后续 LangGraph 进阶章节。如果你能自己把一个“分类 → 分流 → 并行处理 → 汇总回答”的小工作流手写出来,这一章就真正学会了。