LangGraph vs LangChain:同一生态的两副面孔

LangGraph vs LangChain:同一生态的两副面孔 :root { --text: #1a1a2...

LangGraph vs LangChain:同一生态的两副面孔 :root { –text: #1a1a2e; –bg: #fafafa; –accent: #2563eb; –code-bg: #f1f5f9; –border: #e2e8f0; –muted: #64748b; –width: 780px; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Noto Sans SC’, ‘PingFang SC’, ‘Microsoft YaHei’, sans-serif; line-height: 1.85; color: var(–text); background: var(–bg); padding: 2rem 1rem; } article { max-width: var(–width); margin: 0 auto; } /* Typography */ h1 { font-size: 2rem; margin: 2.5rem 0 1.25rem; border-bottom: 2px solid var(–accent); padding-bottom: 0.5rem; line-height: 1.3; } h2 { font-size: 1.45rem; margin: 2rem 0 0.85rem; line-height: 1.35; } h3 { font-size: 1.15rem; margin: 1.5rem 0 0.6rem; color: var(–accent); line-height: 1.4; } h1:first-child { margin-top: 0; border-bottom: 2px solid var(–accent); } p { margin: 0.8rem 0; } a { color: var(–accent); text-decoration: none; border-bottom: 1px solid transparent; transition: border-color 0.2s; } a:hover { border-bottom-color: var(–accent); } /* Inline code */ p code, li code, td code { background: var(–code-bg); padding: 0.15em 0.45em; border-radius: 4px; font-size: 0.88em; font-family: ‘SF Mono’, ‘Fira Code’, Consolas, monospace; color: #e83e8c; } /* Code blocks */ pre { background: #1e1e2e; color: #cdd6f4; padding: 1.15rem 1.25rem; border-radius: 8px; overflow-x: auto; margin: 1rem 0; font-size: 0.9rem; line-height: 1.55; } pre code { background: none !important; padding: 0 !important; color: inherit !important; font-size: inherit; } /* Tables */ table { width: 100%; border-collapse: collapse; margin: 1.25rem 0; font-size: 0.92rem; } th, td { padding: 0.55rem 0.8rem; border: 1px solid var(–border); text-align: left; vertical-align: top; } th { background: #f0f4ff; font-weight: 650; color: #1e40af; } tr:nth-child(even) { background: #f8fafc; } tr:hover { background: #eef2ff; } /* Blockquotes */ blockquote { border-left: 4px solid var(–accent); margin: 1.25rem 0; padding: 0.65rem 1.15rem; background: #f0f4ff; color: #475569; border-radius: 0 6px 6px 0; font-style: italic; } blockquote p { margin: 0.4rem 0; } /* Lists */ ul, ol { margin: 0.6rem 0 0.6rem 1.5rem; } li { margin: 0.3rem 0; } ul ul, ol ol, ul ol, ol ul { margin: 0.2rem 0 0.2rem 1.25rem; } /* Horizontal rule */ hr { border: none; border-top: 1px solid var(–border); margin: 2rem 0; } /* Strong / emphasis styling */ strong { color: #1e40af; } /* TOC Navigation */ nav.toc { background: linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%); padding: 1.15rem 1.35rem; border-radius: 10px; margin-bottom: 2.25rem; border: 1px solid #dbeafe; } nav.toc h2 { margin-top: 0; font-size: 1.05rem; color: var(–accent); margin-bottom: 0.6rem; } nav.toc ol { list-style: none; padding-left: 0; columns: 2; column-gap: 1.5rem; } nav.toc li { margin: 0.2rem 0; break-inside: avoid; } nav.toc a { border-bottom: none; font-size: 0.9rem; color: #475569; transition: color 0.2s; } nav.toc a:hover { color: var(–accent); } /* Footer */ footer { margin-top: 3.5rem; padding-top: 1.25rem; border-top: 1px solid var(–border); text-align: center; color: var(–muted); font-size: 0.82rem; } /* Responsive */ @media (max-width: 800px) { body { padding: 1rem 0.5rem; } h1 { font-size: 1.5rem; } h2 { font-size: 1.25rem; } pre { font-size: 0.82rem; padding: 0.9rem; } table { font-size: 0.8rem; } th, td { padding: 0.4rem 0.5rem; } nav.toc ol { columns: 1; } } /* Print */ @media print { body { background: white; font-size: 11pt; } pre { background: #f5f5f5; color: #333; } nav.toc { break-after: page; } a { color: var(–text); } } /* Custom gradient header */ article > h1:first-child { background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; border-bottom: none; font-size: 2.1rem; font-weight: 800; text-align: center; margin-bottom: 0.3rem; } article > h1:first-child + blockquote { text-align: center; border-left: none; background: none; color: var(–muted); font-style: normal; font-size: 0.9rem; margin-top: 0; padding-top: 0; }

目录

    LangGraph vs LangChain:同一生态的两副面孔

    深度剖析两大框架的架构基因、适用疆界与协同之道


    读完 LangChain 又读完 LangGraph 的文档,我脑子里跳出一个画面:一个木匠的工具箱里,既有锤子又有电钻。你说锤子和电钻哪个更好?没人这么问——因为答案永远是”看你钉钉子还是打孔”。

    LangChain 和 LangGraph 的关系,恰如这锤子与电钻。同为一家公司(LangChain Inc.)出品,同属一个生态,却解决截然不同的问题。然而社区里”LangChain vs LangGraph”的争论从未停歇,盖因两者的边界在演进中几经漂移,让人眼花。

    本文欲正本清源:不拉踩,不站队,只求把两张面孔描清楚——它们各自的基因是什么,各自的疆界在哪里,何时该独当一面,何时又该联手上阵。


    1. 缘起:从一条链到一张图

    故事要从 2022 年讲起。

    那年 10 月,Harrison Chase 开源了 LangChain。彼时大模型应用开发的痛点极其朴素:你得手动拼接 prompt、调用 API、解析输出、再喂给下一个 prompt——这些”胶水代码”重复且脆弱。LangChain 的答案是一套组件 + 链式编排:把 LLM、提示模板、向量存储、文档加载器这些积木标准化,再用 Chain 把它们串起来。

    这个模式在 2023 年大获成功。LangChain 的 GitHub Star 数半年内从零飙到 8 万,成了 LLM 应用开发的事实标准。

    但它内置了一个致命假设:数据沿链单向流动,有进无退,有去无回。

    这假设在 RAG 管道、文本翻译、摘要生成这类”一次过”场景中完全成立。可一旦你开始构建 Agent——那种需要”搜一搜 → 想一想 → 不够再搜 → 够了再回答”的系统——线性链的局限性就暴露无遗。你要循环,它不给;你要回溯,它不干;你要在某个节点暂停等人工审批,它根本没这个概念。

    2023 年秋,LangChain 团队意识到这个问题,基于 Google Pregel 的批量同步并行模型,开源了 LangGraph。这个新框架的核心理念极其简单:把 Agent 工作流建模为有向图,节点是计算函数,边是控制流,支持循环、分支和条件路由。

    2025 年 10 月 22 日,两个库同时发布 v1.0 GA。分工从此明确:

    • LangChain → Agent 框架:提供模型、工具、提示的抽象与集成
    • LangGraph → 编排运行时:提供持久执行、流式传输、人机协同、断点恢复

    自此,LangChain 的 create_agent 方法底层就在跑 LangGraph 的图引擎。它们从未被设计为竞争关系——可惜,这个事实不是所有人都知道。


    2. 架构基因:DAG 对 StateGraph

    欲明其异,先观其骨。

    2.1 LangChain:管道的哲学

    LangChain 的核心抽象是 Chain——一种将组件串联的声明式管道。其最新表达形式是 LCEL(LangChain Expression Language)

    from langchain.prompts import ChatPromptTemplate
    from langchain.chat_models import ChatOpenAI
    
    prompt = ChatPromptTemplate.from_template("将以下文本翻译成英文:{text}")
    model = ChatOpenAI()
    chain = prompt | model  # 管道操作符
    result = chain.invoke({"text": "你好,世界!"})
    

    管道操作符 | 是 LCEL 的灵魂。它让组件组合像 Unix 管道一样直观——A 的输出自动成为 B 的输入。这很美,也很局限。

    LCEL 的底层是一个 DAG(有向无环图) 执行模型。每个步骤有确定的后继,数据单向流动,不存在循环。它适合的场景极其精确:输入 → 处理1 → 处理2 → … → 输出,一步接一步,从不回头。

    2.2 LangGraph:状态机的哲学

    LangGraph 的核心抽象是 StateGraph——以显式状态为中心的有向图,允许循环。它直接从 Google 的 Pregel 论文汲取灵感,采用批量同步并行(BSP)模型:

    每个超步(superstep) = Plan → Execute → Update
    

    与传统链式调用有三大根本区别:

    其一,显式状态。 你用 TypedDict 定义全局状态 Schema,每个节点只读状态、只写部分更新:

    from typing import Annotated, TypedDict
    import operator
    
    class AgentState(TypedDict):
        messages: Annotated[list, operator.add]  # 追加而非覆盖
        research_done: bool
        findings: list
    

    Annotated[list, operator.add] 是个精巧设计——它告诉运行时:当多个节点同时写 messages 时,用加法合并(即追加),而非覆盖。你还可以定义自己的 reducer 函数来实现任意合并策略。

    其二,显式控制流。 每个路由决策都是一个命名函数,而非隐藏在运行时内部的魔法:

    def should_continue(state: AgentState):
        """是否继续搜索?这是一个你写的显式函数。"""
        if len(state["findings"]) >= 3:
            return "summarize"  # 够了,去总结
        return "search"          # 还不够,继续搜
    

    其三,图即文档。 编译后的图可导出为 Mermaid 图表,也可在 LangSmith Studio 中可视化调试。你一眼就能看懂整个 Agent 的执行逻辑——这在代码审查和合规审计中价值连城。

    2.3 一张表看透差异

    维度 LangChain (LCEL) LangGraph (StateGraph)
    图模型 DAG(无环) 有向图(可循环)
    状态 隐式,运行时内部管理 显式 TypedDict,开发者定义
    控制流 管道路由,自动化 条件边 + 命名函数,完全显式
    循环 不支持 原生支持
    并行 LCEL 的 RunnableParallel 图并行分支
    中断/恢复 interrupt() + Command(resume=)
    持久化 需自行实现 内置 SQLite/Postgres Checkpointer
    流式输出 token 级流式 7 种流模式(values/updates/messages/custom/checkpoints/tasks/debug)

    3. Agent 范式:隐式循环 vs 显式图

    这才是两框架真正拉开差距的地方——Agent 的实现方式。

    3.1 LangChain:一行搞定(但你不知道它做了什么)

    LangChain v1.0 的 create_agent 用极少代码启动一个 Agent:

    from langchain.agents import create_agent
    from langchain_openai import ChatOpenAI
    from langchain_community.tools import TavilySearchResults
    
    agent = create_agent(
        ChatOpenAI(model="gpt-4o-mini"),
        [TavilySearchResults(max_results=3)],
        system_prompt="You are a helpful assistant."
    )
    result = agent.invoke({"messages": [("user", "What is LangGraph?")]})
    

    四行代码,Agent 就跑起来了。它会自动判断何时搜索、何时回答、如何循环。这适合80% 的常见场景

    但代价是什么?你完全看不到决策过程。 工具调用的路由逻辑被封在运行时里,调试时只能看最终输出,无法检查 Agent 在第三步为什么选择了搜索而非回答。

    3.2 LangGraph:二十行代码(但你对每个决策了如指掌)

    同一个 Agent,用 LangGraph 原生写法:

    from langgraph.graph import StateGraph, END
    from langgraph.graph.message import add_messages
    from langgraph.prebuilt import ToolNode
    from typing import TypedDict, Annotated
    
    class AgentState(TypedDict):
        messages: Annotated[list, add_messages]
    
    model = ChatOpenAI(model="gpt-4o-mini").bind_tools(tools)
    tool_node = ToolNode(tools)
    
    def call_model(state: AgentState):
        return {"messages": [model.invoke(state["messages"])]}
    
    def should_use_tool(state: AgentState):
        last_msg = state["messages"][-1]
        return "tools" if last_msg.tool_calls else END
    
    graph = StateGraph(AgentState)
    graph.add_node("agent", call_model)
    graph.add_node("tools", tool_node)
    graph.set_entry_point("agent")
    graph.add_conditional_edges("agent", should_use_tool)
    graph.add_edge("tools", "agent")
    app = graph.compile()
    

    代码量翻了五倍,但每行都在告诉你一件事:图在何时、基于什么条件、把控制权交给哪个节点。 should_use_tool 是你写的 Python 函数,里面可以加日志、埋点、任何你想要的逻辑。

    深入一层:create_agent 的底层本身就是在一个 LangGraph StateGraph 上跑的——它不过是帮你写好了那二十行中的十五行,留给你五行定制空间。


    4. 独门绝技:LangGraph 的三大杀器

    若问 LangGraph 凭什么在 Agent 框架的混战中站稳脚跟,答案绕不开这三样。

    4.1 Checkpointer:时间旅行与故障恢复

    每个超步完成后,Checkpointer 自动保存完整状态快照到 SQLite 或 Postgres:

    from langgraph.checkpoint.sqlite import SqliteSaver
    
    checkpointer = SqliteSaver.from_conn_string("checkpoints.db")
    app = graph.compile(checkpointer=checkpointer)
    
    # 如果执行崩溃了,用同一个 thread_id 恢复
    config = {"configurable": {"thread_id": "user-123"}}
    app.invoke({"messages": [("user", "复杂任务...")]}, config)
    # 💥 崩溃了,没关系
    app.invoke(None, config)  # 从上一个检查点继续
    

    这意味着长时间运行的 Agent 任务不再是噩梦。你的 Agent 可以跑几分钟、几小时、甚至跨会话——Checkpointer 保证状态不丢。

    更妙的是时间旅行调试:你可以回放到第 N 步的状态,检查当时 Agent 在想什么、工具返回了什么、为什么做了那个决策。这不叫调试,这叫”拿着回放按钮看 Agent 的灵魂”。

    4.2 Human-in-the-Loop:精确中断与人工审批

    人和 Agent 协作的最高境界不是”人看 Agent 跑完再检查”,而是”Agent 跑到关键点时主动停下来问人”。LangGraph 的 interrupt() 让这变得极其优雅:

    def sensitive_action_node(state: AgentState):
        proposed = "发送批量邮件给 10000 个用户"
        # 🛑 在此暂停,等待人工审批
        approval = interrupt({"proposed_action": proposed})
    
        if approval.get("approved"):
            send_emails()  # 实际发送
            return {"messages": [f"已发送: {proposed}"]}
        return {"messages": ["用户取消了操作"]}
    

    人工审批者看到中断信息后:

    # 审批通过,恢复执行
    app.invoke(Command(resume={"approved": True}), config)
    

    你可以把 interrupt() 放在图的任意节点,实现任意粒度的 HITL。CrewAI 和 AutoGen 做不到这种精确度——它们通常只能在整个任务完成后插入审查。

    4.3 流式输出的七种武器

    LangGraph 支持七种流模式,每种服务于不同的调试和交互需求:

    模式 输出 适用场景
    values 每个超步后的完整状态 终端展示最终结果
    updates 每个节点的状态增量 渐进式 UI 更新
    messages LLM token 流 打字机效果
    custom 自定义流事件 业务逻辑埋点
    checkpoints 检查点元数据 持久化监控
    tasks 任务执行事件 调试和性能分析
    debug 最详细的执行追踪 深度调试

    这七种模式可以组合使用,比如同时用 messages 做打字机效果、updates 做进度条——你在构建生产级 Agent 时才会意识到这有多重要。


    5. 多 Agent 竞技场:LangGraph vs CrewAI vs AutoGen

    LangGraph 不是唯一的 Agent 编排框架。把它放进竞技场,和 CrewAI、AutoGen 同台对比,更能看清各自的基因。

    5.1 三种哲学

    LangGraph CrewAI AutoGen
    隐喻 状态机——一切皆图 公司团队——一切皆角色 对话——一切皆消息
    控制方式 显式图和条件边 角色 + 任务 + 流程模式 多轮对话 + 发言策略
    状态 全局显式 TypedDict 任务间 context 传递 隐含在对话历史中
    适合谁 追求精确控制的架构师 快速验证想法的产品经理 研究型迭代的科学家

    CrewAI 的门槛最低——定义 Agent 的角色和背景故事,框架自动调度。AutoGen 则擅长需要代码执行和多轮对话优化的场景。LangGraph 的学习曲线最陡,但也赋予你最大的控制自由度。

    5.2 能力雷达图

                  可观测性
                      ▲
                      │ LangGraph ⭐⭐⭐⭐⭐
                      │
        状态持久化 ────┼──── 学习曲线(越低越好)
        LangGraph ✅   │      CrewAI ⭐⭐⭐⭐
        CrewAI   ⚠️    │      AutoGen ⭐⭐⭐
        AutoGen  ❌    │      LangGraph ⭐⭐
                      │
                      │
                  部署灵活性 ←──→ Token 效率
                                 LangGraph ⭐⭐⭐⭐⭐
                                 CrewAI   ⭐⭐⭐⭐
                                 AutoGen  ⭐⭐⭐
    

    具体到数字:同一任务,LangGraph 每次循环约 2000 tokens,CrewAI 约 3500,AutoGen 因对话式驱动常达 8000。在高频 Agent 调用场景中,Token 效率直接转化为成本差异。

    5.3 选型决策树

    你的场景需要什么?
           │
     ┌─────┼──────┬──────────┐
     ▼     ▼      ▼          ▼
    精确  角色化  代码执行   Microsoft
    控制  协作   迭代优化   生态集成
     │     │      │          │
     ▼     ▼      ▼          ▼
    Lang- CrewAI AutoGen  AutoGen/
    Graph              MAF
    

    关键更新:2025 年 10 月,Microsoft 将 AutoGen 与 Semantic Kernel 合并为 Microsoft Agent Framework(MAF)。AutoGen 不再作为独立库接收重大更新,但其对话驱动思想被 MAF 继承。


    6. 迁移路线:从旧世界到新世界

    如果你已有 LangChain 旧版(AgentExecutor)代码,官方推荐的演进路径很清晰:

    Step 0: AgentExecutor(旧版,2025 年前)
       │  隐藏的 agent_scratchpad,调试如盲人摸象
       │
       ▼
    Step 1: create_agent(LangChain v1.0,2025.10 起)
       │  4 行代码启动 Agent,底层跑 LangGraph
       │  适合 80% 的场景
       │
       ▼
    Step 2: 自定义 StateGraph(需要完全控制时)
          显式节点、条件边、检查点、HITL
          适合复杂生产系统
    

    判断标准极其简单:如果你的 Agent 需要——循环(重试 / “不够再搜”)、分支(不同输入不同路径)、中断(人工审批)、持久化(跨会话恢复)——四项中任何一项,就该写自定义 StateGraph。一项都不需要,create_agent 足够。

    6.1 增量迁移:2-4 周

    不推倒重来,而是渐进式把旧 Chain 包装为 LangGraph 节点:

    1. 识别现有代码中使用 while 循环或 if-elif 路由的变通方案
    2. 定义 TypedDict 状态模式,捕获所有数据流
    3. 将现有 Chain 包装为 LangGraph 节点函数
    4. 用条件边替换手动路由逻辑
    5. 接入 Checkpointer 以持久化状态

    6.2 全量重写:4-8 周

    适用于两种情况:代码库已被变通方案搞得难以维护,或正在从零构建新的多 Agent 系统。此时应直接从 StateGraph 起步,充分利用调试和可视化工具。


    7. 实战选型矩阵

    场景 LangChain LangGraph 推荐
    RAG 管道(检索→增强→生成) 首选 不必要 LangChain
    文本翻译 / 摘要 / 格式化 首选 过于复杂 LangChain
    单轮 Q&A(问 → 工具调用 → 答) create_agent 即可 底层运行中 LangChain create_agent
    快速原型 / PoC 更快 更慢 LangChain
    多步研究 Agent(搜→评→再搜→整合) 不足 必需 LangGraph
    条件分支(输入不同走不同路径) 不足 原生 LangGraph
    工具调用失败重试 变通方案 原生循环 LangGraph
    人工审批步骤(审核后继续) 不支持 interrupt() LangGraph
    长时间运行 Agent(跨会话) 不支持 Checkpointer LangGraph
    多 Agent 协作(Supervisor 模式) 部分支持 首选 LangGraph
    生产级可观测性(节点追踪) LangSmith LangSmith Studio 两者结合
    合规审计(每步可追溯) 不足 显式状态+检查点 LangGraph
    与 LangChain 生态集成 天然 无缝 两者皆可

    8. 2026 年的格局与趋势

    8.1 框架不是问题,可靠性才是

    LangChain 2026 年开发者调查显示:32% 的团队认为不可靠的性能是扩展 Agent AI 的最大障碍。框架选择排不进前四。 真正的问题是——Agent 能不能稳定产出正确结果,以及失败时能不能优雅恢复。

    这正是 LangGraph 发力的方向:通过 Checkpointer 做故障恢复,通过 interrupt() 做人机协同,通过七种流模式做可观测性。框架之争正在退潮,可靠性之争才是主战场。

    8.2 框架融合正在发生

    三大框架的优秀设计理念正在互相渗透:

    • LangGraph 的精确控制 → CrewAI v2 引入了 Flows(类图结构)
    • CrewAI 的角色隐喻 → LangGraph 社区发展出基于角色的多 Agent 模式
    • AutoGen 的对话驱动 → LangGraph 通过 Send API 支持动态消息路由

    框架选型越来越不是”三选一”,而是在理解各框架基因的基础上、根据场景需求做组合。

    8.3 最终建议

    用 LangChain 的地方:一切线性任务。翻译、摘要、RAG 管道、单轮 Q&A。LCEL 管道的简洁性在这些场景中无可替代。

    用 LangGraph 的地方:一切有循环、有分支、有中断、有多 Agent 的系统。研究型 Agent、客服流程、审批工作流、长时任务。

    用两者结合的地方:绝大多数生产系统。LangChain 提供组件集成和 create_agent 快速启动,LangGraph 提供状态管理和编排控制。它们本就是同一个栈的两个层,协同使用才是设计者的初衷。


    9. 结语

    回到文章开头的比喻:锤子和电钻。

    LangChain 是那把锤子——简单、直接、一锤定音。对于钉钉子的活(线性管道),它完美无缺。

    LangGraph 是那把电钻——需要学习、需要接线、一键启动不够。但当你面对钢筋水泥(循环、分支、持久化、多 Agent),它才是你手里能打的工具。

    真正成熟的工程师不会问”锤子和电钻哪个好”,他们会把两样都放进工具箱,然后根据眼前的活,伸手去拿对的那把。

    2026 年的 LLM 应用开发亦是如此。


    写作时间:2026 年 7 月
    主要参考:LangChain 官方文档、LangGraph 官方文档、Zilliz 技术博客、Atlan AI Agent Memory Guide、DigitalApplied 对比分析、掘金技术社区 Multi-Agent 框架横评
    风格:深度技术对比

    AI #LangChain #LangGraph #Agent #LLM #框架对比

    生成时间: 2026-07-06 20:34:08 · 源文件: langgraph_vs_langchain.md · SHA256: 106bbd94c6ad /* Auto-generate TOC from h1/h2/h3 headings */ (function() { const toc = document.getElementById(‘toc’); const headings = document.querySelectorAll(‘#content h1, #content h2, #content h3’); headings.forEach((h, i) => { if (i === 0 && h.tagName === ‘H1’) return; // skip title const id = ‘sec-‘ + i; h.id = id; const li = document.createElement(‘li’); const a = document.createElement(‘a’); a.href = ‘#’ + id; a.textContent = h.textContent; if (h.tagName === ‘H3’) { a.style.marginLeft = ‘1.25rem’; a.style.fontSize = ‘0.82rem’; } else if (h.tagName === ‘H2’) { a.style.fontWeight = ‘600’; } li.appendChild(a); toc.appendChild(li); }); })();

    发表回复

    人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 借一步网 🐾 智柴网 沪ICP备2024052574号-1