LangChain、LangGraph 和 Deep Agent 基础概念详解
这些概念是构建智能代理系统的核心构建块,从简单函数到复杂多代理协作,每一层都有明确分工,帮助你从新手快速进阶到构建生产级应用。
想象你正在构建一个智能助手,它能帮你查天气、发邮件、管理日程。这个助手不是一个"全能超人",而是一个高效团队:每个人负责特定任务,通过清晰的沟通协作完成复杂工作。
LangChain 1.x 架构全景
用户输入 → create_agent() → [Middleware层] → LangGraph执行图
↓
[Agent循环: LLM → Tools → 判断继续/结束]
↓
[节点: llm_node | tools_node | 自定义节点]
↓
[子图: Subgraphs作为节点,支持多层嵌套]详细概念对比(LangChain 1.x)
| 概念 | 定义 | 作用域 | LangChain 1.x实现 | 示例场景 |
|---|---|---|---|---|
| 函数 | 最基础的执行单元 | 代码层 | 普通Python函数 | multiply(a, b) 计算乘法 |
| 工具 | 原子能力,LLM调用的函数 | Agent内 | @tool装饰器,bind_tools()绑定 | get_weather(city)、数据库查询 |
| 节点 | 图执行单元,单步函数 | 图内部 | StateGraph.add_node(name, func) | llm_node(决策)、tools_node(执行) |
| Agent | 完整智能体,LLM+工具+状态管理 | 顶层入口 | create_agent(model, tools, middleware) | 财务分析代理:查询数据→计算→生成报告 |
| ReAct Agent | 思考+行动循环代理 | 顶层入口 | create_agent() 默认模式 | 数学解题、代码调试 |
| Subagent | 子代理,独立执行单元 | 图内节点 | Subgraph(独立StateGraph,作为主图节点) | 研究代理→调用"数据清洗子代理" |
| Supervisor | 团队领导,协调多代理 | 顶层入口 | 主Agent调用子Agent工具 | 个人助理分发任务给天气/日程专家 |
| Deep Agent | 深度思考代理 | 顶层入口 | 内置规划、文件系统、子代理 | 复杂项目规划、行程安排 |
🛠️ 1. 函数 (Functions) - 团队里的"执行工"
函数是最基础的"执行单元",就像工厂里的工人,接收指令、完成具体任务、返回结果。
在 LangChain/LangGraph 中,函数是所有复杂系统的原子单位。它们可以是:
- 简单的计算:加减乘除
- 外部API调用:天气查询、数据库操作
- 文件处理:读写JSON、调用Shell命令
为什么重要? 复杂代理 = 多个简单函数的组合。函数做好"单一职责",代理才能高效协作。
通俗比喻
用户说:"帮我算 15 * 3"
↓
函数就像计算器,按下按钮,输出"45"
↓
代理拿到结果,继续下一步简单案例:计算器函数
from langchain.tools import tool # @tool 装饰器让函数变成"智能工具"
@tool # 自动生成工具描述,LLM能理解
def multiply(a: int, b: int) -> int:
"""两个数的乘法计算。输入两个整数,返回乘积。
Args:
a: 第一个数
b: 第二个数
"""
return a * b
@tool
def add(a: int, b: int) -> int:
"""两个数的加法计算。输入两个整数,返回和。"""
return a + b
# 测试
result = multiply(15, 3)
print(result) # 输出: 45关键点:
@tool装饰器让普通函数变成LLM能调用的工具- 类型注解(
int)自动生成输入 schema,防止LLM传错参数 - Docstring 是给LLM的"使用说明书"
🔧 2. 工具 (Tools) - 函数的"智能包装"
工具 = 函数 + LLM友好描述 + 输入验证,是代理与世界的接口。
函数只是代码,工具是让LLM"理解并安全调用"的封装。就像手机App:函数是底层代码,工具是用户界面。
工具 vs 函数对比
| 区别 | 函数 | 工具 |
|---|---|---|
| LLM能否调用 | ❌ 需要手动绑定 | ✅ 自动识别 |
| 输入验证 | ❌ 容易传错参数 | ✅ 类型检查 |
| 描述信息 | ❌ 无 | ✅ Docstring指导 |
| 错误处理 | ❌ 容易崩溃 | ✅ 标准化返回 |
完整工具案例:天气查询工具
import requests
from pydantic import BaseModel, Field
from langchain_core.tools import tool
from typing import Literal
class WeatherInput(BaseModel): # 复杂输入schema
"""天气查询输入格式"""
city: str = Field(..., description="城市名称,如:北京、上海")
units: Literal["celsius", "fahrenheit"] = Field(
default="celsius", description="温度单位"
)
@tool(args_schema=WeatherInput) # Pydantic验证输入
def get_weather(city: str, units: str = "celsius") -> str:
"""获取指定城市的实时天气。
记住:始终返回结构化结果,包括温度、天气状况、湿度。
"""
# 模拟API调用
fake_data = {
"city": city,
"temp": 25 if units == "celsius" else 77,
"condition": "晴天",
"humidity": "60%"
}
return f"{city} 当前天气:{fake_data['temp']}°{units[0].upper()},{fake_data['condition']},湿度{fake_data['humidity']}"
# LLM看到这个工具:
# {
# "name": "get_weather",
# "description": "获取指定城市的实时天气...",
# "inputSchema": {...}
# }Q: 为什么工具的描述(docstring)这么重要?
A: LLM 不会执行代码,它只能"阅读"工具的描述来决定用不用。就像招聘时看简历:
❌ 差的描述:def calculate(x) # LLM 不知道这是干嘛的
✅ 好的描述:def calculate(expression: str) -> float:
"""计算数学表达式,支持 + - * / 和括号"""🎯 3. 节点 (Nodes) - LangGraph的"工作站"
节点是LangGraph图中的执行单元,每个节点专注一个任务,状态在节点间传递。
LangGraph把复杂流程变成"有向图":节点=工作站,边=数据流。就像流水线工厂,每个工位处理一部分,最终组装成品。
节点核心概念
状态(State) → 节点A → 更新状态 → 节点B → ... → 最终输出节点 vs 工具的区别
| 概念 | 比喻 | 谁调用 | 例子 |
|---|---|---|---|
| 工具 | 技能 | LLM 决定调用 | get_weather("北京") |
| 节点 | 流程步骤 | 图的边决定执行顺序 | llm_node、tools_node |
简单计算器图案例
from typing_extensions import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
import operator
from langchain_core.tools import tool
# 1. 定义状态:图中传递的数据结构
class CalculatorState(TypedDict):
input: str # 用户输入
result: float # 计算结果
operations: list[str] # 执行历史
messages: Annotated[list, operator.add] # 对话历史(自动追加)
# 2. 定义节点:接收状态,返回更新
def calculator_node(state: CalculatorState):
"""计算节点:解析输入,调用工具"""
input_str = state["input"]
# LLM决定调用哪个工具(简化版)
if "乘" in input_str or "*" in input_str:
nums = extract_numbers(input_str) # 提取数字
result = multiply(*nums)
return {
"result": result,
"operations": state["operations"] + [f"乘法: {nums} = {result}"]
}
# ... 其他运算
# 3. 构建图
workflow = StateGraph(CalculatorState)
workflow.add_node("calculator", calculator_node) # 添加节点
workflow.add_edge(START, "calculator") # 从开始到计算器
workflow.add_edge("calculator", END) # 计算完结束
graph = workflow.compile()节点参数详解:
def my_node(
state: CalculatorState, # 当前图状态
config: RunnableConfig, # 配置(thread_id, tags等)
runtime: Runtime # 运行时上下文(可选)
) -> dict: # 返回状态更新
pass🤖 4. Agent - "智能决策者"
Agent = LLM + 工具 + 循环决策,是"会思考的执行者"。
代理的核心循环:
观察环境 → LLM思考 → 选择工具/回应 → 执行 → 观察新状态 → 重复🎭 用"公司"来理解 Agent 架构
想象一家公司的运作方式:
┌─────────────────────────────────────────────────────────────────┐
│ 🏢 公司 = Agent │
│ │
│ CEO(LLM) │
│ │ │
│ ├── 📋 决策:分析问题,决定谁来做什么 │
│ ├── 🛠️ 工具 = 员工的技能(打电话、发邮件、查数据库) │
│ ├── 📊 节点 = 工作流程的每个步骤 │
│ └── 🏢 子公司 = Subagent(独立运作,汇报结果) │
│ │
└─────────────────────────────────────────────────────────────────┘Agent类型对比
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 简单Agent | 单轮调用工具 | 天气查询、翻译 |
| ReAct Agent | 思考+行动循环 | 数学解题、代码调试 |
| Supervisor | 协调多子代理 | 团队协作任务 |
| Deep Agent | 规划+文件+子代理 | 复杂项目、行程规划 |
基础Agent案例
from langchain_openai import ChatOpenAI
from langchain import create_agent
llm = ChatOpenAI(model="gpt-4o-mini")
# 工具集
tools = [multiply, add, get_weather]
# 创建代理
agent = create_agent(
model=llm,
tools=tools,
system_prompt="你是数学&天气助手。用中文回答。"
)
result = agent.invoke({
"messages": [{"role": "user", "content": "15乘3是多少?北京天气如何?"}]
})Agent 和普通的 LLM 调用有什么区别?
| 普通 LLM 调用 | Agent |
|---|---|
| 一问一答 | 多轮思考 |
| 只能生成文本 | 可以调用工具 |
| 无记忆 | 有状态管理 |
| 人类决定下一步 | 自主决定下一步 |
# 普通调用
response = llm.invoke("北京天气如何?") # 只能瞎猜
# Agent 调用
result = agent.invoke("北京天气如何?")
# Agent 会:1. 识别需要查天气 2. 调用 get_weather 3. 整理结果回答🔄 5. ReAct Agent - "思考+行动"循环代理
ReAct = Reasoning (思考) + Acting (行动),最经典的代理架构。
ReAct思想: LLM不直接回答,而是思考→行动→观察→重复,直到解决问题。
ReAct执行流程图
用户:"帮我算 (15+3)*4"
LLM思考:"先加15+3=18,再乘4"
↓ 行动:调用add(15,3)
↓ 观察:结果18
↓ 思考:"现在18*4"
↓ 行动:调用multiply(18,4)
↓ 观察:结果72
↓ 最终回答:"答案是72"ReAct完整代码
from langchain import create_agent
from langchain_core.messages import HumanMessage
agent = create_agent(
model=llm,
tools=[add, multiply, get_weather],
system_prompt="""你是一个精确的计算助手。
遵循ReAct模式:
1. 先思考需要什么步骤
2. 调用工具执行
3. 根据结果继续思考
4. 直到得出最终答案"""
)
result = agent.invoke({
"messages": [HumanMessage("计算 (15+3)*4,然后告诉我结果")]
})
print(result["messages"][-1].content) # "经过计算,(15+3)*4 = 72"🧠 6. Deep Agent - "深度思考代理" (LangChain v1新特性)
Deep Agent是处理复杂多步任务的"高级大脑",内置规划、文件系统、子代理生成。
Deep Agent三大超能力:
- 自动规划:
write_todos工具,自动分解复杂任务 - 文件系统:
ls/read/write/edit工具,管理长期记忆 - 子代理:
task工具,生成专家子代理
Deep Agent使用场景
普通Agent: "查北京天气" → 直接调用工具
Deep Agent: "帮我规划一周北京行程" →
1. 写todo:查天气/订酒店/安排景点
2. 生成天气子代理/酒店子代理
3. 写文件保存行程表
4. 汇总最终方案Deep Agent快速开始
from deepagents import create_deep_agent # 新库!
deep_agent = create_deep_agent(
model="claude-sonnet-4-5", # 推荐强推理模型
# 自动包含todo/file/subagent中间件
)
result = deep_agent.invoke({
"messages": [{"role": "user", "content": "帮我规划北京3天行程"}]
})Deep Agent自动生成的Todo示例:
1. ✅ 查询北京3天天气预报
2. 🔄 推荐3个必去景点(基于天气)
3. 🔄 制定每日行程表
4. 🔄 计算大致预算
5. 🔄 输出最终方案到文件Deep Agent 状态管理机制
DeepAgent 的状态管理基于 LangGraph 的标准机制,默认使用 TypedDict 状态 schema + MemorySaver checkpointer 自动持久化,支持完全手动管理,并能与 Supervisor 无缝协同。
DeepAgent 是基于 LangGraph 的高级代理库,默认包含 TodoListMiddleware、FilesystemMiddleware、SubAgentMiddleware,构建在标准 LangGraph state 之上。
1. 默认状态管理方式
from typing_extensions import TypedDict, Annotated
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import MemorySaver
# 默认状态 schema(TypedDict)
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages] # 对话历史
todos: list[str] # 待办列表(TodoListMiddleware)
filesystem: dict # 文件系统状态(FilesystemMiddleware)
# 默认使用 MemorySaver 自动持久化
checkpointer = MemorySaver()
agent = create_deep_agent(model="claude-sonnet-4-5-20250929", checkpointer=checkpointer)默认行为:
- 短时状态:
todos、filesystem等存储在当前 thread 的 graph state - 长时内存:通过
StoreBackend持久化到/memories/路径,支持跨 thread
# 长时内存配置(CompositeBackend)
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
store = InMemoryStore() # 或 PostgresStore 等
backend = CompositeBackend(
default=StateBackend(runtime), # 临时状态
routes={"/memories/": StoreBackend(runtime)} # 持久化内存
)2. 手动状态管理
完全支持手动控制,通过 LangGraph API:
# 自定义状态 schema
class CustomDeepAgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
todos: list[str]
research_data: dict # 自定义研究数据
user_preferences: dict # 用户偏好
# 手动编译 graph
graph = StateGraph(CustomDeepAgentState)
graph.add_node("deep_agent", deep_agent_node)
graph.add_edge(START, "deep_agent")
# 手动管理 checkpointer
checkpointer = MemorySaver()
compiled_graph = graph.compile(checkpointer=checkpointer)
# 手动获取/更新状态
config = {"configurable": {"thread_id": "user_123"}}
state = compiled_graph.get_state(config) # 获取当前状态
# 手动更新状态
updated_state = compiled_graph.update_state(
config,
{"research_data": {"key": "value"}}
)
# 手动调用
result = compiled_graph.invoke({"messages": [...]}, config)3. DeepAgent 与 Supervisor 协同
DeepAgent 天然就是 Supervisor,通过内置 SubAgentMiddleware 的 task 工具调用子代理:
# DeepAgent(主管)配置子代理
deep_supervisor = create_deep_agent(
model="claude-sonnet-4-5-20250929",
middleware=[
SubAgentMiddleware(
subagents=[
{
"name": "researcher", # 研究子代理
"description": "进行深入研究",
"tools": [web_search, read_file],
"system_prompt": "你是研究专家..."
},
{
"name": "coder", # 编码子代理
"description": "编写和调试代码",
"tools": [write_file, shell_exec],
"system_prompt": "你是资深工程师..."
}
]
)
]
)
# DeepAgent 自动调用子代理(上下文隔离)
result = deep_supervisor.invoke({
"messages": [{"role": "user", "content": "研究并实现用户认证系统"}]
})双向协同(Supervisor 调用 DeepAgent):
# 传统 Supervisor 将 DeepAgent 作为工具
@tool("deep_research", "调用深度研究代理")
def call_deep_agent(query: str) -> str:
deep_agent = create_deep_agent(...) # 独立的 DeepAgent
result = deep_agent.invoke({"messages": [{"role": "user", "content": query}]})
return result["messages"][-1].content
supervisor = create_agent(
model="gpt-4o",
tools=[call_deep_agent, other_tools]
)4. 状态共享模式
共享状态(推荐用于协同):
class SharedState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
todos: list[str]
research_findings: dict # DeepAgent 研究结果
# Supervisor 和 DeepAgent 共享状态
supervisor_graph.add_node("deep_research", deep_agent_graph)隔离状态(DeepAgent 子代理默认):
# SubAgentMiddleware 默认隔离子代理状态
# Supervisor 只接收最终结果,中间状态不污染主上下文状态管理总结:
| 模式 | 说明 |
|---|---|
| 默认 | TypedDict + MemorySaver 自动管理 |
| 手动 | 完整 LangGraph API 控制 |
| 协同 | DeepAgent 内置 Supervisor 能力,或被 Supervisor 作为工具调用 |
| 灵活 | 短时状态(graph state)+ 长时内存(StoreBackend) |
相关文档:
👑 7. Supervisor - "团队领导"
Supervisor是多代理系统的"总指挥",不亲自干活,只负责任务分配和结果整合。
🏢 用"公司"来理解 Supervisor
如果 Agent 是公司,Subagent 是子公司,那么 Supervisor(主管)就是总公司的高层管理团队,负责协调多个子公司完成复杂任务。
在 LangChain/LangGraph 的多代理系统中,Supervisor Agent 是一个中央协调代理,它将子代理(Subagents,通常作为 LangGraph 中的 Subgraphs 实现)当作工具来调用。Supervisor 接收用户请求,根据任务需求决定调用哪个子代理,收集结果后决定下一步或结束。
Supervisor架构:
用户 → Supervisor → 选择专家(工具) → 专家工作 → 结果回传 → Supervisor整合 → 用户Supervisor完整案例:个人助理系统
# 1. 创建专家子代理(作为工具)
weather_expert = create_agent(model=llm, tools=[get_weather])
calendar_expert = create_agent(model=llm, tools=[schedule_event])
# 2. 包装成Supervisor工具
@tool
def ask_weather_expert(query: str):
"""天气专家:处理所有天气相关问题"""
return weather_expert.invoke({"messages": [query]})
@tool
def ask_calendar_expert(query: str):
"""日程专家:处理会议、日历问题"""
return calendar_expert.invoke({"messages": [query]})
# 3. Supervisor总控
supervisor = create_agent(
model=llm,
tools=[ask_weather_expert, ask_calendar_expert],
system_prompt="""你是个人助理主管。
根据用户需求分发给:
- 天气专家:天气、温度查询
- 日程专家:会议、日历安排
- 需要两个都用时,顺序调用"""
)
# 测试
result = supervisor.invoke({
"messages": [{"role": "user", "content": "明天北京天气如何?帮我安排10点会议"}]
})执行流程:
Supervisor思考:"需要天气+日程两个专家"
↓ 调用ask_weather_expert("明天北京天气")
↓ 得到:"晴天22°"
↓ 调用ask_calendar_expert("安排10点会议")
↓ 得到:"已安排10点会议"
↓ 整合:"明天北京晴天22°,10点会议已安排"🏢 8. Subagent(子代理)- 子公司/外包团队
当任务太复杂时,主 Agent 可以把部分工作"外包"给专门的子 Agent。
主Agent(综合助手)
│
├── 子Agent1:数据分析专家
├── 子Agent2:文档撰写专家
└── 子Agent3:代码审查专家为什么需要 Subagent?
- 专业分工:每个子 Agent 专注一个领域
- 状态隔离:子 Agent 有自己的记忆,不污染主 Agent
- 复用性:同一个子 Agent 可以被多个主 Agent 调用
Subagent实现:子图作为节点
from langgraph.graph import StateGraph, START, END
# === Subagent状态(可独立) ===
class SubState(TypedDict):
query: str
result: str
confidence: float
# === Subagent:天气专家子图 ===
def weather_llm(state: SubState):
"""子代理LLM节点"""
return {"result": f"专业分析: {state['query']} 晴天,置信度0.95"}
def should_continue(state: SubState):
return END # 子图简单,直接结束
sub_weather = StateGraph(SubState)\
.add_node("llm", weather_llm)\
.add_edge(START, "llm")\
.add_conditional_edges("llm", should_continue)\
.compile()
# === 在主代理中调用Subagent ===
async def subagent_node(state: AgentState):
"""主代理节点:调用天气子代理"""
sub_input = {"query": "东京", "confidence": 0.9}
sub_result = await sub_weather.ainvoke(sub_input)
return {
"messages": [f"子代理返回: {sub_result['result']}"],
"calculations": state.get("calculations", [])
}什么时候用 Subagent?
使用场景:
- 任务太复杂:需要多个专家协作
- 需要隔离:子任务不应该看到主任务的所有信息
- 可复用:同一个子 Agent 被多处调用
# 示例:研究 Agent 调用多个子 Agent
主Agent(研究协调员)
├── 调用 "文献搜索子Agent" → 返回相关论文
├── 调用 "数据分析子Agent" → 返回统计结果
└── 调用 "报告撰写子Agent" → 生成最终报告🎮 完整实战:智能旅行规划系统
把所有概念组合,构建生产级应用:
# 1. 基础工具
tools = [get_weather, search_flights, book_hotel]
# 2. 专家子代理
travel_expert = create_agent(model=llm, tools=tools)
# 3. Deep Supervisor(带规划)
deep_supervisor = create_deep_agent(
model="claude-sonnet-4-5",
subagents=[{
"name": "travel_expert",
"description": "专业旅行规划师",
"tools": tools
}]
)
# 4. 执行复杂任务
result = deep_supervisor.invoke({
"messages": [{"role": "user", "content": "帮我规划北京3天商务旅行,预算5000元"}]
})
# Deep Agent自动:
# - 写todo分解任务
# - 调用天气/航班/酒店专家
# - 生成详细行程文件
# - 支持人类介入修改📊 概念关系总览图
用户输入
↓
[Deep Agent] ← 规划/文件/子代理
↓ 分发任务
[Supervisor] ← 协调专家
↓ 工具调用
[ReAct Agent] ← 思考+行动循环
↓ 执行原子操作
[节点/工具/函数] ← 具体工作
↓ 返回结果
[状态传递] ← 图结构流转
最终输出完整LangGraph主代理(节点+子图)
from typing_extensions import TypedDict, Annotated
from langchain_core.messages import add_messages
# === 主代理状态 ===
class FullState(TypedDict):
messages: Annotated[list, add_messages]
subagent_results: list[str] # 子代理结果
# === 主代理节点 ===
async def main_llm_node(state: FullState):
"""主LLM决策节点"""
messages = state["messages"] + [
f"已有子代理结果: {state.get('subagent_results', [])}"
]
result = await llm.bind_tools(tools).ainvoke(messages)
return {"messages": [result]}
async def tools_node(state: FullState):
"""工具执行节点"""
# LangGraph标准工具节点逻辑
pass
# === 组装完整代理 ===
graph = StateGraph(FullState)
graph.add_node("main_llm", main_llm_node)
graph.add_node("tools", tools_node)
graph.add_node("weather_subagent", subagent_node) # Subagent作为节点
graph.add_edge(START, "main_llm")
# 条件路由:LLM决定调用工具或子代理
graph.add_conditional_edges("main_llm", lambda s: "tools" if s["messages"][-1].tool_calls else "weather_subagent")
graph.add_edge("tools", "main_llm")
graph.add_edge("weather_subagent", "main_llm")
full_agent = graph.compile()执行流程图解
用户: "东京天气?计算(23+17)*3"
↓
[create_agent主循环]
↓
Middleware.before_model() # 动态工具过滤
↓
main_llm_node() # LLM: "先查天气,再计算"
↓
→ tools_node() # 调用get_weather("东京")
↓
→ weather_subagent() # 调用子图
↓
main_llm_node() # LLM: "天气晴,计算60*3=180"
↓
→ tools_node() # 调用calculator("(23+17)*3")
↓
Middleware.after_model() # 保存结果
↓
最终回答: "东京晴天,计算结果180"🆚 三大框架对比(2025 年 12 月更新)
LangChain 1.x vs LangGraph 1.x vs DeepAgents
抽象层次(从低到高):
┌─────────────────────────────────────────────────────────────────┐
│ │
│ DeepAgents (Agent Harness) │
│ ├── 开箱即用的完整代理 │
│ ├── 内置规划、文件系统、子代理 │
│ └── 类似 Claude Code 的通用版 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ LangChain 1.x (Agent Framework) │
│ ├── create_agent() 高级 API │
│ ├── Middleware 机制 │
│ └── 快速构建标准 Agent │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ LangGraph 1.x (Agent Runtime) │
│ ├── 底层图执行引擎 │
│ ├── 状态持久化、断点续传 │
│ └── 完全控制每个节点 │
│ │
└─────────────────────────────────────────────────────────────────┘详细对比表
| 特性 | LangChain 1.x | LangGraph 1.x | DeepAgents | Claude Agent SDK |
|---|---|---|---|---|
| 定位 | Agent 框架 | Agent 运行时 | Agent 脚手架 | Agent 脚手架 |
| 核心 API | create_agent() | StateGraph | create_agent() + 增强 | Agent 类 |
| 学习曲线 | ⭐⭐ 简单 | ⭐⭐⭐⭐ 较陡 | ⭐ 极简 | ⭐⭐ 简单 |
| 灵活性 | 中等 | 极高 | 低(开箱即用) | 中等 |
| 内置规划 | ❌ | ❌ | ✅ write_todos | ✅ |
| 文件系统 | ❌ | ❌ | ✅ 内置 | ✅ 内置 |
| 子代理 | Subgraph | Subgraph | ✅ task 工具 | ✅ |
| 模型支持 | 多模型 | 多模型 | 默认 Claude | 仅 Claude |
| 适用场景 | 标准 Agent | 复杂工作流 | 复杂任务、编码 | 文件操作、编码 |
如何选择?
你的需求是什么?
│
├── 快速原型 + 标准工具调用
│ └── ✅ LangChain 1.x create_agent()
│
├── 复杂工作流 + 完全控制
│ └── ✅ LangGraph 1.x
│
├── 类似 Claude Code 的通用代理
│ └── ✅ DeepAgents
│
└── 需要文件操作 + 安全审批
└── ✅ Claude Agent SDK它们可以混合使用!
# LangChain Agent 底层就是 LangGraph
agent = create_agent(model, tools) # 高级 API
# 需要更多控制时,可以获取底层图
graph = agent.get_graph() # 获取 LangGraph 图
graph.add_node("custom", custom_node) # 添加自定义节点
# DeepAgents 也是基于 LangGraph
from deepagents import create_agent as create_deep_agent
deep_agent = create_deep_agent(model)LangChain 1.x vs 旧版本对比
| 特性 | LangChain <1.0 | LangChain 1.x (create_agent) |
|---|---|---|
| 代理创建 | create_react_agent | create_agent()(更简单) |
| 自定义逻辑 | 手动StateGraph | Middleware(before/after钩子) |
| 状态管理 | TypedDict | state_schema + Middleware扩展 |
| 工具错误处理 | 手动try-catch | wrap_tool_call middleware |
| 流式输出 | 手动配置 | 开箱即用(节点名为model) |
| 子代理 | 手动subgraph | Subgraph节点 + Middleware支持 |
🎯 Middleware 机制详解
什么是 Middleware?
通俗解释:Middleware 就像机场的安检——在乘客(请求)登机(到达 LLM)之前和下机之后,都要经过检查站。
用户输入
↓
┌─────────────────────────┐
│ Middleware 1: 权限检查 │ ← before_model()
└─────────────────────────┘
↓
┌─────────────────────────┐
│ Middleware 2: 敏感词过滤 │ ← before_model()
└─────────────────────────┘
↓
🧠 LLM 处理
↓
┌─────────────────────────┐
│ Middleware 2: 日志记录 │ ← after_model()
└─────────────────────────┘
↓
┌─────────────────────────┐
│ Middleware 1: 结果缓存 │ ← after_model()
└─────────────────────────┘
↓
最终输出常见 Middleware 用途
middleware = [
# 1. 长对话自动总结(防止 token 超限)
summarization_middleware(max_tokens=4000),
# 2. 权限控制(某些工具只有管理员能用)
permission_middleware({
"delete_file": ["admin"],
"send_email": ["admin", "manager"]
}),
# 3. 重试机制(模型调用失败自动重试)
ModelRetryMiddleware(max_retries=3),
# 4. 人机交互(敏感操作需要人工确认)
human_approval_middleware(tools=["delete_*", "send_*"])
]生产级特性(1.x独有)
# === Middleware示例:权限控制 ===
middleware = [
# 1. 用户权限过滤工具
permission_middleware({
"send_email": ["admin"], # 仅管理员
"delete_data": ["superadmin"]
}),
# 2. 自动总结长对话
summarization_middleware(max_tokens=4000),
# 3. PII脱敏
pii_redaction_middleware(patterns=["phone", "email"])
]
agent = create_agent(model, tools, middleware=middleware)🔄 状态管理深入理解
为什么状态管理很重要?
想象你和朋友聊天:
- 没有状态:每次说话对方都忘了之前聊过什么
- 有状态:对方记得整个对话历史
# LangGraph 的状态定义
class AgentState(TypedDict):
messages: Annotated[list, add_messages] # 对话历史(自动累加)
user_info: dict # 用户信息
task_progress: list[str] # 任务进度add_messages 是什么?
这是一个 reducer 函数,告诉 LangGraph 如何合并新旧状态:
# 没有 reducer:新值覆盖旧值
state["count"] = 5 # 下次赋值会直接覆盖
# 有 add_messages reducer:新消息追加到列表
state["messages"] = [new_msg] # 实际效果:old_messages + [new_msg]🚀 新手进阶路线
- Week1:掌握函数+工具 → 构建简单计算器
- Week2:理解节点+状态 → LangGraph Hello World
- Week3:ReAct Agent → 数学解题助手
- Week4:Supervisor → 多专家系统
- Month2:Deep Agent → 生产级复杂任务
记住核心原则:
- 函数做计算,工具给LLM用
- 节点专注单责,状态全局共享
- Agent管决策,Supervisor管协调
- Deep Agent搞规划,解决真问题
💡 常见问题解答
Q1: create_agent() vs StateGraph,用哪个?
你需要什么?
│
├── 标准的 ReAct Agent(思考→行动→观察循环)
│ └── ✅ create_agent() 更简单
│
├── 自定义工作流(多分支、并行、人工审批)
│ └── ✅ StateGraph 更灵活
│
└── 两者结合
└── ✅ 先用 create_agent(),需要时获取底层图Q2: 什么时候用 Subagent?
- 任务太复杂:需要多个专家协作
- 需要隔离:子任务不应该看到主任务的所有信息
- 可复用:同一个子 Agent 被多处调用
📚 延伸阅读
官方资源
- LangChain 1.0 发布公告
- LangGraph 架构设计
- DeepAgents 文档
- Claude Agent SDK
- Tools
- Graph API
- Agents
- Supervisor
- Middleware
- Subgraphs
框架对比
最后更新:2025 年 12 月作者:Bryce Wang