跳到主要内容

21-Middleware-Runtime-Guardrails-HITL官方深读

核对日期:2026-05-18
官方资料:Middleware overview https://docs.langchain.com/oss/javascript/langchain/middleware/overview;Runtime https://docs.langchain.com/oss/javascript/langchain/runtime;Guardrails https://docs.langchain.com/oss/javascript/langchain/guardrails;Human-in-the-loop https://docs.langchain.com/oss/javascript/langchain/human-in-the-loop

官方概念

Runtime context 是把数据穿过 Agent 的方式。官方文档强调不要依赖全局状态,而是把数据库连接、用户会话、配置、权限等附加到 context,再在 tools 和 middleware 中读取。创建 Agent 时可用 contextSchema 定义结构,调用时通过 context 传入。

Middleware 是 LangChain 高阶用法的核心接口。它可以在模型调用、工具调用、Agent 前后插入逻辑,用于动态 prompt、动态工具、错误处理、日志、上下文压缩和安全拦截。

Guardrails 是安全和合规检查,可以在 Agent 开始前、完成后、模型/工具调用周围执行。官方内置能力包括 PII 处理和 HITL;也支持自定义 middleware。

HITL middleware 可以对敏感 tool call 发出 interrupt,保存 graph state,等待人工 approve/edit/reject/respond 后继续。

机制

Runtime 深读

官方能力工程用途
contextSchema对运行时上下文做类型和结构校验
runtime.context工具和 middleware 读取 user id、role、tenant、环境
runtime.store读取/写入长期记忆
runtime.executionInfo访问 thread id、run id,做审计关联
runtime.serverInfo在 LangGraph Server 上访问 assistant/user 元数据

runtime context 不应直接拼进 prompt。它首先是控制面数据:权限、连接、配置、审计身份。只有经过策略筛选的内容才能进入 model context。

Middleware 深读

Hook / 模式能做什么示例
beforeModel调模型前修改 state/messages 或拦截trim messages、注入 system prompt
afterModel调模型后检查输出输出质量、结构检查
wrapModelCall包裹模型调用动态模型、动态工具、临时上下文
wrapToolCall包裹工具调用错误处理、重试、审计
beforeAgentAgent 开始前拦截认证、限流、内容过滤
afterAgentAgent 完成后检查安全审查、合规扫描

middleware 顺序很重要。建议按“认证/输入过滤 -> 上下文处理 -> 模型/工具策略 -> 输出过滤 -> 日志”排序。

Guardrails 深读

官方 Guardrails 文档区分 deterministic 和 model-based 两类:

类型优点缺点适合
Deterministic快、可预测、成本低对语义变体弱PII regex、关键词、权限、格式
Model-based能理解语义慢、贵、也可能错安全分类、质量判断、复杂合规

官方 PII middleware 支持 email、credit card、IP、MAC、URL 等类型,也支持自定义 detector;策略包括 redact、mask、hash、block。工程上要按 applyToInput / applyToOutput / applyToToolResults 分层,而不是只在输入层做一次。

HITL 深读

官方 HITL middleware 的核心点:

能力说明
interruptOn配置哪些工具需要审批
checkpointer必须保存状态,才能暂停/恢复
decision: approve原样执行
decision: edit修改参数后执行
decision: reject拒绝并把反馈加入对话
decision: respond跳过工具,把人工回复作为工具结果
多工具中断多个 action 需要按顺序提供多个 decision
streaming + interrupt可边流式输出边检测中断

HITL 不是“前端 confirm 弹窗”。它是持久化工作流的一部分,必须绑定 thread id、工具名、参数、审批人、审批时间和可恢复状态。

TypeScript 落地模板

const contextSchema = z.object({
userId: z.string(),
role: z.enum(["viewer", "operator", "admin"]),
tenantId: z.string(),
});

const authAndAudit = createMiddleware({
name: "AuthAndAudit",
contextSchema,
beforeAgent: {
hook: (state, runtime) => {
if (!runtime.context.userId) {
throw new Error("Authentication required");
}
return;
},
},
wrapToolCall: async (request, handler) => {
const startedAt = Date.now();
try {
const result = await handler(request);
// 写审计日志:tool name、user id、latency、ok
return result;
} catch (error) {
// 统一转成用户可读错误,内部错误进入 trace
throw error;
} finally {
void startedAt;
}
},
});

Python 差异

Python 和 TypeScript 的 HITL 都依赖 LangGraph 的 interrupt/resume 思路,但 API 名称和类型不同。Python 示例里常见 interrupt_on,TypeScript 文档中使用 interruptOn。跨语言项目必须统一审批决策类型和审计字段。

工程边界

  • Runtime context 不能替代鉴权服务,只是传递已验证身份和配置。
  • Middleware 不能变成隐藏业务逻辑;每个 middleware 都要有测试。
  • Guardrails 应分层,不要指望单个模型安全判断解决所有风险。
  • HITL 必须持久化,不持久化的审批无法安全恢复。
  • Edit 决策要保守,修改工具参数可能让 Agent 重新规划并重复执行。

常见反模式

反模式后果
把权限写进 system promptprompt injection 可绕过,且不可审计
middleware 里悄悄改用户输入eval 难复现
PII 只过滤输入不检查工具返回工具结果仍可能泄露
HITL 无 thread id中断后无法恢复正确会话
审批不绑定参数 hash审批后参数被替换仍执行

练习任务

  1. 给多工具任务 Agent 设计 contextSchema,至少包含 userIdroletenantId
  2. 增加一个 deterministic guardrail:检测 API key 形态时 block。
  3. 增加一个 HITL 审批记录结构,包含 toolInputHash。
  4. 为 middleware 顺序写一份测试:认证失败时不能进入工具调用。