---
type: study
created: 2026-08-11
updated: 2026-08-11
sensitivity: private
status: active
tags:
  - study
  - langchain
  - python
  - middleware
  - context-engineering
  - guardrails
topic: LangChain Python Middleware、上下文工程与运行时
sources:
  - https://docs.langchain.com/oss/python/langchain/middleware
  - https://docs.langchain.com/oss/python/langchain/context-engineering.md
  - https://docs.langchain.com/oss/python/langchain/guardrails.md
  - https://docs.langchain.com/oss/python/langchain/human-in-the-loop.md
  - https://docs.langchain.com/oss/python/langchain/middleware/built-in.md
  - https://docs.langchain.com/oss/python/langchain/middleware/custom.md
  - https://docs.langchain.com/oss/python/langchain/middleware/overview.md
  - https://docs.langchain.com/oss/python/langchain/runtime.md
last_verified: 2026-08-11
---
# Middleware、上下文工程与运行时

> `/oss/python/langchain/middleware` 规范跳转到 `/middleware/overview`；两条站内入口指向同一正文。

## 核心结论

Agent 失败往往不是模型完全没有能力，而是模型在某一步没有拿到正确上下文。**上下文工程**是决定每一轮模型和工具能看到什么、能写什么、何时压缩/阻断/重试；**middleware** 是 LangChain 实现这些策略的主要机制；**Runtime** 则把可信依赖注入工具和 middleware。

## 上下文的三层与三个数据源

### 三类上下文

| 类型 | 控制对象 | 默认性质 |
|---|---|---|
| Model context | system prompt、messages、tools、model、response format | 单次调用的瞬时视图 |
| Tool context | 工具读取/写入 state、store、runtime context | 可形成持久变化 |
| Life-cycle context | 模型与工具步骤之间的总结、guardrail、日志、跳转 | 通常通过 state/store 持久化 |

### 三个数据源

| 数据源 | 范围 | 例子 |
|---|---|---|
| Runtime context | 本次调用/会话的静态可信配置 | user ID、权限、DB 连接、环境、feature flag |
| State | 当前 thread 的短期记忆 | messages、上传文件、认证状态、步骤结果 |
| Store | 跨 thread 的长期数据 | 用户偏好、抽取出的记忆、历史知识 |

瞬时修改只改变当前模型请求，不应误以为已写入 state；摘要、工具 `Command` 或 lifecycle hook 返回的 state update 才会影响后续步骤。设计文档应明确每份上下文的来源、可信度、范围、生命周期和删除策略。

## Runtime：可信依赖注入

LangGraph Runtime 暴露：

- `context`：由 `context_schema` 定义并在 invocation 时注入；
- `store`：长期记忆接口；
- `stream_writer`：发出 custom progress；
- `execution_info`：thread/run/attempt 等执行身份；
- `server_info`：LangGraph Server 上的 assistant、graph、authenticated user；本地运行时可能为 `None`。

工具使用 `ToolRuntime[Context]`，node-style middleware 使用 `Runtime[Context]`，wrap-style middleware 从 request.runtime 访问。用户 ID、权限和连接对象不能作为普通工具参数交给模型填写。文档当前标注 execution/server info 需要 `deepagents>=0.5.0` 或 `langgraph>=1.1.5`。

## Middleware hook 模型

两类 hook：

| 风格 | Hook | 用途 |
|---|---|---|
| Node-style | `before_agent`、`before_model`、`after_model`、`after_agent` | 顺序日志、验证、state update、提前结束 |
| Wrap-style | `wrap_model_call`、`wrap_tool_call` | 包裹调用、重试、fallback、缓存、请求/响应转换 |

执行顺序必须纳入设计：`before_*` 按 middleware 列表正序；`after_*` 逆序；`wrap_*` 像函数嵌套，列表首项位于最外层。多个 wrap middleware 更新 state 时通过 `ExtendedModelResponse`/`Command` 组合；普通字段冲突由外层值获胜，带 reducer 字段按 reducer 合并，重试失败尝试产生的 command 不应污染最终 state。

声明 `can_jump_to` 后，middleware 可跳到 `model`、`tools` 或 `end`。这是控制流能力，必须有单元测试防止循环、跳过必要审计或绕过 guardrail。

## 预构建 middleware 地图

官方当前列出的 provider-agnostic 能力包括：

- **上下文**：Summarization、Context editing、Filesystem、File search、Provider tool search；
- **人机协作/安全**：Human-in-the-loop、PII detection；
- **预算与终止**：Model call limit、Tool call limit；
- **容错**：Model fallback、Model retry、Tool retry、Tool error；
- **计划与选择**：To-do list、LLM tool selector、Subagent；
- **执行与测试**：Shell tool、LLM tool emulator、Rubric grading；
- **特定 provider**：Anthropic 的 prompt cache/bash/editor/memory/file search，AWS prompt cache，OpenAI moderation 等。

选择原则：先用内置能力；每个 middleware 只承担一个横切关注点；明确顺序和错误语义。Tool retry 负责重试，Tool error 负责把允许公开的失败转换为模型可见消息；原始异常可能含内部细节，不要直接回显。

## Context engineering 的可执行方法

围绕每一轮模型调用动态控制：

- system prompt：按租户、阶段、偏好和合规规则生成；
- messages：注入本轮相关文件/检索结果，裁剪不相关历史；
- tools：根据认证、权限、feature flag、会话阶段选择；
- model：按复杂度、上下文长度、成本和环境路由；
- response format：按任务或下游消费方选择 schema。

工具读写 state/store 时，坚持 namespace/tenant 隔离、最小权限、幂等与事务边界。模型上下文修改通常是瞬时的；真正需要跨轮保存时再写 state/store，避免把噪声永久沉淀。

## Guardrails：确定性策略不能只写在 prompt

Guardrail 可在 agent 前后、模型前后或工具周围校验输入、输出和动作，典型目标：PII、prompt injection、内容政策、业务规则、质量阈值。

`PIIMiddleware` 可按 redact/mask/hash/block 等策略处理内置或自定义检测器，并选择应用于输入、输出或工具结果。wire 层输出也要防泄漏；文档指出 `apply_to_output=True` 的流式 redaction 依赖 `langchain>=1.3.2`。自定义 regex/detector 要防误报、漏报和 ReDoS，并保留可审计但不含敏感原值的指标。

## HITL：把高风险动作变成可恢复的审批点

`HumanInTheLoopMiddleware` 根据工具名和可选 `when` predicate 决定是否 interrupt。四种决定：

- `approve`：按原参数执行；
- `edit`：修改参数后执行；
- `reject`：不执行，把反馈交给 agent；
- `respond`：把人工回复作为 synthetic tool result，不执行原工具。

必须配置 checkpointer，并用稳定 `thread_id` 调用，才能安全暂停并随后 resume；生产不能用仅进程内的 checkpointer。`when` 可只拦截工作区外写入或非只读 SQL，文档当前标注 conditional interrupt 需要 `langchain>=1.3.3`。

审批策略应按风险分级：读取类默认放行；可逆内部写入可 edit/approve；外部发送、删除、付款等应至少 approve/reject，并显示完整影响范围。审批本身需要身份、时间、原始参数、编辑后参数和结果审计；HITL 不是权限控制的替代品。

## 自定义 middleware 规范

- decorator 适合简单 hook；需要配置、共享状态、多个 hook 或 transformer 时用 `AgentMiddleware` class。
- state 字段写入要声明 schema/reducer；不要在 middleware 实例里保存请求级可变状态。
- async 调用链要使用 async hook/handler，避免阻塞事件循环。
- middleware-registered stream transformer 当前要求 `langchain>=1.3.2`，每个 graph scope 应独立实例。
- 单元测试 hook 本身，再做组合顺序、重试、跳转、并行 state update 与流式输出测试。

## 逐页覆盖索引

| 页面 | 学习结论 |
|---|---|
| Middleware overview | middleware 的用途、agent loop 插入点及在 LangGraph workflow 中复用方式。 |
| Prebuilt middleware | 上下文、HITL、预算、fallback/retry、PII、tools、filesystem、subagent 与 provider-specific 能力清单。 |
| Custom middleware | node/wrap hooks、state updates、decorator/class、schema、transformer、执行顺序、jump 与最佳实践。 |
| Context engineering | model/tool/lifecycle context 与 runtime/state/store 三数据源，以及动态 prompt/messages/tools/model/format。 |
| Runtime | context/store/writer/execution/server info 的依赖注入与 tool/middleware 访问方式。 |
| Guardrails | 内置 PII/HITL 与前后置自定义安全/业务校验。 |
| Human-in-the-loop | interrupt policy、条件审批、四种 decision、checkpoint/resume、批量决定与生命周期。 |

## 延伸

- [[03-State-Streaming-and-Structured-Output]]
- [[05-MCP-Multi-Agent-Retrieval-and-Memory]]
- [[07-Production-Testing-and-Migration]]
