🔗 LangGraph

用图的方式思考 —— 构建 AI Agent 的最强状态机

"凌晨6点08分,我看着那个 if-elif-elif-elif 嵌套了12层的代码,陷入了沉思。这不是代码,这是意大利面工厂。那一刻我想:如果有一种方式,能让程序像地图一样——节点是城市,边是道路,遇到岔路看路标——那该多好。LangGraph 就是那张地图。"

什么是 LangGraph?

LangGraph是 LangChain 团队开发的框架,用于构建有状态的、多步骤的 AI Agent 应用。它的核心思想是:把 Agent 的执行流程建模为一张图(Graph),节点(Node)是处理逻辑,边(Edge)是流转条件。

简单来说:

核心概念

┌──────────────────────────────────────────────────────────────────┐ │ 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 的实战场景

场景 为什么选 LangGraph
客服机器人 需要复杂的状态管理(用户信息、对话历史、工单状态)
数据分析 Agent 多步骤流程(取数据→清洗→分析→可视化),需要条件分支
代码审查系统 需要循环执行(发现Bug→修复→再审查),直到通过
多轮审批系统 需要 Human-in-the-Loop,在审批节点暂停等待人类
研究助手 需要根据搜索结果动态决定下一步(搜更多?换个方向?直接写?)
⚠️ LangGraph 常见踩坑
1. 过度工程:简单任务(如单步搜索+生成)用 LangGraph 太重了,直接用 OpenClaw 即可
2. 状态爆炸:所有东西都塞进 State 会导致图变复杂。只保留必要的共享状态
3. 死循环:条件边写错可能导致无限循环。一定要设重试上限
4. 调试噩梦:图执行出错时,很难追踪是哪个节点出了问题。用好 verbose=True 和 LangSmith

总结

LangGraph 是 Agent 框架的"瑞士军刀"——功能强大但学习成本高。如果你的 Agent 需要复杂的状态管理、条件路由、中断恢复,它是2026年的最佳选择。但如果你的需求是"帮我每天自动发个日报",那还是用 OpenClaw 吧——别用牛刀杀鸡。

"凌晨6点08分的那份意大利面代码,后来我用 LangGraph 重写了。节点清晰、边明确、状态可追溯。代码从1200行缩到300行。但学 LangGraph 的过程,让我多熬了三个通宵。这件事教会我:好的架构需要好的工具,但好的工具也需要好的头发。"