告别 AgentExecutor:LangChain 1.0 的 `create_agent` 如何重新定义 Agent 编排
告别 AgentExecutor:LangChain 1.0 的 create_agent 如何重新定义 Agent 编排
LangChain 1.0 于 2025 年 10 月正式 GA。这篇文章聚焦它最核心的变化——用
create_agent取代旧版AgentExecutor和create_react_agent,以及它背后与 LangGraph 的编排关系。
一、为什么要换掉 create_react_agent
如果你在 2024 年写过 LangGraph 的 Agent,对这段代码一定不陌生:
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model, tools=tools)
这是 langgraph-prebuilt 包里的工厂函数,简洁好用,是那个阶段的"最佳实践"。
但随着 LangChain 1.0 在 2025 年 10 月 GA,官方引入了一个新的标准入口:create_agent(Python)/ createAgent(TypeScript)。
它定义在 langchain.agents 里,位置更靠近 LangChain 的核心层,而不是 LangGraph 的 prebuilt 层。更重要的是,它带来了一套全新的扩展机制——Middleware,彻底替代了过去通过子类化或 Hook 参数来定制行为的方式。
二、create_agent 的最小用法
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""获取某城市的天气"""
return f"{city} 今天晴,25°C"
model = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_agent(model, tools=[get_weather])
result = agent.invoke({"messages": [{"role": "user", "content": "上海天气怎么样?"}]})
也支持直接传模型标识符字符串,框架会自动推断 provider:
agent = create_agent("openai:gpt-4o", tools=[get_weather])
表面上和旧版 create_react_agent 几乎一样,但内部的编排结构发生了根本变化。
三、内部如何编排 LangGraph
create_agent 本质上是一个 StateGraph 工厂。它在内部完成以下装配:

3.1 状态定义(AgentState)
默认状态包含两个字段:
messages:用add_messagesReducer 维护,新消息追加而非替换,保留完整对话历史remaining_steps:ManagedValue channel,防止 Agent 陷入无限循环
class AgentState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
remaining_steps: int
3.2 核心节点
图中有两个必须节点:
agent 节点(LLM 推理)
- 调用
model.bind_tools(tools)生成 AIMessage - 校验
remaining_steps - 注入 prompt / system message
tools 节点(工具执行)
- 由
ToolNode实现 - 接收 AIMessage 里的
tool_calls,批量执行工具 - 将结果以
ToolMessage形式写回 State
3.3 条件路由(should_continue)
这是循环的调度核心,作为条件边(conditional edge)连接在 agent 节点之后:
def should_continue(state: AgentState):
last_msg = state["messages"][-1]
if last_msg.tool_calls:
return "tools" # → tools 节点
if response_format:
return "structured" # → generate_structured_response 节点
return END # → 结束
工具执行完成后,通过普通边(normal edge)回到 agent 节点,形成 ReAct 循环。
3.4 可选节点
| 参数 / 功能 | 生成的节点 | 典型场景 |
|---|---|---|
response_format |
generate_structured_response |
最终输出 Pydantic 对象 |
Middleware before_model |
前置处理节点 | 消息裁剪、历史摘要 |
Middleware after_model |
后置处理节点 | 可信度评分、Guardrails |
四、Middleware:新版最核心的扩展机制
这是 create_agent 相比 create_react_agent 最重要的架构升级。
旧版通过 pre_model_hook 和 post_model_hook 两个参数注入节点,耦合性强,无法复用。新版抽象出了一套正式的 Middleware 系统,有六个标准 Hook 点:
before_agent → before_model → wrap_model_call → [LLM] → wrap_tool_call → after_model → after_agent
使用方式如下:
from langchain.agents import create_agent
from langchain.middleware import SummarizationMiddleware, HumanInTheLoopMiddleware
agent = create_agent(
"anthropic:claude-sonnet-4-20250514",
tools=tools,
middleware=[
SummarizationMiddleware(max_tokens=2000), # 历史消息超限时自动摘要
HumanInTheLoopMiddleware(), # 工具调用前人工确认
]
)
官方内置了几个常用 Middleware:
- SummarizationMiddleware:消息历史超过阈值时自动压缩,防止 context 超限
- HumanInTheLoopMiddleware:在指定节点暂停,等待人工审核或输入
- PiiRedactionMiddleware:PII 脱敏,防止敏感信息进入日志或下游系统
自定义 Middleware 只需实现对应接口,无需修改 Graph 结构本身,可以在不同 Agent 之间复用。
五、compile() 层:持久化与人机交互
Agent 图需要 compile() 才能运行,这一步注入基础设施能力,与业务节点解耦:
from langgraph.checkpoint.sqlite import SqliteSaver
checkpointer = SqliteSaver.from_conn_string("agent_memory.db")
agent = create_agent(model, tools=tools)
compiled = agent.compile(checkpointer=checkpointer)
# 跨会话保持记忆
result = compiled.invoke(
{"messages": [HumanMessage("继续上次的任务")]},
config={"configurable": {"thread_id": "user_001"}}
)
compile() 支持的参数:
checkpointer:持久化每一步 State 快照,支持断点续跑和 time-travel 调试store:跨会话长期记忆interrupt_before/interrupt_after:在指定节点前/后暂停,配合 Human-in-the-Loop
六、动态模型选择
create_agent 支持在运行时根据 State 动态选择模型,这在多 Agent 系统中很有用:
def select_model(state: AgentState) -> BaseChatModel:
# 简单任务用便宜模型,复杂任务用旗舰模型
if len(state["messages"]) < 3:
return ChatOpenAI(model="gpt-4o-mini")
return ChatAnthropic(model="claude-opus-4")
agent = create_agent(select_model, tools=tools)
七、完整的执行流程图
START
│
▼
[before_agent middleware]
│
▼
[before_model middleware]
│
▼
┌─────────────────────────────┐
│ agent 节点 │ ← LLM 推理(bind_tools 已绑定)
│ model.invoke(messages) │
└──────────────┬──────────────┘
│
[after_model middleware]
│
▼
┌───────────────┐
│ should_continue│ ← 条件边
└───┬───┬───┬───┘
有工具调用 │ │无调用 有格式化 无调用
▼ │ ▼
┌──────────┐ ┌───────────────────┐
│ tools 节点│ │generate_structured│
│ ToolNode │ │ response │
└────┬─────┘ └────────┬──────────┘
│ 工具结果 │
└──────→ agent ◄──┘ (loop)
│
END
│
▼
[after_agent middleware]
八、什么时候不该用 create_agent
create_agent 覆盖了绝大多数标准 Tool-Calling Agent 场景。但以下情况你仍然需要直接操作 StateGraph:
- 并行节点执行:多个工具 Agent 同时运行,需要
SendAPI - Supervisor-Worker 多 Agent 模式:需要自定义子图和跨图通信
- 复杂的多路分支:路由逻辑超过简单的 tool_calls 判断
- 自定义重试策略:细粒度控制单个节点的错误处理
经验法则:先用 create_agent,当你发现它的 Middleware 不够用时,再下沉到 StateGraph。
九、从 create_react_agent 迁移
迁移并不复杂:
# 旧版(langgraph.prebuilt)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model,
tools=tools,
pre_model_hook=my_hook,
post_model_hook=my_other_hook,
)
# 新版(langchain 1.0)
from langchain.agents import create_agent
from langchain.middleware import CustomMiddleware
agent = create_agent(
model,
tools=tools,
middleware=[CustomMiddleware(before_model=my_hook, after_model=my_other_hook)]
)
主要变化:
- 导入路径从
langgraph.prebuilt改为langchain.agents pre_model_hook/post_model_hook改为 Middleware 方式声明state_schema仍然支持,自定义字段的用法不变
小结
LangChain 1.0 的 create_agent 不只是一次 API 重命名,它完成了两件重要的事:
一是统一了入口——把散落在 AgentExecutor、create_react_agent 等不同层次的 Agent 创建方式整合成一个标准接口,底层统一走 LangGraph 的 StateGraph 运行时。
二是理清了扩展点——用 Middleware 系统取代过去零散的 Hook 参数,让定制逻辑可以以模块化方式复用,而不是每次都要深入 Graph 内部改动节点结构。
如果你的项目还在用 create_react_agent,现在是个好时机做迁移——API 变化不大,但获得的是一个更稳定、更易维护的基础。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)