Agent 框架演进 - 从裸 SDK 到 LangGraph / The Evolution of Agent Frameworks from Raw SDKs to LangGraph
📅 创建时间:2026-05-08 🏷️ 标签:#LangChain #LangGraph #CrewAI #框架对比 📚 前置知识:[[01-function-calling]]
📋 本章目标
- 理解 Agent 框架演进的逻辑脉络
- 掌握 LangChain 的核心概念和使用方法
- 理解 LangChain 的局限性
- 掌握 LangGraph 的状态机编程模型
- 了解其他框架(CrewAI、AutoGen)的特点
- 能够根据场景选择合适的框架
- 理解 LangChain 与 LangGraph 的本质区别,以及它们与 Agent 循环的关系
- 理解为什么仅靠 LangChain 难以构建高质量的生产级 Agent
第1部分:为什么需要框架?
1.1 裸 SDK 的痛苦
直接用 OpenAI SDK 写一个稍微复杂的 Agent:
# 用裸 SDK 实现一个能查天气、发邮件的 Agent
# 你会发现代码很快变得难以维护
from openai import OpenAI
import json
client = OpenAI()
tools = [...]
def chat(user_input, messages=[]):
messages.append({"role": "user", "content": user_input})
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
if not assistant_message.tool_calls:
return assistant_message.content
# 处理工具调用
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# 开始出现大量 if/else
if function_name == "get_weather":
result = get_weather(function_args["city"])
elif function_name == "send_email":
result = send_email(function_args["to"], ...)
elif function_name == "search_database":
result = search_db(function_args["query"])
elif function_name == "get_current_time":
result = get_time()
# ... 工具越多,if/else 越多
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
# 没有循环终止保护
# 没有重试逻辑
# 没有状态管理裸 SDK 的问题:
┌─────────────────────────────────────────────────────────────┐
│ 裸 SDK 的问题 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 问题1:工具调用逻辑散落各处 │
│ 100 个工具 → 100 个 if/else │
│ 改一个工具 → 改多个地方 │
│ │
│ 问题2:没有循环终止机制 │
│ LLM 可能无限调用工具 │
│ │
│ 问题3:没有状态管理 │
│ 复杂流程的状态需要手动维护 │
│ │
│ 问题4:代码难以复用 │
│ 每个 Agent 都要重写一遍基础设施 │
│ │
│ 问题5:没有可视化 │
│ 流程是黑盒子,调试困难 │
│ │
└─────────────────────────────────────────────────────────────┘1.2 框架的价值
框架 = 封装通用逻辑 + 提供抽象接口 + 让开发者专注业务
┌─────────────────────────────────────────────────────────────┐
│ 框架的价值 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 开发者只关心: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 定义有哪些工具 │ │
│ │ • 编排工具的执行顺序 │ │
│ │ • 决定何时停止 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 框架帮你搞定: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 消息管理 │ │
│ │ • 循环控制 │ │
│ │ • 重试逻辑 │ │
│ │ • 状态持久化 │ │
│ │ • 工具路由 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘第2部分:LangChain 入门
2.1 LangChain 是什么?
LangChain = 帮你用模块化方式构建 LLM 应用的框架
┌─────────────────────────────────────────────────────────────┐
│ LangChain 核心模块 │
├─────────────────────────────────────────────────────────────┤
│ │
│ LangChain = LangChain Core(核心)+ 各种扩展 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Model I/O → Prompt 模板、模型调用、输出解析 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Retrieval → 文档加载、分割、向量存储、检索 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Chains → 把多个步骤串起来的执行链 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Agents → LLM + Tools 的编排逻辑 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Memory → 对话历史管理 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Callbacks → 日志、监控、追踪 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2.2 LangChain 的核心概念
概念1:Prompt 模板(PromptTemplate)
from langchain.prompts import PromptTemplate
# 定义可复用的 Prompt 模板
translator_template = PromptTemplate.from_template(
"""将以下{input_language}文本翻译成{output_language}。
要求:
1. 翻译要地道
2. 保持原文语气
3. 不确定的地方标注[待确认]
文本:
{text}
翻译:"""
)
prompt = translator_template.invoke({
"input_language": "中文",
"output_language": "英文",
"text": "这个项目太棒了"
})概念2:输出解析器(Output Parser)
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel
class WeatherInfo(BaseModel):
city: str
temperature: float
condition: str
parser = PydanticOutputParser(pydantic_object=WeatherInfo)
prompt = PromptTemplate.from_template(
"""提取天气信息:
{query}
{format_instructions}""",
partial_variables={"format_instructions": parser.get_format_instructions()}
)
# 结果直接被解析成 WeatherInfo 对象概念3:Chain(链)
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
llm = ChatOpenAI(model="gpt-4o")
# 把 Prompt 模板和 LLM 串成一个链
chain = LLMChain(
llm=llm,
prompt=translator_template
)
# 一行调用
result = chain.invoke({"input_language": "中文", "output_language": "日文", "text": "你好世界"})概念4:Agent(智能体)
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
# 定义工具
tools = [get_weather, send_email, search_database]
# 创建 Agent(自动处理工具调用循环)
agent = create_openai_functions_agent(llm, tools, system_message)
agent_executor = AgentExecutor(agent=agent, tools=tools)
# 一行调用,内部自动处理多轮工具调用
result = agent_executor.invoke({"input": "北京天气怎么样?顺便发给老板"})2.3 LangChain 的优势
优势1:模块化
┌─────────────────────────────────────────────────────────────┐
│ Prompt 模板 → LLM → 输出解析器 │
│ 每个模块独立,可复用,可替换 │
└─────────────────────────────────────────────────────────────┘
优势2:丰富的生态
┌─────────────────────────────────────────────────────────────┐
│ • 内置 100+ 种 Document Loader │
│ • 支持 50+ 种向量数据库 │
│ • 预置常用 Chains(Summarization、Q&A、SQL 等) │
└─────────────────────────────────────────────────────────────┘
优势3:开箱即用的 Agent
┌─────────────────────────────────────────────────────────────┐
│ create_openai_functions_agent() │
│ → 自动处理工具调用循环 │
│ → 自动管理消息历史 │
│ → 自动处理工具返回结果 │
└─────────────────────────────────────────────────────────────┘第3部分:LangChain 的问题
3.1 开发者吐槽
┌─────────────────────────────────────────────────────────────┐
│ LangChain 被吐槽最多的问题 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 问题1:版本不稳定(v0.1 → v0.2 → 0.3 大量 breaking change)│
│ 问题2:过度抽象(想看源码理解原理,结果发现绕了好几层) │
│ 问题3:文档和代码不一致(文档写的 API 跟实际代码对不上) │
│ 问题4:包体积大(import 慢,开发体验差) │
│ 问题5:调试困难(链太长时不知道哪一步出了问题) │
│ 问题6:抽象泄漏(遇到边界情况不得不绕过框架) │
│ │
└─────────────────────────────────────────────────────────────┘3.2 LangChain 什么时候用?什么时候不用?
┌─────────────────────────────────────────────────────────────┐
│ LangChain 选型指南 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 推荐用 LangChain 的场景: │
│ • 快速原型验证 │
│ • 简单 RAG 流程 │
│ • 标准化的 Chains(摘要、问答、SQL 生成) │
│ • 需要对接多种数据源(PDF、网页、数据库) │
│ │
│ ❌ 不推荐用 LangChain 的场景: │
│ • 复杂的状态机逻辑 │
│ • 需要精细控制执行流程 │
│ • 性能和包体积敏感的项目 │
│ • 团队技术水平高,能自己搭基础 │
│ │
└─────────────────────────────────────────────────────────────┘第4部分:LangGraph 登场
4.1 为什么需要 LangGraph?
LangChain 的问题是:流程是"线性的"
LangChain Chain:
Input → Step1 → Step2 → Step3 → Output
↑
只能一条道走到黑现实中的 Agent 流程是"图"(有分支、有循环)
LangGraph:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ │
│ │ 开始 │ │
│ └────┬─────┘ │
│ ↓ │
│ ┌─────────▼─────────┐ │
│ │ LLM 决定下一步 │ │
│ └─────────┬─────────┘ │
│ ↓ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ ↓ ↓ │
│ ┌──────┐ ┌────────┐ │
│ │查天气 │ │ 发邮件 │ │
│ └──┬───┘ └───┬────┘ │
│ ↓ ↓ │
│ └────────┬──────────┘ │
│ ↓ │
│ ┌───────▼───────┐ │
│ │ 结束 or 继续? │ ← 有循环 │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘4.2 LangGraph 核心概念
三个核心概念:State(状态)+ Node(节点)+ Edge(边)
┌─────────────────────────────────────────────────────────────┐
│ LangGraph 三要素 │
├─────────────────────────────────────────────────────────────┤
│ │
│ State(状态) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个 dict,包含流程中的所有共享数据 │ │
│ │ 例如:messages、current_step、result │ │
│ │ state = {"messages": [...], "steps": 0} │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Node(节点) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个 Python 函数,接收当前 state,返回更新后的 state │ │
│ │ def my_node(state): │ │
│ │ return {"new_field": "value"} │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Edge(边) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 定义节点之间的连接关系 │ │
│ │ • 普通边(无条件跳转) │ │
│ │ • 条件边(根据 state 条件判断跳哪) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘4.3 LangGraph 实战示例
from langgraph.graph import StateGraph, END
from typing import TypedDict
# Step 1: 定义 State
class AgentState(TypedDict):
messages: list
next_action: str
# Step 2: 定义 Node(节点函数)
def llm_decide(state: AgentState):
"""LLM 决定下一步做什么"""
response = llm_with_tools.invoke(state["messages"])
return {"messages": [response], "next_action": "call_tool"}
def execute_tool(state: AgentState):
"""执行工具"""
last_msg = state["messages"][-1]
if last_msg.tool_calls:
tool_result = run_tool(last_msg.tool_calls[0])
return {"messages": [{"role": "tool", "content": tool_result}]}
return {"messages": [], "next_action": "end"}
def should_continue(state: AgentState):
"""条件边:根据 state 决定下一步"""
if state["next_action"] == "end":
return "end"
return "continue"
# Step 3: 构建图
graph = StateGraph(AgentState)
graph.add_node("llm_decide", llm_decide)
graph.add_node("execute_tool", execute_tool)
# Step 4: 定义边
graph.set_entry_point("llm_decide")
graph.add_edge("llm_decide", "execute_tool")
graph.add_conditional_edges(
"execute_tool",
should_continue,
{"continue": "llm_decide", "end": END}
)
# Step 5: 编译并运行
app = graph.compile()
result = app.invoke({"messages": [{"role": "user", "content": "查下北京天气"}]})4.4 LangGraph 的优势
┌─────────────────────────────────────────────────────────────┐
│ LangGraph 的优势 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 状态显式管理 │
│ 每一步的状态都清晰可见,方便调试 │
│ │
│ 2. 支持循环 │
│ Agent 的核心就是"思考→行动→观察→再思考"的循环 │
│ LangGraph 原生支持 │
│ │
│ 3. 支持分支 │
│ 根据条件走向不同路径 │
│ │
│ 4. 可视化 │
│ 可以把图导出为图片,直观看到流程 │
│ │
│ 5. 透明可控 │
│ 不过度抽象,每个步骤都是普通 Python 函数 │
│ │
└─────────────────────────────────────────────────────────────┘第5部分:深入理解——LangChain 与 LangGraph 的本质区别
5.1 回到原点:它们都在做同一件事
不管 LangChain 还是 LangGraph,本质上都是在包装[[01-function-calling|上一篇文章]]里讲的那个 Agent 循环:
LLM 决策 → 检查是否调工具 → 执行工具 → 结果返回 LLM → 再决策 → ...这个循环用裸 SDK 写就是一个 while 循环。LangChain 和 LangGraph 没有发明新东西,它们只是在用不同的方式组织这同一个循环。
三者的对应关系:
裸 SDK:
你手写 while 循环 + if/elif 工具路由 + 手动管理 messages
LangChain:
AgentExecutor 把整个 while 循环包起来,你只需要给 tools 和 prompt
LangGraph:
把循环展开成图(Node + Edge),你显式定义每一步和它们之间的连线三者在能力上没有本质区别——都能实现同样的 Agent。区别在于怎么组织代码,以及在复杂场景下的可维护性。
5.2 同一个 Agent,三种写法
以"LLM 决策 → 调工具 or 回答 → 调完回 LLM"为例:
| 维度 | 裸 SDK | LangChain | LangGraph |
|---|---|---|---|
| 循环控制 | 手写 while + break | AgentExecutor 内置 | 图的 Edge 定义 |
| 工具路由 | if/elif 链 | AgentExecutor 内置 | Node 函数里处理 |
| 状态管理 | 手动维护 messages 列表 | 框架隐式管理 | State 对象显式传递 |
| 插入新步骤 | 改循环体代码 | 改回调或绕框架 | 加一个 Node + Edge |
| 流程可见性 | 读代码靠脑补 | 读代码靠脑补 | 图结构可视化 |
| 调试手段 | print 大法 | LangSmith trace | Node 函数断点 + 图导出 |
| 起步速度 | 慢 | 快 | 中等 |
| 复杂场景 | 代码膨胀快 | 框架反成障碍 | 优势明显 |
5.3 LangGraph 是 LangChain 的"升级版"吗?
一个常见的误解是"LangGraph = LangChain 2.0"或"学 LangGraph 就不用学 LangChain 了"。实际情况是:它们是同一个公司做的两种不同哲学的产品,不是 v1 → v2 的替代关系。
LangChain 的哲学:
"我帮你搞定"——把循环藏起来,减少重复代码
理想用户:快速验证想法,不想写样板代码
LangGraph 的哲学:
"我帮你把流程画清楚"——让你自己写 Node、连 Edge
理想用户:需要精确控制流程,不怕写代码怕流程乱更深一层说,二者解决的是不同层次的问题:
LangChain 解决"代码层面"的复杂度:你不用写消息管理、不用写工具路由 if/elif、不用写重试逻辑。它帮你省代码行数。
LangGraph 解决"流程层面"的复杂度:当 Agent 的行为不是简单的直线,而是"先查,查不到就搜,搜到就总结,总结完让另一个 Agent 审核,不通过就重写"这种有分支有回环的图时,代码行数已经不是主要矛盾了。主要矛盾是你根本看不清这个流程长什么样。
LangGraph 的实质就是把一个 while 循环里散落的状态管理和条件判断,变成了一张显式的、可视化的、可插拔的图。
两者也不是完全割裂的——LangGraph 底层依赖了 LangChain Core 的一些基础组件(消息类型、LLM 封装等)。它们是同一个工具箱里两把不同用途的螺丝刀。
5.4 为什么仅靠 LangChain 很难写出高质量的生产级 Agent?
这个问题不是"LangChain 还不够完善",而是它的设计基因决定的。LangChain 的 AgentExecutor 是一个预设好路线的自动驾驶——它在常规道路上开得很好,但一旦遇到施工绕路、临时封道,方向盘藏在引擎盖下面,你很难够到。
生产级 Agent 通常会遇到的几个 LangChain 处理不好的需求:
需要中途人审批。 Agent 生成了一封邮件草稿,需要用户点"确认发送"才真的调用 send_email。LangChain 的 AgentExecutor 是一个封闭的 while 循环,它不会在中间停下来等你——你得绕一大圈用回调或者强行改源码。而 LangGraph 的做法是在图里加一个 wait_for_human 节点,循环自然就停在那了——因为图本来就是你画的,你想在哪停就在哪停。
出错后要根据错误类型走不同分支。 调 API 超时 → 重试,权限不足 → 升权申请,数据不存在 → 换一个搜索关键词。LangChain 的错误处理是统一的 try/except 包在最外层,粒度太粗。图结构下你可以在每个节点后面加一条条件边,不同的错误导向不同的恢复路径。
实时推送中间状态。 用户不想盯着空白页面等 Agent 跑完,他想看到"正在搜索数据库...找到 3 条结果...正在总结..."。LangChain 可以借助回调流式推送,但你很难精确控制每一步推什么。LangGraph 在每个 Node 函数里 yield 一个状态更新就行了——因为每个 Node 的执行时机是你自己定义的。
总结:LangChain 适合快速验证"这个 Agent 思路能不能跑通",但要做生产级 Agent,你需要能精确控制每一步的执行流程。
第6部分:其他框架简介
5.1 CrewAI
定位:多 Agent 协作框架,专注于角色和任务分配
from crewai import Agent, Task, Crew
# 定义 Agent(角色)
researcher = Agent(
role="研究员",
goal="获取最新的 AI 技术动态",
backstory="你是一个专业的 AI 研究员"
)
writer = Agent(
role="内容编辑",
goal="把研究内容整理成易读的文章",
backstory="你是一个资深编辑,擅长将技术内容通俗化"
)
# 定义任务
task1 = Task(description="搜索并总结本周 AI 领域的重要进展", agent=researcher)
task2 = Task(description="将总结写成一篇 1000 字的文章", agent=writer)
# 创建 Crew 并执行
crew = Crew(agents=[researcher, writer], tasks=[task1, task2])
result = crew.kickoff()CrewAI 适用场景:多角色、多任务、需要流水线协作的场景
5.2 AutoGen(微软)
定位:多 Agent 对话框架,强调 Agent 之间的协商
import autogen
assistant = autogen.AssistantAgent(
name="assistant",
system_message="你是一个代码助手"
)
user_proxy = autogen.UserProxyAgent(
name="user_proxy",
code_execution_config={"work_dir": "coding"}
)
# 两个 Agent 开始对话
chat_result = user_proxy.initiate_chat(
assistant,
message="帮我写一个快速排序算法并运行"
)AutoGen 适用场景:需要 Agent 之间深度协作、协商的场景
6.3 框架对比
┌─────────────────────────────────────────────────────────────┐
│ 框架横向对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ │ 特性 │ LangChain │ LangGraph │ CrewAI │ AutoGen │
│ ├─────────────┼───────────┼───────────┼────────┼─────────┤
│ │ 上手难度 │ 中等 │ 较高 │ 简单 │ 中等 │
│ │ 状态管理 │ 隐式 │ 显式 │ 隐式 │ 隐式 │
│ │ 循环支持 │ 一般 │ 原生 │ 一般 │ 一般 │
│ │ 多 Agent │ 一般 │ 好 │ 优秀 │ 优秀 │
│ │ 可视化 │ 一般 │ 优秀 │ 一般 │ 一般 │
│ │ 生态 │ 丰富 │ 一般 │ 增长中 │ 增长中 │
│ │ 稳定性 │ 较差 │ 好 │ 一般 │ 一般 │
│ │
│ 推荐: │
│ • 快速原型 → LangChain │
│ • 复杂 Agent → LangGraph │
│ • 多 Agent 协作 → CrewAI 或 AutoGen │
│ • 生产级项目 → 考虑直接用 SDK + 自研 │
│ │
└─────────────────────────────────────────────────────────────┘核心总结
总结1:框架演进脉络
裸 SDK(什么都自己写)
↓
LangChain(封装通用逻辑,但过度抽象)
↓
LangGraph(显式状态机,回归透明可控)
↓
CrewAI / AutoGen(专注多 Agent 协作)总结2:选型建议
| 场景 | 推荐 |
|---|---|
| 快速验证想法 | LangChain |
| 复杂 Agent 流程 | LangGraph |
| 多 Agent 协作 | CrewAI / AutoGen |
| 生产级、长期维护 | SDK + 自研或 LangGraph |
总结3:LangChain 与 LangGraph 的本质区别
相同点:二者本质上都在包装 Agent 循环(LLM 决策 → 调工具 → 返回结果 → 循环)
不同点:
LangChain → 把循环"藏起来"(AgentExecutor),帮你省代码
LangGraph → 把循环"画出来"(图结构),让流程可见可控
LangGraph 不是 LangChain 的升级替代,而是另一种哲学的产品:
LangChain 解决"代码层面"的复杂度
LangGraph 解决"流程层面"的复杂度生产级 Agent 为什么需要 LangGraph(或自研循环)而不是 LangChain:
- 需要中途人审批 → LangChain 的封闭循环停不下来
- 出错后要根据错误类型走不同分支 → LangChain 的 try/except 粒度太粗
- 需要实时推送中间状态 → 图结构下每个 Node 的执行时机由你定义
总结4:LangGraph 三要素
State = 共享数据(dict)
Node = 处理函数(接收 state,返回更新)
Edge = 连接关系(普通边 / 条件边)章节测试
测试1:LangChain 的核心问题
LangChain 最被开发者诟病的三个问题是什么?
测试2:LangGraph vs LangChain
LangGraph 和 LangChain 的核心区别是什么?
测试3:状态管理
在 LangGraph 中,State 的作用是什么?
测试4:选型
如果要构建一个需要多个专业 Agent 协作(如研究员 + 写手 + 审核员)的系统,应该选哪个框架?
测试5:概念对应
请将以下概念和其在 LangGraph 中的对应物连线:
| 概念 | LangGraph 对应 |
|---|---|
| 共享数据 | ? |
| 处理函数 | ? |
| 连接关系 | ? |
测试6:LangGraph 与 LangChain 的关系
LangGraph 是 LangChain 的"升级版"吗?请简述二者的关系。
测试7:生产级 Agent
为什么仅靠 LangChain 很难写出高质量的生产级 Agent?举出至少两个具体场景。
参考答案
测试1答案
答案:
- 版本不稳定(breaking change 频繁)
- 过度抽象(难以理解和调试)
- 文档和代码不一致
测试2答案
答案:LangChain 的流程是线性的(Chain),适合简单的顺序执行;LangGraph 的流程是图结构(Graph),原生支持循环和条件分支,更适合复杂的 Agent 流程。
测试3答案
答案:State 是一个 TypedDict,用于在整个流程中传递和管理共享数据。每个 Node 函数接收当前 State,进行处理后返回更新后的 State,Graph 自动合并更新。
测试4答案
答案:CrewAI(专为多 Agent 协作设计,角色和任务概念清晰)或 AutoGen(支持 Agent 之间的协商对话)。
测试5答案
| 概念 | LangGraph 对应 |
|---|---|
| 共享数据 | State |
| 处理函数 | Node |
| 连接关系 | Edge |
测试6答案
答案:不是升级版。LangGraph 是同一家公司做的另一种哲学的产品。
解析:
LangChain 的哲学是"我帮你搞定"——AgentExecutor 把循环藏起来,减少样板代码。
LangGraph 的哲学是"我帮你把流程画清楚"——你自己写 Node、连 Edge,框架不藏任何东西。
二者不是 v1→v2 的替代关系,而是解决不同层次的问题:
LangChain 解决"代码层面"的复杂度(省代码行数)
LangGraph 解决"流程层面"的复杂度(让复杂流程可见、可改、可调试)
一个简单的 RAG 问答用 LangChain 几行搞定,上 LangGraph 反而小题大做。
一个复杂的多 Agent 协作流程 LangChain 根本画不出来,只能上 LangGraph。测试7答案
答案:LangChain 的 AgentExecutor 是封闭的 while 循环,很难在中途介入控制。
典型场景:
- 中途需要人审批:Agent 生成邮件草稿后需要用户点"确认"才发送。AgentExecutor 的封闭循环不会停下来等你。
- 根据错误类型走不同分支:API 超时 → 重试,权限不足 → 升权,数据不存在 → 换搜索词。LangChain 的 try/except 统一包在最外层,粒度太粗无法区分。
- 实时推送中间状态:用户希望看到每步进展。LangChain 用回调可以推流式 token,但在每个步骤之间精确插入状态更新很困难。
相关笔记
- [[01-function-calling]] - 框架底层依赖的 Tool Calling 机制
- [[05-agent-workflow]] - LangGraph 在工作流中的具体应用
- [[06-multi-agent]] - 多 Agent 协作框架 CrewAI/AutoGen
下一步学习
- [ ] 阅读 03 - RAG 基础
学习状态:🟡 开始学习