添加中间件

上一页介绍了技能将可重用域专业知识(说明、参考资料和脚本)打包到任何代理可按需加载的自包含单元中。 但是,当你将代理部署到生产环境时,会出现一个新类别的问题:无论代理做什么,都会影响每个交互的问题。

需要记录每个请求和响应。 在模型看到有害内容之前,你需要实施防护措施以阻止这些内容。 需要强制实施速率限制、正常捕获异常并注入遥测数据 , 所有这些操作都无需触摸代理的核心逻辑。 将这些担忧复制粘贴到每个代理(或每个工具或每个技能)中无法扩展,并且会导致维护难题。

中间件 可以解决此问题。 中间件允许你使用可复用的行为包装代理的执行管道,从而在明确定义的节点拦截、检查和修改请求和响应。 将中间件视为代理周围的一系列同心层 , 每个层都有机会在进入代理之前对输入执行操作,在到达调用方之前在输出上执行操作。

何时使用此项

在以下情况下向代理添加中间件:

  • 你需要防护措施,以在模型处理内容之前或之后阻止有害、偏离主题或违反策略的内容。
  • 你希望对所有代理交互进行 集中日志记录或遥测 ,而无需单独修改每个代理。
  • 需要 修改请求或响应 (扩充提示、转换输出或完全替换结果),而无需更改代理逻辑。
  • 你想要 强制实施 适用于每次运行的速率限制、内容筛选或身份验证检查等策略。
  • 需要一致、地处理异常 — 针对暂时性故障重试、返回正常回退响应,或记录错误日志以供诊断。
  • 想要跨管道 共享状态 ,例如跟踪请求计时或累积多个中间件组件所需的指标。

小窍门

代理框架包括内置的用于跟踪和指标的工具。 有关详细信息,请参阅 可观测性

中间件管道的工作原理

调用代理的 run 方法时,请求不会直接转到模型。 相反,它会流经中间件层的管道,其中每个层都可以检查或修改请求,委托给下一层,然后在返回的路上检查或修改响应。

┌─────────────────────────────────────────────────────────┐
│  Caller: agent.run("What's the weather?")               │
└──────────────┬──────────────────────────────────────────┘
               ▼
┌─────────────────────────────────────────────────────────┐
│  Middleware 1 (Logging)                                  │
│  • Logs the incoming request                            │
│  • Calls next middleware                                │
│  • Logs the outgoing response                           │
└──────────────┬──────────────────────────────────────────┘
               ▼
┌─────────────────────────────────────────────────────────┐
│  Middleware 2 (Guardrails)                               │
│  • Checks input against content policy                  │
│  • If blocked → returns early with rejection message    │
│  • If allowed → calls next middleware                   │
│  • Checks output against content policy                 │
└──────────────┬──────────────────────────────────────────┘
               ▼
┌─────────────────────────────────────────────────────────┐
│  Agent core (model invocation, tool calls, etc.)        │
└─────────────────────────────────────────────────────────┘

要点:

  1. 每个中间件决定是否继续。 中间件可以调用链中的下一层以正常方式继续,或者可以通过直接返回响应来使管道短路,例如,当护栏阻止请求时。
  2. 中间件能够识别这两个方向。 中间件在委托之前(检查或修改输入)和响应返回后(检查或修改输出)运行代码。 这是经典“洋葱”模式。
  3. 多个中间件链式连接。 注册多个中间件组件时,它们嵌套:第一个注册的中间件是最外部层,最后一个注册的中间件是最靠近代理的内部层。

小窍门

有关中间件如何适应完整的代理执行管道(包括上下文提供程序和聊天客户端层)的详细视图,请参阅 代理管道体系结构

中间件可以执行的操作

代理框架在管道的三层(代理运行、函数调用和聊天客户端)上支持中间件,从而可以精细控制截获执行的位置。 常见模式包括:

图案 示例 引用
护栏与终止措施 阻止有害内容,限制聊天长度 终止和指导原则
异常处理 针对瞬态故障重试,返回备用响应 异常处理
结果替代 编辑敏感数据,扩充或替换代理输出 结果替代
共享状态 在中间件之间传递请求 ID 或计时数据 共享状态
运行时上下文 根据会话、用户或每次运行的配置改变行为 运行时上下文
范围 将中间件应用于所有运行或仅将中间件应用于单个运行 代理与运行范围

有关定义和注册中间件的完整演练,请参阅 “定义中间件”。 有关完整体系结构概述,请参阅 中间件概述

注意事项

注意事项 详细信息
关注点分离 中间件使跨领域逻辑远离代理代码、工具和技能。 每个中间件组件都有一个责任(日志记录、防护栏、错误处理),你可以单独添加、删除或重新排序。
顺序依赖 中间件形成链。 注册中间件的顺序很重要:首先运行的日志记录中间件将看到原始输入,而上次运行的中间件将看到先前中间件已修改的输入。 有意识地规划流程顺序。
调试复杂性 当中间件修改输入或输出时,调试需要了解完整的管道。 响应可能看起来不正确,不是因为代理,而是因为中间件转换了它。 良好的日志记录中间件(位于链中早期)有助于诊断这些情况。
性能开销 每个中间件层都会向每个请求添加处理时间。 对于轻量级操作(如日志记录)而言,这是微不足道的。 对于昂贵的操作(例如调用外部内容审查 API),延迟会加起来,尤其是在链接了多个此类中间件时。

后续步骤

现在,代理具有工具、技能和中间件,下一步是 上下文提供程序 ,即在每次运行之前将内存、用户配置文件和动态知识注入代理的上下文窗口中的组件。

更深入: