LangGraph 从入门到实战
如果说 LangChain 更像快速搭 Agent 能力的高层框架,那么 LangGraph 更像把复杂 Agent 系统“管起来、编排起来、跑稳定”的底层工作流框架。这一篇会从最基础的状态图直觉讲起,带你逐步理解线程、检查点、人工介入、可恢复执行这些真正工程化的概念。
先别急着记 API,先建立 LangGraph 的直觉。
如果说 LangChain 更像“把模型能力快速拼起来”的高层框架,那么 LangGraph 更像“把复杂流程管起来”的状态图框架。它最重要的价值不是多一个类库,而是把状态、节点、边、线程、检查点、可恢复执行、人工介入这些工程化能力纳入同一套运行模型。 你可以先把它想成:给 AI 应用画流程图,但这张流程图不是 PPT,而是真的可以跑、可以停、可以继续、可以回放、可以插人进去处理。
图 1:LangGraph 最适合解决的问题 任务不止一步:规划、执行、校验、修正 ↓ 中途可能失败、等待、被人工拦下 ↓ 后面还要基于旧状态继续往下跑 ↓ 这时就不再是“简单链式调用”,而是图式编排 一句最实用的话 当你的 AI 应用开始出现“要不要分支”“中断后怎么恢复”“人工审核后怎么继续”“同一个任务怎么带着状态跑很多步”这些问题时,LangGraph 才真正开始变得有价值。
02. 为什么有了 LangChain 还要 LangGraph
这个问题几乎每个初学者都会问,而且必须讲透。不然你会觉得自己在学两个差不多的东西。其实它们不是替代关系,更像上下层关系。
| 问题 | LangChain 更擅长 | LangGraph 更擅长 |
|---|---|---|
| 快速接模型和工具 | 是 | 可以,但不是重点 |
| 快速做一个单链路 Agent | 是 | 可以,但更底层 |
| 复杂分支流程控制 | 一般 | 强项 |
| 中断后恢复继续 | 依赖更底层配合 | 强项 |
| 人工审批 / 人工修改后继续 | 不自然 | 强项 |
| 长时带状态运行 | 有压力 | 强项 |
2.1 什么时候你已经开始“需要图”了
- 任务不是一步完成,而是多步协作完成。
- 不同条件下要走不同分支。
- 一个节点失败后不能简单整体重来。
- 流程中间要停住,等人点确认。
- 你开始在代码里堆越来越多的 if else 和状态变量。
适合只用 LangChain 的场景
Prompt → Model → Parser 这类单主链场景,偶尔加个 Tool 或 Retriever,通常没必要一开始就上图。
适合进入 LangGraph 的场景
审批、计划执行、循环修正、长流程恢复、人工介入、多节点协作,这些都是 LangGraph 的主场。
03. State / Node / Edge 一次搞懂
LangGraph 真正的核心不是某个 API 名字,而是几个概念:State、Node、Edge。只要这三个想清楚,后面的图就不会乱。
| 概念 | 你可以怎么理解 | 它在图里扮演什么角色 |
|---|---|---|
| State | 任务当前携带的全部上下文 | 图在流转时不断被读写的“任务背包” |
| Node | 做一件具体事的步骤 | 读取状态,产出状态更新 |
| Edge | 从一个步骤走向下一个步骤的规则 | 决定流程往哪走 |
| START / END | 图的开始和结束 | 让一条执行链有明确起点和终点 |
| Thread | 同一条任务的执行身份 | 让系统知道“这次恢复的是哪条任务” |
| Checkpoint | 某个时刻的状态快照 | 用于暂停、恢复、回溯 |
图 2:把 LangGraph 看成“带状态的流程图”
State:任务背包 → Node:做一步事 → Edge:决定下一步去哪 → Checkpoint:关键时刻可暂停、可恢复
3.1 State 为什么是第一主角
很多人学 LangGraph 时只看节点函数,结果越写越乱。真正决定图是否清晰的,往往不是节点数量,而是状态设计得好不好。因为节点只是“处理状态”,而状态才是整条任务真正携带的信息。
| 状态里可能放什么 | 示例 |
|---|---|
| 用户输入 | 原始问题、工单内容、上传文件摘要 |
| 阶段结果 | 分类结果、检索结果、工具返回、审核意见 |
| 控制信息 | 当前步骤、重试次数、是否通过审批、是否结束 |
| 日志信息 | 执行痕迹、节点耗时、错误原因 |
初学者最容易踩的坑。
状态不是越多越好。把什么都往 state 里塞,图会越来越重、越来越难懂。状态应该服务于“流程往下走需要知道什么”,而不是把所有中间对象都长期背着跑。
04. 第一个最小图
先看一个非常小的例子,不追求业务复杂,只追求把图的基本骨架看清楚。
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class MyState(TypedDict):
question: str
answer: str
def draft_answer(state: MyState):
return {"answer": f"你问的是:{state['question']}"}
builder = StateGraph(MyState)
builder.add_node("draft", draft_answer)
builder.add_edge(START, "draft")
builder.add_edge("draft", END)
graph = builder.compile()
result = graph.invoke({"question": "什么是 LangGraph?"})
print(result)4.1 这段代码逐行在做什么
| 代码部分 | 作用 |
|---|---|
| MyState | 声明这条任务会携带哪些状态字段 |
| draft_answer | 定义一个节点:吃入状态,返回状态更新 |
| StateGraph(MyState) | 告诉 LangGraph:我要构建一张以这个状态结构为核心的图 |
| add_node | 把具体节点注册进图 |
| add_edge | 规定执行顺序 |
| compile() | 把这张图编译成可运行对象 |
| invoke() | 真正运行一次图 |
4.2 为什么这个例子很重要
因为它把 LangGraph 的最小骨架暴露得非常清楚:先有状态,再有节点,再有边,最后编译和执行。你以后写复杂图,骨架也还是这个骨架,只是节点更多、边更复杂、状态更丰富。
05. 常见编排模式
学框架不能只看 API,真正有用的是模式。下面这些模式,是 LangGraph 场景里最常见、最值得掌握的。
5.1 Router 模式:先分类,再走不同分支
| 适合什么场景 | 例子 | 关键状态 |
|---|---|---|
| 同一入口,不同问题走不同处理链 | 售后、退款、物流、咨询分流 | intent / route |
用户请求 → 意图识别节点 → 不同业务分支 → 统一收口
5.2 Loop 模式:做一轮,不满意就再来一轮
| 适合什么场景 | 例子 | 关键状态 |
|---|---|---|
| 需要迭代修正 | 计划-执行-检查-修正 | attempt、score、max_rounds |
Loop 很常见,但也很危险。因为只要退出条件没写清,就可能无限循环。所以状态里通常要带 max_rounds、当前轮次、是否达标这类控制字段。
5.3 Plan-Execute-Review 模式
| 步骤 | 作用 |
|---|---|
| Plan | 先把任务拆成计划 |
| Execute | 按计划执行,每一步可能调用工具 |
| Review | 检查结果是否合格,不合格再补救 |
5.4 Human Review 模式
当流程中有高风险动作,比如退款、发公告、删数据、审批工单时,经常不是让 Agent 自己一把梭,而是生成建议后交给人确认。这时 LangGraph 的 interrupt / resume 模式就特别有价值。
06. 持久化、线程与记忆
LangGraph 真正和“普通流程脚本”拉开差距的地方,就是持久化。因为图不是一次性跑完就算了,它可能跑到一半停住,过几分钟、几小时甚至几天之后再继续。这就要求系统不仅记得“执行到哪了”,还得记得“当时的状态是什么”。
| 概念 | 你可以怎么理解 |
|---|---|
| Thread | 同一条任务的身份标识,相当于“这一摊事是谁的” |
| Checkpoint | 这条任务某一时刻的状态快照 |
| Resume | 下次从上次停住的地方继续跑 |
图 3:为什么要有 checkpoint 任务跑到第 3 步 ↓ 等待人工审核,先停住 ↓ 系统把当前状态保存成 checkpoint ↓ 审核通过后,从原位置继续跑,而不是整条重来
6.1 这和 LangChain 里的“memory”有什么不同
LangChain 更偏“应用运行时如何组织上下文”;LangGraph 这里讲的持久化,更偏“工作流执行到哪一步、状态怎么保存、以后怎么继续”。前者更接近对话和上下文,后者更接近流程编排和工程状态。
测试视角提醒。
只要系统支持恢复继续,你就要补测:恢复后是不是从正确节点继续、恢复时状态有没有丢、恢复后会不会重复执行已经执行过的动作。
07. interrupt 与人工介入
这是 LangGraph 很有辨识度的能力。很多真实业务场景都不能“让 Agent 自己做完所有决定”,而是做到某一步时停住,把当前结果交给人看,人确认后再继续。interrupt 的意义就在这里。
7.1 一个很典型的审批场景
用户提交退款申请 → Agent 生成建议处理意见 → 人工审核节点 interrupt → 审核通过后继续执行退款动作
7.2 为什么人工介入不是“框架不够智能”
恰恰相反,它说明你开始按真实业务规则设计系统了。现实世界里很多动作本来就不该全自动:权限审批、金额确认、对外发送、风险控制、法律合规,这些都需要人兜底。
# 伪代码:思路示意,不是完整可运行示例
if need_human_review:
interrupt({
"reason": "高风险动作需要人工审核",
"draft": current_result,
})
# 人审核后,系统再 resume 继续往下走7.3 interrupt 场景的测试重点
人工介入测试清单
- 该停的时候有没有真的停住。
- 停住时带给人工看的信息是否足够。
- 人工修改了状态后,后续节点是否正确读取。
- 恢复后会不会重复执行上一步动作。
- 人工拒绝时,流程是否能优雅收口。
08. 典型业务场景
下面挑几个非常典型的业务场景,你可以感受一下 LangGraph 为什么在这些地方比普通链式调用更顺手。
8.1 场景一:多阶段客服助手
| 阶段 | 节点示例 | 为什么像图 |
|---|---|---|
| 意图识别 | router | 不同问题分流到不同链 |
| 资料收集 | follow_up | 字段不全时要循环追问 |
| 处理建议 | draft_solution | 需要生成建议而不是直接执行 |
| 人工审核 | review | 高风险单必须人工确认 |
8.2 场景二:报告生成与复核
先搜集资料,再生成草稿,再校验格式,再让人看一眼。任何一步不过关都可能回退重试。这就是很典型的 plan-execute-review 图。
8.3 场景三:工具链较长的 Agent
比如“查库存 → 算运费 → 判断是否满足活动 → 生成推荐话术”,每一步都有自己的输入输出,还可能有失败重试和人工确认。此时状态图比一长串 if else 更清晰。
LangGraph 在这些场景里的价值
不只是“能跑”,而是“更容易看清流程、保存状态、恢复执行、插入人工、分层测试”。
测试同学能得到什么
更明确的节点边界、更清楚的状态快照、更容易做分支覆盖和恢复测试。
09. 常见坑与设计建议
| 常见坑 | 为什么会出事 | 建议 |
|---|---|---|
| 状态设计太胖 | 每个节点都在读写一大坨状态,越来越难维护 | 只保留流程推进真正需要的信息 |
| 没有明确终止条件 | 循环分支很容易跑飞 | 用 max_rounds、status、done 标志收口 |
| 节点副作用过重 | 恢复执行时可能重复发消息、重复下单 | 关键动作做幂等设计 |
| 人工介入信息不全 | 人不知道该怎么判断 | 停住时把理由、上下文、候选动作一起给出来 |
| 只测 happy path | 真正难点都在分支、中断、恢复 | 按节点和分支逐层补测试 |
一句非常现实的提醒。
LangGraph 不是让你把一切都图化,而是当“流程复杂度已经客观存在”时,给你一套更可控的组织方式。为了用图而上图,最后只会增加维护成本。
10. 它如何和 LangChain 配合
学到这里,你应该把二者关系重新理顺了:LangChain 更像“节点里的能力积木”,LangGraph 更像“节点之间的流程编排器”。
| 层次 | LangChain 往往负责 | LangGraph 往往负责 |
|---|---|---|
| 节点内部 | Prompt、Model、Tool、Parser、Retriever | 通常不管这么细 |
| 节点之间 | 简单串联可以做 | 复杂状态流转和分支控制是强项 |
| 运行时控制 | 基础执行 | 线程、检查点、中断恢复、人工介入 |
图 4:一个典型配合方式 LangGraph 节点 A:调用 LangChain 做分类 ↓ LangGraph 节点 B:调用 LangChain 的 Retriever 做检索 ↓ LangGraph 节点 C:调用 LangChain Tool 执行业务动作 ↓ LangGraph 负责整个任务何时停、何时转、何时恢复
11. 设计一个真实工作流
前面我们讲了概念和模式,这里把它落到一个真实一点的业务场景:售后工单处理流。这个场景很适合教学,因为它天然带分支、带状态、带人工审核、带恢复继续。
| 阶段 | 节点 | 状态里至少要有什么 |
|---|---|---|
| 问题进入 | receive_ticket | ticket_id、user_input、attachments |
| 意图路由 | route_ticket | intent、priority |
| 补资料 | collect_missing_info | missing_fields、retry_count |
| 处理建议 | draft_solution | proposal、confidence |
| 人工审核 | human_review | review_status、review_comment |
| 执行动作 | execute_action | action_result、done |
图 5:一个很典型的 LangGraph 业务流
收单 → 分类分流 → 补资料或给建议 → 人工审核 / 自动执行 / 结束
11.1 设计工作流时最先问的 4 个问题
- 这条任务真正的开始和结束是什么?
- 中间有哪些必须分支的条件?
- 哪些节点有副作用,不能重复执行?
- 哪些地方必须支持人工介入或恢复继续?
11.2 为什么这个场景用 LangGraph 比 if else 更稳
因为这类流程最麻烦的地方,不是“顺着跑一遍”,而是补资料、重试、审核打回、恢复继续、错误回收这些边边角角。用图来思考,会让这些分支和状态边界更清楚。
12. 测试与排障怎么做
LangGraph 这种带状态的图,测试方法和普通接口页不完全一样。最值钱的测试,往往不是 happy path,而是:分支有没有走对、恢复有没有从正确位置继续、人工介入后状态有没有被正确读写。
12.1 最适合 LangGraph 的测试维度
| 维度 | 要测什么 |
|---|---|
| 节点测试 | 单个节点吃入状态后,是否产生正确状态更新 |
| 边测试 | 同一状态在不同条件下是否走对分支 |
| 恢复测试 | checkpoint 后 resume 是否从正确位置继续 |
| 人工介入测试 | 人工修改状态后,后续节点是否正确使用 |
| 幂等测试 | 副作用节点重复执行时是否会出事故 |
12.2 一套很实用的排障顺序
- 先确认当前 thread 是不是你以为的那条任务。
- 再看最近一个 checkpoint 里的 state 到底长什么样。
- 确认当前节点读到了哪些字段,缺了哪些字段。
- 看边的条件判断是不是和设计一致。
- 最后才看模型或 Tool 本身是不是出错。
一句经验。
很多“图跑错了”的问题,根因不是模型,而是状态设计不清、条件分支不清、恢复点不清。LangGraph 项目里,状态就是第一调试对象。
12.3 适合新手照着写的回归模板
测试对象:售后工单 LangGraph 工作流
范围:router / collect_missing_info / draft_solution / human_review / execute_action
核心关注:
1. 不同 intent 是否走对分支
2. 缺字段时是否进入补资料循环
3. human_review interrupt 后是否能正确 resume
4. execute_action 是否具备幂等保护
5. 打回后是否回到正确节点而不是整图重跑13. 练习题与自查
这一页最怕“概念听着懂,真让你画图就不会”。下面这些题,适合你自己答,也适合带新人时用。
| 问题 | 你至少要答到什么程度 |
|---|---|
| State 和普通函数参数有什么不同? | State 是整条任务共享的上下文,不是某一步的临时局部变量 |
| 为什么 checkpoint 很关键? | 因为长流程可能要暂停、恢复、回放,不能每次从头重来 |
| interrupt 的价值是什么? | 让人工可以在高风险节点插入决策,而不是强行全自动 |
| 为什么副作用节点要做幂等? | 因为恢复或重试时可能再次执行,不能重复发消息、重复下单 |
本页自测标准
- 你能不能自己画出一个“分类 → 分支 → 人审 → 执行”的最小图。
- 你能不能说清 thread、checkpoint、resume 三者关系。
- 你能不能说明为什么 LangGraph 比一长串 if else 更适合复杂流程。
- 你能不能给出 3 条和恢复执行有关的测试点。
14. 学习顺序与官方资料
LangGraph 不适合“空学”。最稳的学习顺序,是先把 LangChain 的单链路积木玩明白,再用 LangGraph 去解决真正复杂的状态图问题。
先学什么
先把 LangChain 的 Prompt、Tool、RAG、Structured Output 理顺。
再学什么
再上 LangGraph,重点盯 State、Node、Edge、Thread、Checkpoint。
怎么练最有效
挑一个真实流程:比如“分类 → 检索 → 生成人工审核草稿 → 审核通过后执行动作”。 学完本页,你至少应该能回答这些问题
- 为什么 LangGraph 不是“另一个 LangChain”。
- State、Node、Edge 各自是什么。
- 为什么 Thread 和 Checkpoint 对恢复执行很关键。
- 什么时候该引入 interrupt 和人工介入。
- 复杂工作流为什么更适合图式编排。
- LangChain 和 LangGraph 在一个项目里各自负责哪一层。
补充参考答案要点
- 练习题与自查里最关键的是能画清状态流转图,说明每个节点的输入、输出和下一跳条件。
- 带分支、重试和人工介入的图,要重点验证状态是否被正确保留,失败后是否回到预期节点。
- 如果图变复杂,优先做节点级断言、边级断言和状态快照,而不是只看最终回答。