告别 AgentExecutor:LangChain 1.0 的 create_agent 如何重新定义 Agent 编排

LangChain 1.0 于 2025 年 10 月正式 GA。这篇文章聚焦它最核心的变化——用 create_agent 取代旧版 AgentExecutorcreate_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_messages Reducer 维护,新消息追加而非替换,保留完整对话历史
  • 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_hookpost_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 同时运行,需要 Send API
  • 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)]
)

主要变化:

  1. 导入路径从 langgraph.prebuilt 改为 langchain.agents
  2. pre_model_hook / post_model_hook 改为 Middleware 方式声明
  3. state_schema 仍然支持,自定义字段的用法不变

小结

LangChain 1.0 的 create_agent 不只是一次 API 重命名,它完成了两件重要的事:

一是统一了入口——把散落在 AgentExecutorcreate_react_agent 等不同层次的 Agent 创建方式整合成一个标准接口,底层统一走 LangGraph 的 StateGraph 运行时。

二是理清了扩展点——用 Middleware 系统取代过去零散的 Hook 参数,让定制逻辑可以以模块化方式复用,而不是每次都要深入 Graph 内部改动节点结构。

如果你的项目还在用 create_react_agent,现在是个好时机做迁移——API 变化不大,但获得的是一个更稳定、更易维护的基础。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐