钩子
中间件提供两种样式的钩子来拦截代理执行:节点风格钩子
在特定执行点按顺序运行。
包装风格钩子
在每个模型或工具调用周围运行。
节点风格钩子
在特定执行点按顺序运行。用于日志记录、验证和状态更新。 选择您的中间件需要的钩子。您可以在节点风格钩子和包装风格钩子之间进行选择。 节点风格钩子在特定执行点运行:| 钩子 | 运行时机 |
|---|---|
before_agent | 代理开始之前(每次调用一次) |
before_model | 每次模型调用之前 |
after_model | 每次模型响应之后 |
after_agent | 代理完成之后(每次调用一次) |
| 钩子 | 运行时机 |
|---|---|
wrap_model_call | 在每次模型调用周围 |
wrap_tool_call | 在每次工具调用周围 |
- 装饰器
- 类
包装风格钩子
拦截执行并控制何时调用处理程序。用于重试、缓存和转换。 您可以决定处理程序被调用零次(短路)、一次(正常流程)或多次(重试逻辑)。 可用的钩子:wrap_model_call- 在每次模型调用周围wrap_tool_call- 在每次工具调用周围
- 装饰器
- 类
状态更新
节点风格和包装风格钩子都可以更新代理状态。机制有所不同:- 节点风格钩子(
before_agent、before_model、after_model、after_agent):直接返回一个字典。该字典使用图的 reducer 合并到代理状态中。 - 包装风格钩子(
wrap_model_call、wrap_tool_call):对于模型调用,返回带有Command的ExtendedModelResponse,以在模型响应旁边注入状态更新。对于工具调用,直接返回一个Command。当您需要根据在模型或工具调用期间运行的逻辑来跟踪或更新状态时使用这些,例如摘要触发点、使用量元数据或从请求或响应计算的自定义字段。
节点风格钩子
从节点风格钩子返回一个字典,以将更新合并到代理状态中。字典键映射到状态字段。包装风格钩子
从wrap_model_call 返回带有 Command 的 ExtendedModelResponse,以从模型调用层注入状态更新:
Command 通过图的 reducer 流动,因此更新被正确应用,消息是附加的而不是替换现有状态。
与多个中间件的组合
当多个中间件层返回ExtendedModelResponse 时,它们的命令会组合:
- 命令通过 reducer 应用: 每个
Command成为单独的状态更新。对于消息,这意味着它们是附加的。 - 冲突时外层获胜: 对于非 reducer 状态字段,命令从内到外应用。最外层中间件的值在冲突键上优先。
- 重试安全: 如果外层中间件实现的逻辑可能导致多次调用
handler()(例如重试逻辑),则丢弃较早调用的命令。
创建中间件
您可以通过两种方式创建中间件:基于装饰器的中间件
对于单钩子中间件快速简单。使用装饰器包装各个函数。
基于类的中间件
对于具有多个钩子或配置的复杂中间件更强大。
基于装饰器的中间件
对于单钩子中间件快速简单。使用装饰器包装各个函数。 可用的装饰器: 节点风格:@before_agent- 代理开始之前运行(每次调用一次)@before_model- 每次模型调用之前运行@after_model- 每次模型响应之后运行@after_agent- 代理完成之后运行(每次调用一次)
@wrap_model_call- 用自定义逻辑包装每次模型调用@wrap_tool_call- 用自定义逻辑包装每次工具调用
@dynamic_prompt- 生成动态系统提示词
- 需要单个钩子
- 无需复杂配置
- 快速原型开发
基于类的中间件
对于具有多个钩子或配置的复杂中间件更强大。当您需要为同一钩子定义同步和异步实现,或者想要在单个中间件中组合多个钩子时使用类。 示例:- 为同一钩子定义同步和异步实现
- 单个中间件中需要多个钩子
- 需要复杂配置(例如可配置阈值、自定义模型)
- 跨项目重用,配置在初始化时进行
自定义状态模式
如果您的中间件需要跨钩子跟踪状态,中间件可以用自定义属性扩展代理的状态。这使中间件能够:- 跨执行跟踪状态: 维护在整个代理执行生命周期中持续存在的计数器、标志或其他值
-
在钩子之间共享数据: 从
before_model传递信息到after_model,或在不同的中间件实例之间传递 - 实现横切关注点: 添加功能,如速率限制、使用量跟踪、用户上下文或审计日志,而无需修改核心代理逻辑
- 做出条件决策: 使用累积状态来决定是否继续执行、跳转到不同节点或动态修改行为
- 装饰器
- 类
执行顺序
使用多个中间件时,了解它们的执行方式:执行流程
执行流程
Before 钩子按顺序运行:
middleware1.before_agent()middleware2.before_agent()middleware3.before_agent()
middleware1.before_model()middleware2.before_model()middleware3.before_model()
middleware1.wrap_model_call()→middleware2.wrap_model_call()→middleware3.wrap_model_call()→ model
middleware3.after_model()middleware2.after_model()middleware1.after_model()
middleware3.after_agent()middleware2.after_agent()middleware1.after_agent()
before_*钩子:从第一个到最后一个after_*钩子:从最后一个到第一个(反向)wrap_*钩子:嵌套(第一个中间件包装所有其他)
代理跳转
要从中间件提前退出,返回带有jump_to 的字典:
可用的跳转目标:
'end':跳转到代理执行的末尾(或第一个after_agent钩子)'tools':跳转到工具节点'model':跳转到模型节点(或第一个before_model钩子)
- 装饰器
- 类

