文章摘要
从图结构状态机到生产级 Agent 工作流,掌握 LangGraph 的核架构、最佳实践与 2026 年最新特性
前置阅读收获
阅读本文后,你将收获:理解 LangGraph 为何采用图结构而非线性链式架构来构建 Agent 工作流;掌握 StateGraph、MessageGraph 和 Channel 的核心抽象;学会用条件边、循环和检查点构建复杂多步 Agent;了解 2026 年 LangGraph 最新特性(人类审批节点、流式输出优化、子图编排),以及在生产环境中部署 LangGraph Agent 的关键实践。
💡 建议前置阅读:如果你还不了解 AI Agent 的基本概念,建议先阅读 agent-001「AI Agent 入门」 和 agent-007「Agent 框架对比」。如果你已经熟悉 LangChain 的基础用法,可以直接开始本文。
💡 一句话理解
LangGraph 的核心理念是:Agent 工作流本质上是一个有向图,而非线性链。每个节点是一个计算单元,每条边决定下一步走向。理解这一点,后面的所有 API 设计都会变得直观。
1LangGraph 是什么:为什么需要图结构?
LangGraph 是 LangChain 团队开发的开源框架(GitHub 星标数持续增长,稳居 AI 开源项目前列),专门用于构建有状态、多步骤、带循环和分支的 AI Agent 工作流。它诞生于一个核心洞察:绝大多数真实的 Agent 应用都无法用线性链(Chain)来表达。
线性链的局限性:在 LangChain 的 LCEL 中,数据从 A → B → C 单向流动。但真实的 Agent 工作流需要:(1)循环——Agent 执行工具后可能需要回到规划步骤;(2)条件分支——根据工具返回结果决定下一步;(3)状态记忆——在多个步骤间共享和更新上下文;(4)人工介入——在关键节点暂停等待人类审批。这些需求在图结构中自然表达,在线性链中则需要大量 hack。
LangGraph 的核心抽象是有向图(Directed Graph)。图中的每个节点是一个计算单元(可以是 LLM 调用、工具执行、Python 函数),每条边定义节点之间的流转关系。通过引入 State(状态对象),LangGraph 让每个节点都能读取和修改共享状态,实现跨步骤的信息传递。状态对象的设计灵感来源于函数式编程中的不可变更新模式——每次节点执行后返回的不是完整的新状态,而是一个状态更新字典,LangGraph 会自动将这个更新通过 Reducer 合并到全局状态中。
2026 年,LangGraph 已经从一个实验性框架成长为生产级 Agent 编排标准。LangChain 13.8 万星的生态中,LangGraph 是最活跃的子项目之一,支持了从简单 ReAct Agent 到复杂多 Agent 协作系统的各种场景。根据 LangChain 官方的用户调查,超过 60% 的 LangChain 用户在构建多步 Agent 时选择使用 LangGraph 而非手写代码或 LCEL,这一比例在 2025 年仅为 35%。
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
# 定义共享状态
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
current_step: str
tool_results: dict
final_answer: str
# 创建图
graph_builder = StateGraph(AgentState)
# 添加节点
graph_builder.add_node("planner", planner_node)
graph_builder.add_node("executor", executor_node)
graph_builder.add_node("reviewer", reviewer_node)
# 添加边
graph_builder.add_edge("planner", "executor")
graph_builder.add_conditional_edges(
"executor",
route_based_on_result,
{"continue": "planner", "done": "reviewer"}
)
graph_builder.add_edge("reviewer", END)
# 设置入口
graph_builder.set_entry_point("planner")
# 编译
graph = graph_builder.compile()| 特性 | LangChain LCEL | LangGraph | 手写代码 |
|---|---|---|---|
线性链 | ✅ 原生支持 | ✅ 支持 | ✅ 可写 |
循环/回溯 | ❌ 不支持 | ✅ 原生支持 | ⚠️ 需手写 |
条件分支 | ⚠️ 有限支持 | ✅ 原生支持 | ⚠️ 需手写 |
状态管理 | ⚠️ 隐式 | ✅ 显式 State | ⚠️ 自行管理 |
人类审批 | ❌ 不支持 | ✅ interrupt | ⚠️ 需手写 |
检查点/恢复 | ❌ 不支持 | ✅ 内置 | ⚠️ 需手写 |
可视化 | ❌ 无 | ✅ 自动生成 | ❌ 无 |
流式输出 | ✅ 支持 | ✅ 增强支持 | ⚠️ 需手写 |
💡 一句话理解
⚠️ 常见踩坑
LangGraph 的学习曲线比 LCEL 陡峭。不要在简单任务上过度使用图结构——杀鸡用牛刀会让代码变得难以维护。遵循「足够简单,足够复杂」的原则。
2StateGraph 核心架构:状态、节点与边
StateGraph 是 LangGraph 最基础也是最常用的图构建器。它的核心由三部分组成:State(状态定义)、Node(节点函数)和 Edge(流转关系)。理解这三者的关系是掌握 LangGraph 的第一步。
State(状态)是一个 TypedDict 或 Pydantic 模型,定义了 Agent 在整个生命周期中需要维护的所有数据。State 中的每个字段可以通过 Reducer 来控制更新行为——默认是覆盖(Replace),但可以配置为追加(Append)、合并(Merge)等。Reducer 是 LangGraph 状态管理的精髓:它让多个节点可以安全地并发修改同一状态,而不会产生竞态条件。
节点(Node)是一个接收当前 State、返回 State 更新的函数。节点可以是任意 Python 可调用对象:LLM 调用、工具执行、HTTP 请求、数据库查询。节点的返回值会自动通过 Reducer 合并到全局 State 中。这种设计使得节点之间的耦合度极低——每个节点只需要知道自己需要读取和修改哪些 State 字段,不需要了解其他节点的内部实现。节点之间的唯一通信机制就是 State,这保证了数据流的清晰性和可追溯性。
Edge(边)定义节点之间的流转。LangGraph 支持三种边类型:(1)普通边(add_edge):无条件从 A 到 B;(2)条件边(add_conditional_edges):根据节点返回值中的某个字段,动态选择下一个节点;(3)入口边(set_entry_point):指定图的起始节点。条件边的灵活性是 LangGraph 的核心竞争力——它允许 Agent 根据运行时条件做出决策,而不是硬编码的执行流程。
条件边的实现原理:条件边函数接收当前 State,返回一个字符串(下一个节点的名称)或字符串列表(并行执行多个节点)。这个字符串必须出现在条件边注册时提供的映射中,否则会抛出运行时错误。
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
import operator
# 定义状态:messages 追加,其他字段覆盖
class ResearchState(TypedDict):
query: str
messages: Annotated[List[str], operator.add] # 追加模式
findings: Annotated[List[str], operator.add] # 追加模式
summary: str # 覆盖模式
step_count: int
max_steps: int
def research_node(state: ResearchState) -> dict:
"""研究节点:执行搜索并追加结果"""
query = state["query"]
# 模拟搜索
findings = search_web(query)
return {
"findings": findings,
"messages": [f"完成搜索: {query}"],
"step_count": state["step_count"] + 1
}
def should_continue(state: ResearchState) -> str:
"""条件路由:判断是否继续研究"""
if state["step_count"] >= state["max_steps"]:
return "summarize"
if len(state["findings"]) >= 10:
return "summarize"
return "research"
builder = StateGraph(ResearchState)
builder.add_node("research", research_node)
builder.add_node("summarize", summarize_node)
builder.add_edge("research", "research") # 自循环
builder.add_conditional_edges(
"research",
should_continue,
{"research": "research", "summarize": "summarize"}
)
builder.add_edge("summarize", END)
builder.set_entry_point("research")
app = builder.compile()| Reducer 类型 | 行为 | 适用场景 | 示例 |
|---|---|---|---|
operator.add | 追加到列表 | 消息历史、搜索结果 | messages += [msg] |
覆盖(默认) | 替换旧值 | 单一值字段 | summary = '...' |
自定义 Reducer | 自定义合并逻辑 | 复杂状态更新 | merge_dicts(old, new) |
operator.or_ | 按位或合并集合 | 去重标签/工具 | tags |= new_tags |
💡 一句话理解
使用 TypedDict 定义 State 时,务必为每个字段选择合适的 Reducer。最常见的错误是忘记给列表字段加 operator.add,导致每次节点更新都覆盖之前的结果而非追加。
⚠️ 常见踩坑
State 中的字段类型必须与 Reducer 兼容。给一个字符串字段使用 operator.add 会导致字符串拼接而不是覆盖——这不是你想要的行为。始终检查 Reducer 与字段类型的匹配性。
3检查点与持久化:中断、恢复与时间旅行
检查点(Checkpointer)是 LangGraph 最强大的生产级特性之一。它允许在图的执行过程中保存中间状态,实现三大核心能力:(1)中断恢复——在长时间运行的任务中暂停和恢复;(2)人类审批——在关键决策点暂停,等待人类确认后继续;(3)时间旅行——查看和回放历史状态,用于调试和审计。
LangGraph 内置了多种 Checkpointer 实现:MemorySaver(内存存储,适合测试)、SqliteSaver(SQLite 文件存储,适合单机部署)、PostgresSaver(PostgreSQL 存储,适合生产环境)、RedisSaver(Redis 存储,适合分布式部署)。选择哪种 Checkpointer 取决于你的部署场景——测试环境用 MemorySaver,生产环境用 PostgresSaver。
检查点的工作机制:每次节点执行完成后,LangGraph 将当前 State 序列化并存储到 Checkpointer 中。每次存储都关联一个 Thread ID,同一个 Thread ID 下的多次执行构成一个对话历史。通过传入不同的 Thread ID,可以实现多用户隔离。Thread ID 的设计使得 LangGraph 天然支持多租户场景——每个用户的对话历史通过 Thread ID 完全隔离,互不干扰。在实际部署中,建议使用用户标识(如用户 ID 或会话 ID)作为 Thread ID,这样可以在用户重新连接时自动恢复之前的对话状态。
人类审批的实现方式:使用 interrupt_before 或 interrupt_after 参数指定在哪些节点之前或之后暂停。暂停后,Agent 返回一个 interrupt 事件,包含当前状态。人类可以通过外部系统(如 Web UI)查看状态并决定是否继续。继续时,调用 invoke(None, config) 即可从断点处恢复执行。
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.postgres import PostgresSaver
# 测试环境:内存存储
memory = MemorySaver()
app = builder.compile(checkpointer=memory)
# 生产环境:PostgreSQL 存储
pg = PostgresSaver.from_conn_string(
"postgresql://user:pass@localhost:5432/langgraph"
)
app_prod = builder.compile(checkpointer=pg)
# 带中断的编译:在 human_review 节点前暂停
app_with_interrupt = builder.compile(
checkpointer=pg,
interrupt_before=["human_review"]
)
# 执行
config = {"configurable": {"thread_id": "user-123"}}
result = app_with_interrupt.invoke(
{"query": "研究 AI Agent 安全趋势"},
config
)
# 返回中断状态,等待人类审批
# 人类审批后继续
approved_result = app_with_interrupt.invoke(None, config)# 时间旅行:查看历史状态
config = {"configurable": {"thread_id": "user-123"}}
# 获取所有检查点
checkpoints = list(app.get_state_history(config))
for cp in checkpoints:
print(f"Step: {cp['metadata']['step']}")
print(f"State: {cp['values']}")
# 回到特定步骤
target_step = 3
state_at_step = app.get_state(config, checkpoint_id=checkpoints[target_step]['id'])
print(f"State at step 3: {state_at_step['values']}")
# 从历史步骤分叉执行
fork_config = {
"configurable": {
"thread_id": "user-123-fork",
"checkpoint_id": checkpoints[target_step]['id']
}
}
forked_result = app.invoke(None, fork_config)| Checkpointer | 持久化 | 并发支持 | 适用场景 |
|---|---|---|---|
MemorySaver | ❌ 内存 | ❌ 单线程 | 测试/开发 |
SqliteSaver | ✅ 文件 | ⚠️ 有限 | 单机部署 |
PostgresSaver | ✅ 数据库 | ✅ 多实例 | 生产环境 |
RedisSaver | ✅ 缓存 | ✅ 分布式 | 高并发场景 |
💡 一句话理解
在生产环境中,务必使用 PostgresSaver 或 RedisSaver。MemorySaver 在进程重启后会丢失所有状态,不适合任何有用户数据持久化需求的场景。
⚠️ 常见踩坑
检查点的序列化和反序列化有性能开销。对于 State 很大的场景(如包含大量文本的历史记录),检查点写入可能成为瓶颈。考虑只存储关键字段,或配置自定义的序列化策略。
4子图与嵌套:构建复杂多 Agent 系统
子图(Subgraph)是 LangGraph 2026 年最重要的架构升级之一。它允许在一个图中嵌入另一个完整的图,实现层级化的 Agent 编排。这解决了单图架构的两个核心问题:复杂度爆炸(所有逻辑写在一个图里难以维护)和 复用性差(相同的子流程需要在多个地方重复定义)。
子图的工作方式:你首先定义一个独立的 StateGraph(子图),然后将它作为一个节点添加到父图中。子图拥有自己的 State 定义,但可以与父图 State 通过 输入/输出映射 进行数据交换。这种设计使得子图可以作为独立模块开发和测试,然后在多个父图中复用。
多 Agent 协作的 LangGraph 实现:通过子图,可以优雅地实现多 Agent 协作模式。每个 Agent 是一个子图,父图负责编排 Agent 之间的协作流程。LangGraph 2026 年新增了 Send API,支持在运行时动态创建并行子图执行——这对于需要同时调用多个 Agent 的场景(如研究 Agent + 写作 Agent + 审核 Agent 并行工作)非常有用。
子图的状态隔离:子图的 State 是独立的,默认不会泄露到父图。如果需要将子图的结果传递给父图,需要在子图的出口节点显式返回映射到父图 State 的字段。这种显式的数据流设计使得调试和追踪变得非常清晰。子图的状态隔离还带来了一个重要的安全优势:即使子图内部发生错误或被攻击,也不会直接影响父图的状态。这为多 Agent 系统提供了一个天然的故障隔离边界。
# 子图:研究 Agent
class ResearchSubState(TypedDict):
query: str
findings: Annotated[List[str], operator.add]
research_builder = StateGraph(ResearchSubState)
research_builder.add_node("search", search_node)
research_builder.add_node("analyze", analyze_node)
research_builder.add_edge("search", "analyze")
research_builder.set_entry_point("search")
research_subgraph = research_builder.compile()
# 父图:主编 Agent
class EditorState(TypedDict):
topic: str
research_results: List[str]
draft: str
final_article: str
editor_builder = StateGraph(EditorState)
# 将子图添加为节点
editor_builder.add_node("research", research_subgraph)
editor_builder.add_node("write", write_node)
editor_builder.add_node("review", review_node)
# 定义状态映射
def map_input(state: EditorState) -> dict:
return {"query": state["topic"]}
def map_output(sub_result: dict) -> dict:
return {"research_results": sub_result["findings"]}
editor_builder.add_edge("research", "write")
editor_builder.add_edge("write", "review")
editor_builder.add_edge("review", END)
editor_builder.set_entry_point("research")
editor_graph = editor_builder.compile()| 架构模式 | 适用场景 | 复杂度 | LangGraph 支持 |
|---|---|---|---|
单图单 Agent | 简单工具调用 | 低 | ✅ StateGraph |
单图多节点 | 条件分支工作流 | 中 | ✅ 条件边 |
子图嵌套 | 多 Agent 协作 | 高 | ✅ 子图+状态映射 |
动态并行 | 同时执行多个子任务 | 极高 | ✅ Send API |
💡 一句话理解
子图设计的黄金法则:每个子图应该是一个完整的、可独立测试的功能单元。如果一个子图需要依赖父图的内部实现细节,说明你的职责划分有问题。
⚠️ 常见踩坑
子图的 State 映射是显式的,不是隐式的。常见的错误是期望子图能自动访问父图的 State——这是不可能的。必须通过输入/输出映射函数显式传递数据。
5流式输出:实时反馈与用户体验优化
流式输出(Streaming)是生产级 Agent 的关键用户体验特性。用户不应该等待 30 秒才看到第一个字符——他们应该在 Agent 思考的每一步都收到实时反馈。LangGraph 提供了多层级的流式支持,从粗粒度的节点级到细粒度的 Token 级。
LangGraph 的 stream() 方法返回一个迭代器,每次迭代产出当前节点执行后的完整 State 快照。这适合需要「逐步展示 Agent 进度」的场景,比如向用户展示「正在搜索 → 正在分析 → 正在总结」的进度条。
对于更细粒度的流式需求,LangGraph 支持 astream_events() 方法。它产出的不是完整 State,而是每个节点内部的事件流——包括 LLM 的 Token 级输出、工具调用的输入/输出、状态更新的中间结果。这是构建聊天界面的理想选择:用户可以看到 Agent 逐个 Token 地生成回复,而不是等待完成后一次性显示。astream_events() 的 v2 版本在 2026 年进行了重大改进,事件结构更加标准化,减少了冗余信息,使前端处理变得更加高效。
2026 年的流式优化:LangGraph 在流式输出方面进行了多项改进,包括(1)减少中间状态的序列化开销,使流式延迟降低 40%;(2)支持选择性流式——只流式输出用户关心的字段,而不是整个 State;(3)事件过滤——通过 event_filter 参数过滤掉调试事件,只保留用户可见的事件。
# 节点级流式:每完成一个节点产出一个快照
for event in app.stream({"query": "最新 AI 趋势"}):
for node_name, node_output in event.items():
print(f"节点 {node_name} 完成")
if "findings" in node_output:
print(f"找到 {len(node_output['findings'])} 条结果")
# Token 级流式:LLM 逐字输出
async for event in app.astream_events(
{"query": "最新 AI 趋势"},
version="v2"
):
kind = event["event"]
if kind == "on_chat_model_stream":
# LLM 产生的单个 token
token = event["data"]["chunk"].content
print(token, end="", flush=True)
elif kind == "on_tool_start":
print(f"\n[调用工具: {event['name']}]")
elif kind == "on_tool_end":
print(f"\n[工具完成]")// 前端 WebSockets 流式输出(Node.js 示例)
import { streamToWebSocket } from './stream-utils';
// 将 LangGraph 流式输出推送到前端
app.on('connection', (ws) => {
ws.on('message', async (query) => {
const config = { configurable: { thread_id: generateId() } };
for await (const event of graph.stream(
{ query },
{ streamMode: 'values' }
)) {
ws.send(JSON.stringify({
type: 'node_complete',
node: Object.keys(event)[0],
state: event
}));
}
ws.send(JSON.stringify({ type: 'complete' }));
});
});| 流式模式 | 粒度 | 延迟 | 适用场景 |
|---|---|---|---|
stream() | 节点级 | 中等(秒级) | 进度条、状态指示 |
astream_events() v2 | Token 级 | 极低(毫秒级) | 聊天界面 |
streamMode='values' | State 快照 | 中等 | 调试/审计 |
streamMode='updates' | 增量更新 | 低 | 实时仪表盘 |
💡 一句话理解
构建聊天界面时,优先使用 astream_events() v2 + on_chat_model_stream 事件。这是实现「打字机效果」的标准方式,延迟最低,用户体验最好。
62026 年 LangGraph 新特性盘点
2026 年上半年,LangGraph 经历了多次重要更新,大幅增强了其在生产环境中的能力。以下是本阶段最值得关注的特性:
人类审批节点(Human-in-the-loop)增强:从简单的 interrupt 机制升级为完整的审批工作流。新增了 Human 节点类型,支持自定义审批 UI、超时自动降级、多审批人投票等高级功能。这使得 LangGraph 可以构建需要人类监督的关键业务流程(如金融审批、医疗诊断辅助)。
LangGraph Platform 正式发布:LangChain 团队推出了 LangGraph Platform——一套完整的 Agent 部署和管理平台。它包含:(1)LangGraph Server:用于部署和运行 Agent 图的托管服务,支持自动扩展、负载均衡和健康检查;(2)LangGraph Studio:可视化编辑和调试 Agent 图的 IDE,支持实时查看图的执行状态、节点输入输出、和 State 变更历史;(3)LangGraph Cloud:托管的 Serverless 运行环境,开发者无需管理基础设施即可部署 Agent 应用。Platform 的发布使得 LangGraph 从「框架」升级为「平台」。
动态图构建:新增 StateGraph.add_node() 支持运行时动态添加节点和边。这使得 Agent 可以根据运行时条件自我修改工作流——例如,研究 Agent 在发现某个子领域需要深入时,动态添加一个新的分析节点。
性能优化:2026 年的 LangGraph 在大规模 State 场景下进行了深度优化,包括惰性求值(Lazy Evaluation)减少不必要的 State 序列化、异步节点并行执行提升吞吐量、以及内存池管理降低 GC 压力。根据官方基准测试,在 100 节点、1000 条消息的极端场景下,延迟比 2025 年版本降低 60%。
# 2026 新特性:Human 节点
from langgraph.types import Human
class ApprovalState(TypedDict):
proposal: str
risk_assessment: str
human_decision: str
approved: bool
builder = StateGraph(ApprovalState)
builder.add_node("analyze", analyze_risk)
# Human 节点:等待人类审批
builder.add_node(
"approve",
Human(
schema={"decision": {"type": "string", "enum": ["approve", "reject", "modify"]},
"reason": {"type": "string"}},
timeout=3600, # 1 小时超时
auto_fallback="reject" # 超时自动拒绝
)
)
builder.add_node("execute", execute_if_approved)
builder.add_node("notify", notify_result)
builder.add_edge("analyze", "approve")
builder.add_conditional_edges(
"approve",
lambda s: "execute" if s["human_decision"] == "approve" else "notify",
{"execute": "execute", "notify": "notify"}
)
builder.add_edge("execute", "notify")
builder.add_edge("notify", END)
builder.set_entry_point("analyze")| 特性 | 版本 | 影响 | 成熟度 |
|---|---|---|---|
Human 节点 | 2026-Q1 | 人类审批工作流 | ✅ 稳定 |
LangGraph Platform | 2026-Q2 | 部署/管理平台 | 🟡 公测 |
动态图构建 | 2026-Q1 | 运行时修改图 | ✅ 稳定 |
Send API 并行 | 2026-Q2 | 动态子图并行 | 🟡 公测 |
惰性求值优化 | 2026-Q1 | 性能提升 60% | ✅ 稳定 |
💡 一句话理解
7生产部署最佳实践
将 LangGraph Agent 从开发环境迁移到生产环境,需要解决四个核心问题:可观测性、错误处理、安全控制和性能优化。以下是经过大量生产环境验证的最佳实践。
可观测性:LangGraph 与 LangSmith 深度集成,可以自动追踪每个节点的输入/输出、执行时间、Token 消耗。在生产环境中,务必启用 LangSmith 追踪,并设置节点级别的超时和重试策略。对于不使用 LangSmith 的场景,可以通过自定义回调(Callback)将事件推送到你的监控系统(如 Prometheus + Grafana)。
错误处理:Agent 的错误处理比传统 API 复杂得多,因为一个错误可能发生在 LLM 调用、工具执行或状态更新的任何环节。LangGraph 2026 年新增了 on_error 配置,支持在节点级别定义错误处理策略:重试、降级、跳过或抛出。
安全控制:生产环境中的 Agent 需要严格的工具访问控制。使用 工具白名单(只允许 Agent 调用预定义的工具集)、参数验证(检查工具调用参数是否在安全范围内)和输出过滤(防止 Agent 输出敏感信息)。
性能优化:(1)使用 State 压缩——不要在 State 中存储完整的 LLM 响应,只存储摘要;(2)启用 检查点批量写入——PostgresSaver 支持批量写入,减少数据库连接开销;(3)对于高并发场景,使用 连接池和异步节点提升吞吐量。
from langgraph.config import RetryPolicy
from langgraph.types import Command
# 节点级错误处理:重试 + 降级
builder.add_node(
"llm_call",
llm_node,
retry=RetryPolicy(
max_attempts=3,
backoff_factor=2,
retry_on=[TimeoutError, ConnectionError]
),
fallback=degraded_response # 降级函数
)
# 自定义回调:推送到监控系统
class MonitoringCallback(BaseCallbackHandler):
def on_chain_end(self, outputs, **kwargs):
metrics.increment("agent.node.completed")
metrics.histogram(
"agent.node.duration",
kwargs.get("run_time", 0)
)
def on_tool_end(self, output, **kwargs):
metrics.increment(f"agent.tool.{kwargs['name']}.called")
app = builder.compile(
checkpointer=pg_saver,
interrupt_before=["human_review"]
)
# 带回调执行
result = app.invoke(
{"query": "分析市场趋势"},
config={
"configurable": {"thread_id": "session-1"},
"callbacks": [MonitoringCallback()]
}
)| 关注点 | 开发环境 | 生产环境 |
|---|---|---|
检查点 | MemorySaver | PostgresSaver / RedisSaver |
错误处理 | 抛出异常 | 重试 + 降级策略 |
监控 | print 日志 | LangSmith / Prometheus |
工具权限 | 无限制 | 白名单 + 参数验证 |
并发 | 单线程 | 异步 + 连接池 |
State 大小 | 不优化 | 压缩 + 只存摘要 |
💡 一句话理解
生产部署的第一步:启用 LangSmith 追踪。它能帮你看到 Agent 的每一步执行、每次 LLM 调用、每个工具的输出——没有这些可视化能力,排查生产问题是盲人摸象。
⚠️ 常见踩坑
永远不要在生产环境中使用 MemorySaver。进程重启 = 所有对话历史丢失。即使在开发阶段,也建议尽早切换到 SqliteSaver,这样你才能发现状态恢复相关的问题。
8对比分析:LangGraph vs 其他 Agent 编排方案
选择 Agent 编排框架不是非 LangGraph 不可。2026 年,市场上有多个成熟的 Agent 编排方案,各自有不同的设计哲学和适用场景。理解它们的差异,才能做出正确的技术选型。
CrewAI采用角色驱动的设计——每个 Agent 被赋予一个角色(Role)和目标(Goal),Agent 之间通过任务(Task)进行协作。CrewAI 的优势在于快速搭建多 Agent 团队,适合「多个专家各司其职」的场景。但它的工作流控制不如 LangGraph 精细——复杂的条件分支和循环需要额外编码。
AutoGen(微软)以对话为核心——Agent 之间通过消息传递进行协作。它的优势在于自然的多 Agent 对话模式,适合需要大量 Agent 间交互的研究场景。但 AutoGen 的学习曲线最陡峭,且对生产环境的支持(如持久化、监控)相对薄弱。
LlamaIndex Workflows是 LlamaIndex 生态中的 Agent 编排方案,专注于RAG 工作流。如果你的应用核心是检索增强生成(RAG),LlamaIndex Workflows 提供了最直接的集成。但它的通用性不如 LangGraph——非 RAG 场景需要使用其他框架。
LangGraph 的定位是通用、生产级的 Agent 编排。它在图结构表达力、状态管理、检查点、人类审批等方面提供了最完整的能力集。代价是学习曲线较陡,简单场景下显得「过重」。
| 维度 | LangGraph | CrewAI | AutoGen | LlamaIndex Workflows |
|---|---|---|---|---|
核心理念 | 图结构状态机 | 角色驱动团队 | 多 Agent 对话 | RAG 工作流 |
工作流控制 | ✅ 最强 | ⚠️ 中等 | ⚠️ 中等 | ⚠️ 中等 |
状态管理 | ✅ 显式 State | ⚠️ 隐式 | ⚠️ 消息传递 | ⚠️ 隐式 |
人类审批 | ✅ 内置 | ❌ 无 | ❌ 无 | ❌ 无 |
检查点/恢复 | ✅ 内置 | ❌ 无 | ❌ 无 | ❌ 无 |
多 Agent | ✅ 子图+Send | ✅ 原生 | ✅ 原生 | ⚠️ 有限 |
学习曲线 | ⚠️ 陡 | ✅ 平缓 | ❌ 很陡 | ✅ 平缓 |
生产就绪 | ✅ 是 | ⚠️ 部分 | ⚠️ 部分 | ⚠️ 部分 |
9实战:构建一个研究-写作-审核 Agent 系统
综合以上所有概念,我们构建一个完整的三阶段 Agent 系统:研究 Agent 负责搜索和分析信息,写作 Agent 根据研究结果生成文章草稿,审核 Agent 检查文章质量并提出修改建议。这个系统展示了 StateGraph、子图、条件边、检查点和流式输出的综合应用。
系统架构:父图包含三个子图(研究、写作、审核),每个子图有自己的内部状态和多个处理节点。父图通过条件边控制流程——如果审核不通过,回退到写作阶段修改;如果通过,输出最终结果。整个系统使用 PostgresSaver 持久化,支持中断恢复(人类可以在审核阶段介入审批)。
关键设计决策:(1)研究 Agent 使用循环 + 条件边实现「搜索 → 分析 → 判断是否需要更多搜索」的循环;(2)写作 Agent 使用子图封装,可以独立测试;(3)审核 Agent 在关键节点设置 interrupt,等待人类确认后才继续;(4)所有子图共享父图的 thread_id,实现端到端的对话历史。
# 完整的三阶段 Agent 系统
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
import operator
# === 共享状态 ===
class PipelineState(TypedDict):
topic: str
research_findings: Annotated[List[dict], operator.add]
draft: str
review_feedback: str
revisions: int
max_revisions: int
final_article: str
approved: bool
# === 研究子图 ===
class ResearchState(TypedDict):
topic: str
findings: Annotated[List[dict], operator.add]
search_count: int
def search_and_analyze(state: ResearchState) -> dict:
results = search_topic(state["topic"])
analyzed = [analyze_source(r) for r in results]
return {"findings": analyzed, "search_count": state["search_count"] + 1}
def needs_more_research(state: ResearchState) -> str:
if state["search_count"] >= 3:
return "done"
if len(state["findings"]) >= 5:
return "done"
return "continue"
research_builder = StateGraph(ResearchState)
research_builder.add_node("search", search_and_analyze)
research_builder.add_conditional_edges(
"search", needs_more_research,
{"continue": "search", "done": END}
)
research_builder.set_entry_point("search")
research_graph = research_builder.compile()
# === 父图 ===
builder = StateGraph(PipelineState)
# 添加子图作为节点
builder.add_node("research", research_graph)
builder.add_node("write", write_draft)
builder.add_node("review", review_draft)
builder.add_node("revise", revise_draft)
builder.add_node("publish", publish_article)
# 流程控制
builder.add_edge("research", "write")
builder.add_edge("write", "review")
builder.add_conditional_edges(
"review",
lambda s: "revise" if s["revisions"] < s["max_revisions"] else "publish",
{"revise": "revise", "publish": "publish"}
)
builder.add_edge("revise", "review")
builder.add_edge("publish", END)
builder.set_entry_point("research")
# 编译(带检查点和审核中断)
pipeline = builder.compile(
checkpointer=PostgresSaver.from_conn_string(DB_URL),
interrupt_before=["publish"]
)| 阶段 | 输入 | 输出 | 关键技术 |
|---|---|---|---|
研究 | 主题 | 搜索结果列表 | 子图+循环+条件边 |
写作 | 研究结果 | 初稿 | LLM 调用+模板 |
审核 | 初稿 | 审核意见 | LLM 评估+人类审批 |
修改 | 审核意见+初稿 | 修改稿 | 条件边循环 |
发布 | 终稿 | 已发布文章 | 人类审批节点 |
💡 一句话理解
这个实战系统的核心是可扩展性:每个子图可以独立替换(比如把研究子图从 Web 搜索换成内部知识库),父图不需要修改。这就是子图架构的最大价值——模块化和可维护性。
⚠️ 常见踩坑
实战系统中的最大性能瓶颈是研究子图的循环搜索。每次搜索都需要调用 LLM 分析,可能耗时 10-30 秒。建议设置合理的 search_count 上限(如 3),避免无限循环导致超时。
10扩展阅读与进一步学习
官方资源:LangGraph 的官方文档(langchain-ai.github.io/langgraph)是最权威的学习资料。文档中包含完整的 API 参考、教程和概念解释。建议按以下顺序学习:(1)Quickstart——30 分钟搭建第一个图;(2)Concepts——理解 State、Node、Edge 的设计哲学;(3)Tutorials——跟着教程完成 ReAct Agent、多 Agent 协作等经典场景;(4)How-to Guides——查询特定功能的实现方式。
相关知识点:如果你想深入了解 Agent 框架的整体生态,推荐阅读 agent-007「Agent 框架对比」,了解 LangGraph 与 CrewAI、AutoGen 等框架的差异。如果你想了解 Agent 安全,推荐阅读 agent-046「Agent 安全治理框架」 和 ethics-004「对抗攻击与防御」。
2026 年趋势:Agent 编排正在从「框架之争」走向「平台之争」。LangGraph Platform 的发布标志着 LangChain 团队将 Agent 编排从开源框架升级为商业平台。与此同时,CrewAI 和 AutoGen 也在加强生产级能力。对于开发者来说,这是一个好消息——竞争推动了工具的快速进化。
社区资源:LangGraph 的 GitHub Issues 和 Discord 频道是获取帮助的最佳途径。许多常见问题(如 State Reducer 使用、检查点配置、子图状态映射)都有现成的解答。2026 年新增的 LangGraph Studio 也提供了内置的文档和帮助系统。
💡 一句话理解
⚠️ 常见踩坑
不要一开始就尝试构建复杂的多 Agent 系统。先从单 Agent、单图的简单场景开始,逐步增加复杂度。直接上手多 Agent 子图是学习曲线最陡峭的方式,容易在状态映射和调试中迷失方向。