LangGraph 教程:复杂 Agent 工作流编排与人工审批
🎯 本节目标
Section titled “🎯 本节目标”学完这一节,你能:
- 用地铁网类比,跟家里人讲清 LangGraph 为什么需要“图”
- 从最简单的两节点图(A→B) 起步,亲手逐步叠加条件分支、人工审批,跑通一个真 Agent
- 知道何时用 LangChain 就够、何时必须升级到 LangGraph
🍎 生活化类比:流水线 vs 地铁网
Section titled “🍎 生活化类比:流水线 vs 地铁网”LangChain = 工厂流水线(一条直线,只能往前走)。LangGraph = 城市地铁网(能绕、能停、能回头)。
流水线一路向前,不能回头。但真实业务里:Agent 第一次没读懂想重试(地铁能坐回头)、置信度有高有低要分岔(地铁有换乘)、金额太大要等人审批(地铁每站都能停)。这些直线流水线全做不到——所以我们换一种能绕、能停、能回头的结构:图(Graph)。LangGraph 就是帮我们画这种“地铁网”的工具。
📖 概念讲解
Section titled “📖 概念讲解”1. 三要素:用“地铁系统”记一辈子
Section titled “1. 三要素:用“地铁系统”记一辈子”| 地铁系统 | LangGraph | 大白话 |
|---|---|---|
| 乘客(站间流动的人) | State(状态) | 节点之间传递的数据。乘客上车拿行李,下车可能又多一个包——数据会累积、会变 |
| 地铁站(每站做一件事) | Node(节点) | 一个处理步骤。拿到乘客,做自己那点活儿,再送走 |
| 轨道(连接两站) | Edge(边) | 节点间的流向。有的直通,有的有条件(高峰开、平峰停) |
一句话记住:乘客(State)坐着轨道(Edge),从一个站(Node)流到下一个站。
2. 何时从 LangChain 升级到 LangGraph
Section titled “2. 何时从 LangChain 升级到 LangGraph”| 业务长啥样 | 用什么 |
|---|---|
| 单轮问答、A→B→C 一条直线 | LangChain 够 |
| 要循环(没做对就重试)/ 条件岔路 | LangGraph |
| 要中途停下等人审批 | LangGraph(杀手锏) |
| 多 Agent 协作 | LangGraph |
四个信号里只要出现一个,直线链就开始别扭。
3. HITL(人工审批):取快递要本人签字
Section titled “3. HITL(人工审批):取快递要本人签字”HITL 全称 Human-In-The-Loop(人在环里),听着玄,其实就是有些步骤必须停下来等真人点个头。就像取贵重快递,快递员非要你本人签字——快递不会自动签收,必须在最后一公里停下来等你。Agent 也一样:大部分自动处理,金额超 10 万的必须有个真人点“批准”。这个“停下来等人签字”的站,就是 HITL。
🛠️ 动手实操:三步搭出一个真 Agent
Section titled “🛠️ 动手实操:三步搭出一个真 Agent”不学那种“一上来甩完整 Agent”的写法——零基础跟不上。我们分三小步,每步都是能跑的最小例子,逐步往上加东西。
⚠️ 下面是示意代码,讲清图的逻辑。LangGraph API 在迭代,跑之前看本节末尾官方文档,以最新写法为准。
Step 1:最朴素的两节点图(感受“站→轨道→站”)
Section titled “Step 1:最朴素的两节点图(感受“站→轨道→站”)”先画一条最简单的地铁线:A 站 → B 站,没分支、没回头。
# 伪代码示意,跑之前看官方最新文档from langgraph.graph import StateGraph, ENDfrom typing import TypedDict
# 1. "乘客长啥样"——一个带字段的字典class State(TypedDict): name: str # 乘客带个名字 greeting: str # A 站会给它加一句问候
# 2. 两个"地铁站",每个做一件小事def station_a(state): # A 站:加问候 return {"greeting": f"你好,{state['name']}!"}def station_b(state): # B 站:打印后送下车 print(f"B 站收到:{state['greeting']}"); return {}
# 3. 画地铁线:建图→加两站→连轨道→指定终点graph = StateGraph(State)graph.add_node("a", station_a) # 加 A 站graph.add_node("b", station_b) # 加 B 站graph.set_entry_point("a") # 列车从 A 站发车graph.add_edge("a", "b") # A→B 直通轨道graph.add_edge("b", END) # B 站之后是终点(下车)app = graph.compile()app.invoke({"name": "张奶奶"}) # 打印:B 站收到:你好,张奶奶!跑通了?你已经掌握 LangGraph 的骨架。剩下的花活,都是在这条线上加站、加岔路、加签字站。
Step 2:加一条“条件轨道”(岔路口)
Section titled “Step 2:加一条“条件轨道”(岔路口)”业务常有岔路:置信度高直接放行,低转人工。这就是有条件的轨道——高峰开、平峰停。
# 接 Step 1 加东西def check_confidence(state): # "判断站":只决定下一站去哪 return "high" if state["confidence"] > 0.8 else "low"
graph.add_node("check", check_confidence)graph.add_node("auto_process", ...) # 自动处理站(略)graph.add_node("human_review", ...) # 人工复审站(略)
graph.add_conditional_edges( # 条件轨道:看返回值决定去哪 "check", check_confidence, {"high": "auto_process", "low": "human_review"})条件轨道的精髓:不连死的,而是“看情况”决定下一站。这正是流水线做不到、而图能做到的事。
Step 3:加一个“签字站”(人工审批 HITL)
Section titled “Step 3:加一个“签字站”(人工审批 HITL)”加上本节的杀手锏:有一个站,列车到了**必须停下来,等真人点“批准”**才继续——就像取贵重快递要本人签字。
# 接 Step 2 加东西def human_approve(state): # "签字站":停下来等人输入 y/n print(f"待审批:{state['extracted']}") approved = input("批准吗?(y/n): ") == "y" # 生产用 interrupt,别用 input return {"approved": approved}
graph.add_node("human", human_approve)graph.add_edge("human", "generate") # 签完字 → 生成询价单graph.add_edge("generate", END) # 生成完 → 终点app = graph.compile()# 跑的时候,列车开到 human 站会"卡住",等你输入 y/n 才继续三步拼起来,就是蚂蚁 FDE 访谈里**“询价邮件自动处理 Agent”** 的最小骨架:抽取信息 → 判断置信度 → (低的话)等人签字 → 生成询价单。再复杂的 Agent,本质都是这条地铁线加东西——多几个站、几条岔路、几个签字站而已。别被吓到。
⚠️ 常见错误
Section titled “⚠️ 常见错误”| 问题 | 大白话原因 | 怎么解决 |
|---|---|---|
| 图跑出死循环 | 有轨道绕回去了,但没终止条件 | 确保所有岔路最终通向 END |
| State 数据没更新 | 节点返回的 key 跟 State 定义对不上 | 返回的 key 必须和 State 字段名一模一样 |
| HITL 卡死不动 | 用了 input(),生产会真死等 |
生产用 LangGraph 的 interrupt,别用 input() |
| 报错找不到节点 | add_edge 写了站名,add_node 没加 |
站名拼错或忘加,把所有 add_node 检查一遍 |
1. 用地铁系统类比,说清三要素各是啥?State 为什么重要?
State = 乘客(站间流动的数据),Node = 地铁站(每站做一件事),Edge = 轨道(连站,有的有条件)。State 重要,因为它是唯一在站之间传递的东西——每个站读它、改它、再传走。没有 State,站和站就断了。
2. 什么情况必须从 LangChain 升级到 LangGraph?举一个生活化例子。
四个信号里任何一个:① 循环重试 ② 条件岔路 ③ 停下等人审批(HITL)④ 多 Agent 协作。比如自动处理邮件,大部分自动发,金额超 10 万必须等人签字——这就必须上 LangGraph,因为直线流水线停不下来等人。
🚀 实战小项目:给询价 Agent 再加一个签字站
Section titled “🚀 实战小项目:给询价 Agent 再加一个签字站”在 Step 3 基础上再加一个审批站:除了“金额超 10 万要签字”,再加“客户是新客户也要签字“。提示:再 add_node 一个签字站,再用一条 add_conditional_edges 决定去不去。
验收:① 新老客户 × 金额大小 四种组合,都能走到对的终点;② 两个签字站各签一次,流程能跑完;③ 故意输 n 拒绝,流程能优雅结束,不卡死。
📚 总结 & 下一节
Section titled “📚 总结 & 下一节”- LangChain 是流水线(直线),LangGraph 是地铁网(能绕、能停、能回头)——业务一出现循环、岔路、等人,就该升级
- 三要素用地铁记一辈子:State=乘客、Node=地铁站、Edge=轨道(有的有条件)
- HITL 就是取快递要本人签字——LangGraph 的杀手锏,生产 Agent 几乎都少不了
下一节:MCP 协议——让 Agent 标准化地连接外部工具,不用每个工具都从头写胶水代码。
🏋️ 配套自练
Section titled “🏋️ 配套自练”- LangGraph 官方教程 — 跟着官方 intro 跑一个最简图(免费)
- LangGraph Studio — 可视化调试图工作流,看节点怎么流动(免费、macOS)
- 把本节的“询价邮件 Agent”画在纸上,标出哪些是 Node、哪些是 Edge