【LangChain】一.LangChain v1.0-快速上手(核心组件、工具、中间件)

目录

写在前面

本文内容

[1. LangChain 是什么](#1. LangChain 是什么)

[2. 核心组件](#2. 核心组件)

[2.1 model:推理引擎](#2.1 model:推理引擎)

[2.2 messages:上下文的标准容器](#2.2 messages:上下文的标准容器)

[2.3 agent:总装配点](#2.3 agent:总装配点)

[2.4 streaming:运行观察机制](#2.4 streaming:运行观察机制)

[2.5 structured output:Agent 接入真实业务的接口](#2.5 structured output:Agent 接入真实业务的接口)

[2.6 核心组件小结](#2.6 核心组件小结)

[3. 工具系统](#3. 工具系统)

[3.1 工具:Agent 的行动接口](#3.1 工具:Agent 的行动接口)

[3.2 工具契约:能力说明书](#3.2 工具契约:能力说明书)

[3.3 ToolRuntime:工具能读取运行时](#3.3 ToolRuntime:工具能读取运行时)

[3.4 Command:工具能修改系统状态](#3.4 Command:工具能修改系统状态)

[3.5 动态工具:工具集合可以动态变化](#3.5 动态工具:工具集合可以动态变化)

[3.6 MCP:工具来源外部化](#3.6 MCP:工具来源外部化)

[3.7 为什么很多"高级能力"最后都落在工具上](#3.7 为什么很多"高级能力"最后都落在工具上)

[4. 中间件与控制系统](#4. 中间件与控制系统)

[4.1 middleware 在 LangChain 里的位置](#4.1 middleware 在 LangChain 里的位置)

[4.2 官方预置中间件](#4.2 官方预置中间件)

[4.2.1 可靠性、容错与成本控制](#4.2.1 可靠性、容错与成本控制)

[4.2.2 上下文管理](#4.2.2 上下文管理)

[4.2.3 安全与治理](#4.2.3 安全与治理)

[4.2.4 任务组织与重型代理环境](#4.2.4 任务组织与重型代理环境)

[4.3 怎么组合官方中间件](#4.3 怎么组合官方中间件)

[4.4 自定义中间件](#4.4 自定义中间件)

[4.4.1 Node-style hooks:适合状态更新、校验、日志](#4.4.1 Node-style hooks:适合状态更新、校验、日志)

[4.4.2 Wrap-style hooks:适合重试、fallback、动态模型、动态工具](#4.4.2 Wrap-style hooks:适合重试、fallback、动态模型、动态工具)

[4.4.3 执行顺序](#4.4.3 执行顺序)

[4.5 Runtime:把"系统依赖"和"模型语料"分开](#4.5 Runtime:把"系统依赖"和"模型语料"分开)

[4.6 Context Engineering:每一轮该给什么](#4.6 Context Engineering:每一轮该给什么)

[4.7 这一章真正要记住什么](#4.7 这一章真正要记住什么)

[5. 核心能力总结](#5. 核心能力总结)

[5.1 你能做什么了](#5.1 你能做什么了)

[5.2 一个生产级示例](#5.2 一个生产级示例)

[5.3 接下来学什么](#5.3 接下来学什么)

参考文档


写在前面

学 LangChain 觉得别扭?多半是入口选错了。

把它当成"调大模型的库",你看到的就是零散 API:messages、tools、middleware、memory、RAG、MCP、multi-agent,像一堆互不相干的专题。

LangChain 真正在做的是:把模型、上下文、工具、控制逻辑、记忆、知识接入和代理协作,组织成一套能持续运行的 Agent 系统。

这篇文章不写 quickstart 流水账,也不按官方文档顺序。我会按开发者最容易理解的逻辑,带你掌握 LangChain 的核心能力------搭建一个可控、可运行的 Agent 系统。

本文内容

  1. 核心组件:model、messages、agent、streaming、structured output
  2. 工具系统:Agent 如何获得行动能力
  3. 中间件与控制系统:如何让 Agent 可控、可治理、可上线

目标很简单:一篇文章带你掌握 LangChain 的核心开发能力。 看完后你脑子里不是一堆 API 名词,而是一张能直接指导开发的框架地图。


1. LangChain 是什么

先把边界说清楚。

LangChain 不是 prompt 模板库,不是模型 SDK 包装层,也不是聊天机器人脚手架。它是一套面向 Agent 开发的上层框架

什么叫"上层框架"?

第一,统一模型、消息、工具、结构化输出等基础对象,让你快速搭起一个能运行的 Agent。

第二,提供 middleware、runtime、memory 等控制面,让你管理的不是"一次模型调用",而是一个"会持续执行的系统"。

第三,把 RAG、长期记忆、MCP、多代理这些看似分散的能力,收束到同一个 Agent 开发模型里。

同时也要分清它和周边生态的关系:

|-----------|-------------------------------|
| 组件 | 定位 |
| LangChain | 上层 Agent 框架,负责开发体验和常见抽象 |
| LangGraph | 底层运行时与编排引擎,负责状态、持久化、流式执行、中断恢复 |
| LangSmith | 观测、调试、评测平台 |

LangChain 的核心价值不是"统一调模型",而是"把 Agent 的执行过程工程化"

后面所有章节,都在展开这句话。


2. 核心组件

一个最基本的 Agent,靠哪些骨架对象跑起来?

先说五个最该先立住的对象:model、messages、agent、streaming、structured output。这五个对象没建立清楚,后面的工具、中间件、记忆、RAG 都会飘着。

2.1 model:推理引擎

任何 Agent 最终都要靠模型完成推理:理解用户问题、决定用不用工具、解释工具结果、生成最终回答。LangChain 在模型层的核心工作,是把不同 provider 的模型调用统一成同一套接口。

python 复制代码
from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-5.4")

模型在 LangChain 里首先是一个可被系统调度的推理节点。

但模型层并不是 LangChain 最有价值的部分。"调一次模型"本身,不足以构成一个 Agent 框架。

2.2 messages:上下文的标准容器

很多人学 LangChain 的第一个误区,是把消息系统看成"prompt 的另一种写法"。

在 LangChain 里,消息不是语法糖,而是上下文的标准容器

python 复制代码
messages = [
    {"role": "system", "content": "You are a concise assistant."},
    {"role": "user", "content": "Explain LangChain simply."},
]

这意味着:

  • 上下文不再是一段巨大字符串
  • 不同角色的内容在系统里有不同语义
  • 工具结果、历史对话、记忆摘要、流式事件,最终都会回到消息系统里

memory 要管理消息历史,middleware 经常要裁剪、摘要、编辑消息,streaming 很多时候是在暴露消息级事件,而不是纯 token。

2.3 agent:总装配点

今天的 LangChain,最标准的入口是 create_agent(...)

python 复制代码
from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-5.4",
    tools=[],
    system_prompt="You are a concise assistant.",
)

create_agent(...)总装配点,负责把 model、messages、tools、response_format、middleware、checkpointer、store 装到一起。

agent 本身不是魔法。真正重要的是它把哪些抽象组织起来,以及这些抽象如何一起工作。

2.4 streaming:运行观察机制

很多人从聊天 UI 的角度理解 streaming,把它看成前端体验优化。但在 LangChain 里,streaming 更重要的价值是**"看见 Agent 正在怎么运行"**。

python 复制代码
for chunk in agent.stream(inputs, stream_mode="updates", version="v2"):
    print(chunk)

官方常见的几种流式模式:

  • updates:看 agent step 和状态变化
  • messages:看消息块或 token 流
  • custom:看工具或节点主动发出的自定义进度

streaming 首先是调试、观察和运维能力,其次才是展示能力

2.5 structured output:Agent 接入真实业务的接口

如果模型输出还要被程序继续消费,纯自然语言不够稳。这时你需要的不是"让模型尽量按 JSON 输出",而是让框架接管结果结构。

python 复制代码
from pydantic import BaseModel
from langchain.agents import create_agent


class ContactInfo(BaseModel):
    name: str
    email: str


agent = create_agent(
    model="openai:gpt-5.4",
    response_format=ContactInfo,
)

structured output 不是输出格式优化,而是 Agent 接入真实业务的关键接口

2.6 核心组件小结

到这里,骨架应该清楚了:

  • model 负责推理
  • messages 负责承载上下文
  • agent 负责装配系统
  • streaming 负责暴露运行过程
  • structured output 负责把结果接到程序世界

系统到这里还只是"能跑起来"。真正让 Agent 接触世界、改写状态、接入外部能力的主轴,是工具。


3. 工具系统

Agent 怎样获得行动能力?

这是 LangChain 最重要的主轴之一。很多后面看起来很"高级"的能力,本质上都还是通过工具落地。

3.1 工具:Agent 的行动接口

模型本身只能推理,不能直接:

  • 查数据库
  • 调 HTTP API
  • 操作文件
  • 搜外部知识
  • 写入长期记忆
  • 把任务交给别的 agent

LangChain 用工具把这些外部能力显式暴露给模型。

python 复制代码
from langchain.tools import tool


@tool
def get_weather(city: str) -> str:
    """Get weather for a given city."""
    return f"{city}: sunny, 25C"

工具不是"给 Python 程序用的函数",而是"给模型调用的能力接口"

3.2 工具契约:能力说明书

为什么工具经常"选不对""参数填错""该用时不用"?很多时候不是模型太弱,而是工具契约写得太差。

工具契约至少回答三件事:

  • 这个工具是干什么的
  • 什么时候该用
  • 参数分别代表什么

所以工具名、参数名、docstring 都很关键。对模型来说,它看到的不是你的业务代码,而是这份能力说明书。

坏工具契约

  • 名字太泛,如 process_data
  • docstring 含糊,如 Handle user info
  • 参数语义不明,如 value, data, type

好工具契约的标准不是"程序员看得懂",而是"模型能稳定选对"。

3.3 ToolRuntime:工具能读取运行时

如果工具只接收参数、只返回字符串,那它只是浅层的 function calling。LangChain 更关键的一步,是让工具能读取运行时。

python 复制代码
from dataclasses import dataclass
from langchain.tools import ToolRuntime, tool


@dataclass
class Context:
    user_id: str


@tool
def query_order(order_id: str, runtime: ToolRuntime[Context]) -> str:
    """Query the current user's order."""
    user_id = runtime.context.user_id
    return f"user={user_id}, order={order_id}"

工具已经不是孤立函数,而是系统里的运行节点。

通过 ToolRuntime,工具可以访问:

  • context:本次调用注入的静态依赖,如用户 ID、租户信息、数据库连接
  • state:当前线程的短期状态
  • store:跨线程的长期记忆
  • stream_writer:主动写出自定义流式进度

3.4 Command:工具能修改系统状态

这是 LangChain 工具系统非常关键的一步升级。

工具不一定只"返回文本",它还可以通过 Command 更新状态。一旦能更新状态,工具就不只是取数接口,而会变成控制接口。

复制代码
from langgraph.types import Command
from langchain.tools import tool


@tool
def mark_vip_customer(user_id: str) -> Command:
    """Mark the current user as VIP in agent state."""
    return Command(update={"vip_user_id": user_id})

工具可以参与控制流,而不只是提供信息

这在很多场景都很重要:

  • 工具写入短期状态,影响后续 prompt 或路由
  • 工具触发 handoff,把任务切给别的 agent
  • 工具把"业务动作"转成"系统状态变化"

3.5 动态工具:工具集合可以动态变化

很多教程会默认 agent 的工具列表在创建时就完全确定。但真实系统里,工具经常是动态的:

  • 不同用户权限不同
  • 不同租户接入的系统不同
  • 某些工具只在某个对话阶段开放
  • 工具可能在运行时从远端注册中心或 MCP 服务器加载

LangChain 对动态工具的核心支持点,不在"某个神奇 API",而在 middleware。

python 复制代码
from collections.abc import Callable
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse


@wrap_model_call
def only_show_admin_tools(
    request: ModelRequest,
    handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
    if not request.runtime.context.is_admin:
        allowed = [tool for tool in request.tools if tool.name != "delete_user"]
        request = request.override(tools=allowed)
    return handler(request)

动态工具不是工具层单独的功能,而是工具系统和中间件系统的交叉点

3.6 MCP:工具来源外部化

很多人把 MCP 学成"一个新协议"。但站在 LangChain 的视角看,它最重要的意义很简单:MCP 让工具不必写死在本地代码里,而可以从外部服务器动态接入

python 复制代码
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient


client = MultiServerMCPClient(
    {
        "browser": {"transport": "stdio", "command": "python", "args": ["browser_server.py"]},
    }
)
tools = await client.get_tools()

agent = create_agent("openai:gpt-5.4", tools=tools)

MCP 在 LangChain 里不是平行世界,它最后还是回到工具系统里

官方文档还强调了一点:MCP 工具本身运行在外部进程里,拿不到 LangGraph runtime;如果你想让 MCP 工具读 context、store、state,要用 interceptor 把这些能力桥接进去。工具系统和运行时系统是绑在一起理解的。

3.7 为什么很多"高级能力"最后都落在工具上

这点一定要看明白,因为它决定了你会不会把 LangChain 学散。

很多表面上是"高级专题"的能力,底层其实都强依赖工具:

  • retrieval 常常先做成检索工具
  • long-term memory 往往通过工具读写 store
  • handoff / multi-agent 常常通过工具触发状态变化
  • MCP 本质上是外部工具接入

工具不是一个普通章节,而是 LangChain 从"会说话"走向"会行动"的分水岭


4. 中间件与控制系统

这是全文最重要的一章。

如果说工具系统解决的是"Agent 能做什么",那么中间件系统解决的是:Agent 在做这些事的时候,如何被控制、约束、治理和稳定运行

很多人低估 middleware,是因为把它理解成 Web 框架那种"可有可无的扩展层"。但在 LangChain 里,middleware 更接近控制面

没有它,你当然也能跑一个 agent;但一旦进入真实环境,你马上会碰到这些问题:

  • 模型失败了怎么办
  • 工具失败了怎么办
  • 工具太多,模型总乱选怎么办
  • 对话越来越长,上下文爆炸怎么办
  • 敏感信息要不要脱敏
  • 某些工具调用前要不要人工确认
  • 不同用户要不要走不同模型、看到不同工具

这些问题如果都散落在 prompt 和业务代码里,系统很快就会失控。LangChain 把它们收束到 middleware,就是为了把 Agent 的执行过程工程化。

4.1 middleware 在 LangChain 里的位置

middleware 的核心作用不是"改一点 prompt",而是在 Agent 循环的关键节点插手执行。

官方的 Agent 主循环很简单:

  1. 调模型
  2. 模型决定是否调用工具
  3. 执行工具
  4. 将工具结果回注到上下文
  5. 再次调模型,直到结束

middleware 就是插在这条链路前后,去做:

  • 改模型:动态切换模型、降级、重试
  • 改工具集合:按权限过滤、动态加载、MCP 接入
  • 改消息上下文:裁剪、摘要、脱敏、注入
  • 改错误处理:捕获异常、fallback、告警
  • 改中断和恢复策略:HITL 审批、断点续跑
  • 改安全和治理规则:限流、审计、合规检查

它不是"装饰层",而是控制层。可以把 middleware 理解成 Agent 系统的"操作系统内核"------它决定了 Agent 能做什么、不能做什么、怎么做、做到什么程度。

4.2 官方预置中间件

如果你直接背中间件类名,很快就会乱。更好的理解方式是:先按"它解决什么问题"分类。

4.2.1 可靠性、容错与成本控制

这一组中间件解决的是:别让 agent 因为模型不稳、工具抖动或循环失控而把系统拖垮。

ModelRetryMiddleware

  • 解决什么问题:模型调用的瞬时失败,如 timeout、throttling、临时网络错误
  • 什么时候用:生产环境基本都建议加
python 复制代码
from langchain.agents.middleware import ModelRetryMiddleware

middleware = [
    ModelRetryMiddleware(max_retries=3),
]

ToolRetryMiddleware

  • 解决什么问题:外部工具调用的瞬时失败
  • 什么时候用:工具依赖 HTTP、数据库、第三方 API 时很常见
python 复制代码
from langchain.agents.middleware import ToolRetryMiddleware

middleware = [
    ToolRetryMiddleware(max_retries=3),
]

ModelFallbackMiddleware

  • 解决什么问题:主模型失败时切换备用模型
  • 什么时候用:要做 provider 容灾,或者希望降级保活
python 复制代码
from langchain.agents.middleware import ModelFallbackMiddleware

middleware = [
    ModelFallbackMiddleware("openai:gpt-5.4-mini", "anthropic:claude-sonnet-4-5"),
]

ModelCallLimitMiddleware

  • 解决什么问题:模型循环调用失控,成本和延迟失控
  • 什么时候用:担心 agent 进入长循环,或者要严格控费
python 复制代码
from langchain.agents.middleware import ModelCallLimitMiddleware

middleware = [
    ModelCallLimitMiddleware(run_limit=5, thread_limit=10, exit_behavior="end"),
]

ToolCallLimitMiddleware

  • 解决什么问题:工具调用过多,尤其是昂贵或限流工具被反复调用
  • 什么时候用:搜索、爬虫、数据库、付费 API
python 复制代码
from langchain.agents.middleware import ToolCallLimitMiddleware

middleware = [
    ToolCallLimitMiddleware(tool_name="search", run_limit=3, thread_limit=5),
]

这一组和工具系统的关系很直接:工具让 agent 有了行动能力,而这些中间件负责让行动不会失控

4.2.2 上下文管理

这一组中间件解决的是:上下文不是越多越好,而是越精准越好

SummarizationMiddleware

  • 解决什么问题:长对话把上下文撑爆
  • 什么时候用:多轮线程、长任务、需要长期保留会话连贯性的场景
python 复制代码
from langchain.agents.middleware import SummarizationMiddleware

middleware = [
    SummarizationMiddleware(
        model="openai:gpt-5.4-mini",
        trigger=("tokens", 4000),
        keep=("messages", 20),
    ),
]

重点不是"自动摘要",而是让旧消息压缩成更便宜、更短的上下文表示。

ContextEditingMiddleware

  • 解决什么问题:工具输出太长、太脏、太多,直接塞回消息会污染上下文
  • 什么时候用:文件搜索、RAG、网页抓取、长文本工具
python 复制代码
from langchain.agents.middleware import ContextEditingMiddleware, ClearToolUsesEdit

middleware = [
    ContextEditingMiddleware(edits=[ClearToolUsesEdit(keep_most_recent=3)]),
]

LLMToolSelectorMiddleware

  • 解决什么问题:工具太多时,主模型被工具描述淹没
  • 什么时候用:一个 agent 挂了大量工具,但每次真正 relevant 的只有少数几个
python 复制代码
from langchain.agents.middleware import LLMToolSelectorMiddleware

middleware = [
    LLMToolSelectorMiddleware(model="openai:gpt-5.4-mini", max_tools=5),
]

它本质上不是"工具增强",而是上下文压缩。因为工具描述本身也是上下文的一部分。

4.2.3 安全与治理

这一组中间件解决的是:不是所有内容都该原样进模型,也不是所有动作都该自动执行

PIIMiddleware

  • 解决什么问题:输入、输出、工具参数里包含邮箱、手机号、信用卡号等敏感信息
  • 什么时候用:面向真实用户的系统几乎都该考虑
python 复制代码
from langchain.agents.middleware import PIIMiddleware

middleware = [
    PIIMiddleware("email", strategy="redact", apply_to_input=True),
]

可用策略包括 redactmaskhashblock。guardrails 在 LangChain 里并不是一个平行世界,而是控制系统的一部分。

HumanInTheLoopMiddleware

  • 解决什么问题:高风险工具调用不能让 agent 自己拍板
  • 什么时候用:发邮件、写数据库、付款、删文件、调用内部管理系统
python 复制代码
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import InMemorySaver

middleware = [
    HumanInTheLoopMiddleware(
        interrupt_on={"send_email": {"allowed_decisions": ["approve", "edit", "reject"]}}
    )
]

checkpointer = InMemorySaver()

HITL 不是"让人参与一下",而是把中断、审批、恢复纳入标准执行流程

所以把 guardrails、HITL 单独学成"高级专题"其实是不对的。它们本质上是治理型 middleware。

4.2.4 任务组织与重型代理环境

这一组中间件更偏"给 agent 直接注入一整类工作能力"。

其中有些是 LangChain 通用中间件,有些更常见于官方的 Deep Agents 能力栈。理解它们的最佳方式不是背 API,而是看它们给 agent 增加了什么工作环境。

TodoListMiddleware

  • 解决什么问题:长任务缺少显式计划,agent 容易丢步骤
  • 什么时候用:多步骤任务、代码修改、复杂执行链
python 复制代码
from langchain.agents.middleware import TodoListMiddleware

middleware = [TodoListMiddleware()]

它的本质不是"多一个 todo 功能",而是给 agent 注入显式任务管理能力。

LLMToolEmulator

  • 解决什么问题:某些工具成本高、权限高,或你想先模拟工具效果
  • 什么时候用:联调、演示、低成本预演
python 复制代码
from langchain.agents.middleware import LLMToolEmulator

middleware = [
    LLMToolEmulator(),
]

ShellToolMiddleware

  • 解决什么问题:给 agent 安全地注入 shell 执行能力
  • 什么时候用:代码代理、自动化脚本、运维辅助
python 复制代码
from langchain.agents.middleware import ShellToolMiddleware

middleware = [
    ShellToolMiddleware(workspace_root="/workspace"),
]

FilesystemFileSearchMiddleware

  • 解决什么问题:让 agent 拥有 glob / grep 风格的文件搜索能力
  • 什么时候用:代码库分析、文档仓搜索、本地知识发现
python 复制代码
from langchain.agents.middleware import FilesystemFileSearchMiddleware

middleware = [
    FilesystemFileSearchMiddleware(root_path="/workspace", use_ripgrep=True),
]

FilesystemMiddleware

  • 解决什么问题:给 agent 提供读写文件、编辑文件、短长期文件记忆
  • 什么时候用:重型代理、代码代理、以文件系统为主工作区的任务

它更接近"给 agent 配一套工作台",而不只是加一个工具。

SubAgentMiddleware

  • 解决什么问题:把复杂任务切给子代理,隔离上下文
  • 什么时候用:单 agent 上下文过载,或者不同角色需要独立工作区

它是后面 multi-agent 章节的桥。

4.3 怎么组合官方中间件

中间件不是堆得越多越好。更合理的思路是按问题链路组合:

  1. 先解决可靠性:ModelRetryMiddlewareToolRetryMiddlewareModelFallbackMiddleware
  2. 再控制成本和失控:ModelCallLimitMiddlewareToolCallLimitMiddleware
  3. 再管理上下文:SummarizationMiddlewareContextEditingMiddlewareLLMToolSelectorMiddleware
  4. 最后治理高风险动作:PIIMiddlewareHumanInTheLoopMiddleware

一个典型的生产向组合可能长这样:

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import (
    ModelRetryMiddleware,
    ToolRetryMiddleware,
    SummarizationMiddleware,
    PIIMiddleware,
    HumanInTheLoopMiddleware,
)
from langgraph.checkpoint.memory import InMemorySaver

agent = create_agent(
    model="openai:gpt-5.4",
    tools=[...],
    middleware=[
        ModelRetryMiddleware(max_retries=2),
        ToolRetryMiddleware(max_retries=2),
        SummarizationMiddleware(model="openai:gpt-5.4-mini", trigger=("tokens", 4000)),
        PIIMiddleware("email", strategy="redact", apply_to_input=True),
        HumanInTheLoopMiddleware(interrupt_on={"send_email": True}),
    ],
    checkpointer=InMemorySaver(),
)

LangChain 的重点不是"有 agent",而是"能系统地控制这个 agent"

4.4 自定义中间件

官方预置中间件已经覆盖了很多常见场景。所以正确顺序应该是:

  1. 先看有没有 built-in
  2. 没有再自己写

LangChain 的自定义 middleware,大体分两类。

4.4.1 Node-style hooks:适合状态更新、校验、日志

常见节点型钩子有:

  • before_agent
  • before_model
  • after_model
  • after_agent

它们更适合做轻量控制:打日志、记计数器、做输入校验、写状态字段。

python 复制代码
from langchain.agents import AgentState
from langchain.agents.middleware import after_model


@after_model
def count_model_calls(state: AgentState, runtime):
    return {"model_call_count": state.get("model_call_count", 0) + 1}

node-style hooks 更像在 agent 生命周期节点上加规则

4.4.2 Wrap-style hooks:适合重试、fallback、动态模型、动态工具

常见包裹型钩子有:

  • wrap_model_call
  • wrap_tool_call

它们更适合接管真正的模型或工具调用过程。

python 复制代码
from collections.abc import Callable
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse


@wrap_model_call
def choose_model(
    request: ModelRequest,
    handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
    model = "openai:gpt-5.4-mini" if len(request.messages) < 8 else "openai:gpt-5.4"
    return handler(request.override(model=model))

wrap-style hooks 不是打补丁,而是在接管执行策略

4.4.3 执行顺序

如果你配置了多个 middleware,顺序就不是小事。

  • before_*:按列表顺序执行
  • wrap_*:像洋葱一样嵌套包裹
  • after_*:反向执行

一个实用原则是:

  • 越基础、越全局的控制放前面
  • 越靠近业务的观察和收尾逻辑放后面

比如:

  • 先做 PII 处理
  • 再做上下文裁剪
  • 再做动态模型或动态工具
  • 最后做日志和统计

4.5 Runtime:把"系统依赖"和"模型语料"分开

很多初学者会把所有信息都塞进 prompt。这是 Agent 系统很快失控的原因之一。

LangChain 的 runtime 在这里建立了一条非常重要的边界:

  • 什么应该给模型看
  • 什么只应该作为系统运行时依赖存在

runtime 里最常用的几部分是:

  • context:本次调用传入的静态依赖
  • state:当前线程的短期状态
  • store:跨线程长期记忆
  • stream_writer:自定义流式输出
  • execution_info:线程 ID、run ID、attempt 等执行元信息

最小链路可以这样看:

python 复制代码
from dataclasses import dataclass
from langchain.agents import create_agent
from langchain.tools import ToolRuntime, tool


@dataclass
class Context:
    user_id: str
    tenant_id: str


@tool
def get_current_profile(runtime: ToolRuntime[Context]) -> str:
    return f"user={runtime.context.user_id}, tenant={runtime.context.tenant_id}"


agent = create_agent(
    model="openai:gpt-5.4",
    tools=[get_current_profile],
    context_schema=Context,
)

runtime 的意义不是多给你几个对象,而是把"系统依赖"和"模型语料"分开

4.6 Context Engineering:每一轮该给什么

LangChain 官方现在非常强调 context engineering。这不是换个新术语,而是在纠正一个旧误区:

Agent 稳不稳,往往不取决于 prompt 写得多华丽,而取决于每一轮到底给了模型什么上下文。

从开发角度看,至少要分清三类上下文。

model context

  • 真正送进模型的消息、系统提示、工具描述、摘要信息

tool context

  • 工具执行时能访问的运行时依赖,如 context、state、store

life-cycle context

  • 在 agent 生命周期不同节点上才可见和可改写的信息,比如模型前后、工具前后、中断恢复前后

这也是为什么 context engineering 必须放在 middleware 这一章讲。因为它不是"提示词技巧",而是"在生命周期里精确安排上下文"的能力。

python 复制代码
from langchain.agents.middleware import dynamic_prompt, ModelRequest


@dynamic_prompt
def role_aware_prompt(request: ModelRequest) -> str:
    role = request.runtime.context.user_role
    base = "You are a helpful assistant."
    if role == "beginner":
        return base + " Explain concepts simply."
    return base + " Answer with technical depth."

动态 prompt 不是为了"更花哨",而是为了让上下文在正确的生命周期节点被生成

4.7 这一章真正要记住什么

到这里,中间件这一章要收住成一句话:

LangChain 最核心的价值,不在 create_agent(...) 本身,而在于它把 Agent 的控制、上下文和治理工程化了。

如果你只会用 model + tools,你只是会搭一个能跑的 agent。如果你真正掌握了 middleware、runtime、context engineering,你才开始会做一个能上线、能治理、能维护的 agent 系统。


5. 核心能力总结

到这里,你应该已经掌握了 LangChain 的核心开发能力。我们来总结一下。

5.1 你能做什么了

学完这篇,你应该能:

  1. 搭建基本 Agent:用 model、messages、agent 三个核心组件,搭起一个能运行的 Agent
  2. 赋予行动能力:通过工具系统,让 Agent 能查数据库、调 API、操作文件
  3. 实现可控执行:用中间件系统,解决重试、限流、上下文管理、安全治理等问题
  4. 调试和观察:用 streaming 看清 Agent 的执行过程
  5. 接入真实业务:用 structured output 让模型输出可被程序消费的结构化数据

5.2 一个生产级示例

把今天学的串起来,一个生产级的 Agent 可能长这样:

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import (
    ModelRetryMiddleware,
    ToolRetryMiddleware,
    SummarizationMiddleware,
    PIIMiddleware,
    HumanInTheLoopMiddleware,
)
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver


@tool
def search_database(query: str) -> str:
    """Search the internal database."""
    return f"Results for: {query}"


agent = create_agent(
    model="openai:gpt-5.4",
    tools=[search_database],
    middleware=[
        # 可靠性
        ModelRetryMiddleware(max_retries=2),
        ToolRetryMiddleware(max_retries=2),
        # 上下文管理
        SummarizationMiddleware(
            model="openai:gpt-5.4-mini",
            trigger=("tokens", 4000),
        ),
        # 安全治理
        PIIMiddleware("email", strategy="redact", apply_to_input=True),
        HumanInTheLoopMiddleware(
            interrupt_on={"send_email": {"allowed_decisions": ["approve", "reject"]}}
        ),
    ],
    checkpointer=InMemorySaver(),
)

这就是 LangChain 的核心价值:把 Agent 的执行过程工程化

5.3 接下来学什么

这篇文章解决的是"让 Agent 跑起来 + 可控"的问题。但如果你想让 Agent 更强大,还需要:

  • 记忆系统:让 Agent 记住用户、记住历史、记住偏好
  • RAG / 知识接入:让 Agent 能按需获取外部知识
  • Multi-agent:让多个 Agent 协作完成复杂任务

这些内容,我们在【LangChain】二.LangChain v1.0-高级特性(记忆、RAG 、Multi-Agent )中详细讲解。


参考文档

相关推荐
SunnyDays10111 小时前
Python Word 转 Excel 详解(含整个文档、特定页面或表格转换)
python·word 转 excel·docx 转 xlsx·word 表格导出 excel
m0_741173331 小时前
CSS移动端实现卡片悬浮投影_利用box-shadow设置层次感
jvm·数据库·python
西洼工作室1 小时前
uniapp+vue3+python对接阿里云短信认证服务alibabacloud_dypnsapi20170525
python·阿里云·uni-app
chushiyunen1 小时前
pygame实现射击游戏
python·游戏·pygame
sinat_383437361 小时前
如何在 Laravel 中筛选并格式化匹配预定义列表的产品数据
jvm·数据库·python
2401_846339561 小时前
mysql如何用执行流程思维写好SQL_SQL优化方法总结
jvm·数据库·python
forEverPlume1 小时前
SQL如何统计分组内不重复值的数量_COUNT与DISTINCT结合应用
jvm·数据库·python
chaofan9802 小时前
突破大模型落地瓶颈:Claude 4.7 与 GPT-5.5 长上下文工程实测
数据库·人工智能·python·gpt·自动化·php·api
2501_901200532 小时前
PHP源码部署需要多大硬盘空间_PHP项目存储空间估算方法【方法】
jvm·数据库·python