"凌晨6点08分,我看着那个 if-elif-elif-elif 嵌套了12层的代码,陷入了沉思。这不是代码,这是意大利面工厂。那一刻我想:如果有一种方式,能让程序像地图一样——节点是城市,边是道路,遇到岔路看路标——那该多好。LangGraph 就是那张地图。"
什么是 LangGraph?
LangGraph是 LangChain 团队开发的框架,用于构建有状态的、多步骤的 AI Agent 应用。它的核心思想是:把 Agent 的执行流程建模为一张图(Graph),节点(Node)是处理逻辑,边(Edge)是流转条件。
简单来说:
- 📝 普通编程 = if-else 线性逻辑(面条代码)
- 🔗 LangGraph = 节点和边组成的图(清晰的工作流)
- 🎭 CrewAI = 角色和任务组成的剧组
核心概念
┌──────────────────────────────────────────────────────────────────┐
│ LangGraph 核心架构 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ │ │ │ │ │ │
│ │ Node A │────────▶│ Node B │────────▶│ Node C │ │
│ │ (Agent) │ Edge │ (Tool) │ Edge │ (Output) │ │
│ │ │ │ │ │ │ │
│ └──────────┘ └────┬─────┘ └──────────┘ │
│ │ │
│ 条件边 (Conditional) │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Node D │ │ Node E │ │
│ │ (Retry) │ │ (Fallback)│ │
│ └──────────┘ └──────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ State(全局状态) │ │
│ │ messages, documents, current_step, errors, ... │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
1. State(状态)
State 是整个图的"共享记忆",所有节点都可以读写。通常用 TypedDict 或 Pydantic 定义:
from typing import TypedDict, Annotated, List
from langgraph.graph import add_messages
class AgentState(TypedDict):
"""全局状态定义"""
messages: Annotated[list, add_messages] # 消息历史
documents: List[str] # 搜索到的文档
current_step: str # 当前步骤
retry_count: int # 重试次数
final_answer: str # 最终答案
2. Node(节点)
Node 是处理函数,接收当前状态,返回状态更新:
def search_node(state: AgentState):
"""搜索节点:根据用户问题搜索相关信息"""
query = state["messages"][-1]["content"]
results = search_tool.run(query)
return {
"documents": results,
"current_step": "searched"
}
def generate_node(state: AgentState):
"""生成节点:基于搜索结果生成回答"""
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke(
f"基于以下资料回答问题:\n{state['documents']}"
)
return {"final_answer": response.content}
3. Edge(边)
Edge 定义了节点之间的流转关系:
def should_retry(state: AgentState):
"""条件边:决定是否重试"""
if state["retry_count"] < 3:
return "retry"
return "generate"
# 构建图
graph = StateGraph(AgentState)
graph.add_node("search", search_node)
graph.add_node("generate", generate_node)
graph.add_node("retry", retry_node)
# 添加边
graph.add_edge("search", "generate") # 固定边
graph.add_conditional_edges(
"generate",
should_retry,
{"retry": "retry", "generate": END} # 条件边
)
graph.set_entry_point("search")
LangGraph vs 其他框架
| 维度 | LangGraph | CrewAI | OpenClaw | AutoGen |
|---|---|---|---|---|
| 核心抽象 | 图(Graph) | 角色(Role) | Agent + Skills | 对话(Chat) |
| 状态管理 | ✅✅ 最强 | ⭐⭐ 基础 | ✅ 内置 Memory | ⭐⭐ 中等 |
| 复杂流程 | ✅✅ 优势领域 | ⭐⭐ 顺序为主 | ✅ 事件驱动 | ⭐⭐ 对话驱动 |
| 条件路由 | ✅✅ 非常灵活 | ⭐ 较弱 | ✅ Prompt驱动 | ⭐⭐ 中等 |
| 持久化 | ✅ Checkpoint | ❌ 无内置 | ✅ 内置 | ❌ 无内置 |
| 学习曲线 | ⭐⭐⭐⭐ 陡峭 | ⭐⭐ 平缓 | ⭐ 最简单 | ⭐⭐⭐ 中等 |
OpenClaw 中的等价实现
OpenClaw 虽然没有显式的"图"概念,但通过 Skill + Subagent + Cron 可以实现类似的流程编排:
# OpenClaw 实现 LangGraph 风格的条件路由
# 在 OpenClaw 的 Skill 中定义流程
# SKILL.md 示例:
## 内容发布工作流
### 执行步骤
1. 使用 web_search 搜索相关内容
2. 分析搜索结果质量(内部判断)
3. 如果质量不够 → 回到步骤1换关键词重搜
4. 如果质量OK → 生成文章
5. 保存到 /var/www/miaoquai/news/
6. 更新 sitemap.xml
### 条件判断
- 如果搜索结果少于3条 → 调整关键词重搜
- 如果文章长度不足800字 → 扩展内容
- 如果已存在相同主题 → 跳过,输出"已覆盖"
# OpenClaw 的 Agent 会根据这些规则进行条件路由
# 本质上也是一种"图",只是用自然语言描述
💡 LangGraph 的杀手锏:Checkpoints
LangGraph 最大的亮点是 Checkpointer——它可以把图的执行状态保存到数据库(SQLite、PostgreSQL),支持:
1. 中断恢复:程序崩了,从上次断点继续
2. 人工介入:在特定节点暂停,等待人类审批后继续
3. 时间旅行:回到任意历史状态重新执行
4. 多会话:支持多个用户并发使用同一个图
LangGraph 最大的亮点是 Checkpointer——它可以把图的执行状态保存到数据库(SQLite、PostgreSQL),支持:
1. 中断恢复:程序崩了,从上次断点继续
2. 人工介入:在特定节点暂停,等待人类审批后继续
3. 时间旅行:回到任意历史状态重新执行
4. 多会话:支持多个用户并发使用同一个图
LangGraph 的实战场景
| 场景 | 为什么选 LangGraph |
|---|---|
| 客服机器人 | 需要复杂的状态管理(用户信息、对话历史、工单状态) |
| 数据分析 Agent | 多步骤流程(取数据→清洗→分析→可视化),需要条件分支 |
| 代码审查系统 | 需要循环执行(发现Bug→修复→再审查),直到通过 |
| 多轮审批系统 | 需要 Human-in-the-Loop,在审批节点暂停等待人类 |
| 研究助手 | 需要根据搜索结果动态决定下一步(搜更多?换个方向?直接写?) |
⚠️ LangGraph 常见踩坑
1. 过度工程:简单任务(如单步搜索+生成)用 LangGraph 太重了,直接用 OpenClaw 即可
2. 状态爆炸:所有东西都塞进 State 会导致图变复杂。只保留必要的共享状态
3. 死循环:条件边写错可能导致无限循环。一定要设重试上限
4. 调试噩梦:图执行出错时,很难追踪是哪个节点出了问题。用好
1. 过度工程:简单任务(如单步搜索+生成)用 LangGraph 太重了,直接用 OpenClaw 即可
2. 状态爆炸:所有东西都塞进 State 会导致图变复杂。只保留必要的共享状态
3. 死循环:条件边写错可能导致无限循环。一定要设重试上限
4. 调试噩梦:图执行出错时,很难追踪是哪个节点出了问题。用好
verbose=True 和 LangSmith
总结
LangGraph 是 Agent 框架的"瑞士军刀"——功能强大但学习成本高。如果你的 Agent 需要复杂的状态管理、条件路由、中断恢复,它是2026年的最佳选择。但如果你的需求是"帮我每天自动发个日报",那还是用 OpenClaw 吧——别用牛刀杀鸡。
"凌晨6点08分的那份意大利面代码,后来我用 LangGraph 重写了。节点清晰、边明确、状态可追溯。代码从1200行缩到300行。但学 LangGraph 的过程,让我多熬了三个通宵。这件事教会我:好的架构需要好的工具,但好的工具也需要好的头发。"