钩子
中间件提供两种钩子风格来拦截代理执行:节点式钩子
在特定执行节点按顺序运行。适用于日志记录、验证和状态更新。 可用钩子:before_agent- 代理启动前(每次调用执行一次)before_model- 每次模型调用前after_model- 每次模型响应后after_agent- 代理完成后(每次调用执行一次)
- 装饰器
- 类
包装式钩子
拦截执行并控制处理器的调用时机。适用于重试、缓存和数据转换。 你可以决定处理器被调用零次(短路)、一次(正常流程)或多次(重试逻辑)。 可用钩子:wrap_model_call- 围绕每次模型调用wrap_tool_call- 围绕每次工具调用
- 装饰器
- 类
创建中间件
你可以通过两种方式创建中间件:基于装饰器的中间件
对于单钩子中间件快速简便。使用装饰器包装单个函数。 可用装饰器: 节点式:@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钩子)
- 装饰器
- 类
最佳实践
- 保持中间件专注——每个中间件应只做好一件事
- 优雅地处理错误——不要让中间件错误导致代理崩溃
- 使用合适的钩子类型:
- 节点式用于顺序逻辑(日志记录、验证)
- 包装式用于控制流(重试、回退、缓存)
- 清晰记录任何自定义状态属性
- 在集成之前对中间件进行独立单元测试
- 考虑执行顺序——将关键中间件放在列表的最前面
- 尽可能使用内置中间件
示例
动态模型选择
- 装饰器
- 类
工具调用监控
- 装饰器
- 类
动态选择工具
在运行时选择相关工具以提升性能和准确性。本节介绍如何过滤预注册工具。如需在运行时注册发现的工具(例如来自 MCP 服务器),请参阅运行时工具注册。 优势:- 更短的提示词 - 通过只暴露相关工具来降低复杂性
- 更高的准确性 - 模型从更少的选项中正确选择
- 权限控制 - 根据用户访问权限动态过滤工具
- 装饰器
- 类
处理系统消息
使用ModelRequest 上的 system_message 字段在中间件中修改系统消息。system_message 字段包含一个 SystemMessage 对象(即使代理是用字符串 system_prompt 创建的)。
示例:向系统消息添加上下文
- 装饰器
- 类
- 装饰器
- 类
ModelRequest.system_message始终是一个SystemMessage对象,即使代理是用system_prompt="string"创建的- 使用
SystemMessage.content_blocks以块列表的形式访问内容,无论原始内容是字符串还是列表 - 修改系统消息时,使用
content_blocks并追加新块以保留现有结构 - 对于缓存控制等高级用例,你可以直接将
SystemMessage对象传递给create_agent的system_prompt参数
其他资源
将这些文档连接 到 Claude、VSCode 等工具,通过 MCP 获取实时答案。

