中间件
中间件包裹 Lead Agent 中的每次 LLM 调用。它们是添加跨领域行为(如记忆、摘要压缩、澄清和 token 追踪)的主要扩展点。
每次 Lead Agent 调用 LLM 时,都会先后执行一条中间件链。中间件可以读取和修改 Agent 的状态、向系统提示注入内容、拦截工具调用,并对模型输出做出反应。
这种设计使 Agent 核心保持简单稳定,同时允许丰富的可组合行为分层叠加。
链的工作方式
中间件链在每次 Agent 调用时根据当前配置和请求参数构建一次。中间件按定义的顺序运行:
- 运行时中间件(错误处理、线程数据、上传、悬空工具调用修补)
SummarizationMiddleware— 上下文压缩(如果启用)TodoMiddleware— 任务列表管理(仅计划模式)TokenUsageMiddleware— token 追踪(如果启用)TitleMiddleware— 自动生成线程标题MemoryMiddleware— 跨会话记忆注入和队列ViewImageMiddleware— 图像细节注入(如果模型支持视觉)DeferredToolFilterMiddleware— 隐藏延迟工具 schema(如果启用工具搜索)SubagentLimitMiddleware— 限制并行子 Agent 调用(如果启用子 Agent)LoopDetectionMiddleware— 打破重复工具调用循环- 自定义中间件(如有)
ClarificationMiddleware— 拦截澄清请求(始终最后)
顺序很重要。摘要压缩在早期运行以在其他处理之前减少上下文。澄清总是最后运行,这样它可以在所有其他中间件完成后拦截。
中间件参考
ClarificationMiddleware
拦截澄清工具调用,并将其转换为面向用户的信息请求。当模型决定在继续之前需要询问用户某事时,此中间件会将该请求呈现出来。
配置:由 guardrails.clarification 设置控制。
LoopDetectionMiddleware
检测 Agent 是否在没有取得进展的情况下重复进行相同的工具调用。检测到循环时,中间件会介入打破循环,防止 Agent 无限消耗轮次。
Warning 介入会按 thread 和 run 排队,并在下一次模型调用时合并为一条隐藏的 HumanMessage(name="loop_warning"),追加到已有工具结果之后。这样不会破坏 provider 对 tool-call/tool-message 配对的校验。Run 开始和结束时会清理过期或未送达的 warning;达到 hard stop 时仍会清空 tool calls 并强制生成最终文本回复。
配置:内置,无需用户配置。
MemoryMiddleware
在每次对话开始时读取持久化记忆事实并将其注入到系统提示中。对话结束后,将后台更新排队,以将新信息纳入记忆存储。
配置:参见记忆系统页面和 config.yaml 中的 memory: 部分。
memory:
enabled: true
injection_enabled: true
max_injection_tokens: 2000
debounce_seconds: 30SubagentLimitMiddleware
限制 Agent 在单次轮次中可以进行的并行子 Agent 任务调用数量。这防止 Agent 生成无限数量的并发子 Agent。
配置:每次请求配置中的 subagent_enabled 和 max_concurrent_subagents。
TitleMiddleware
在第一次交互后自动为线程生成标题。标题从用户的第一条消息和 Agent 的响应中派生。
配置:config.yaml 中的 title: 部分。
title:
enabled: true
max_words: 6
max_chars: 60
model_name: null # 使用默认模型TodoMiddleware
当计划模式激活时,维护一个对用户可见的结构化任务列表。Agent 使用 write_todos 工具,随着完成复杂目标,将任务标记为 pending、in_progress 或 completed。
激活:在请求配置中设置 is_plan_mode: true 时自动启用。不需要 config.yaml 条目。
TokenUsageMiddleware
追踪每次模型调用的 LLM token 消耗,并以 info 级别记录。对于监控成本和了解长时序任务中 token 的使用位置很有帮助。
配置:config.yaml 中的 token_usage: 部分。
token_usage:
enabled: trueSummarizationMiddleware
当对话变长时,对旧消息进行摘要以减少上下文大小。摘要被注入回对话,替代原始消息,在不需要完整 token 成本的情况下保留含义。
配置:config.yaml 中的 summarization: 部分。详见下方详细配置。
ViewImageMiddleware
当当前模型支持视觉(supports_vision: true)时,此中间件拦截 view_image 工具调用,并将图像内容直接注入到模型的上下文中以便分析。
激活:当解析的模型具有 supports_vision: true 时自动启用。
DeferredToolFilterMiddleware
当工具搜索启用时,此中间件从模型上下文中隐藏延迟工具 schema。工具通过 tool_search 工具按需发现,而不是预先全部列出,从而减少上下文使用。
配置:config.yaml 中的 tool_search.enabled: true。
摘要压缩配置详解
SummarizationMiddleware 是长时序任务中影响最大的中间件之一。完整配置参考如下:
summarization:
enabled: true
# 摘要使用的模型(null = 使用默认模型)
# 推荐使用轻量级、经济的模型,如 "gpt-4o-mini"
model_name: null
# 触发条件——满足任意一个条件时运行摘要
trigger:
- type: tokens # 当上下文超过 N 个 token 时触发
value: 32000
# - type: messages # 当消息数超过 N 时触发
# value: 50
# - type: fraction # 当上下文达到模型最大输入的 X% 时触发
# value: 0.8
# 摘要后保留多少最近历史
keep:
type: messages
value: 10 # 保留最近 10 条消息
# 或者按 token 保留:
# type: tokens
# value: 3000
# 为摘要器准备消息时要裁剪的最大 token 数
trim_tokens_to_summarize: 15564
# 自定义摘要提示词(null = 使用默认 LangChain 提示词)
summary_prompt: null触发类型:
tokens:当对话中总 token 数超过value时触发。messages:当消息数超过value时触发。fraction:当上下文达到模型最大输入 token 限制的value比例时触发。
保留类型:
messages:摘要后保留最后value条消息。tokens:保留最近value个 token 的历史。fraction:保留模型最大输入 token 限制的value比例的最近历史。
编写自定义中间件
自定义中间件可以注入到链中用于专业用途。中间件必须实现 langchain.agents.middleware 中的 AgentMiddleware 接口:
from langchain.agents.middleware import AgentMiddleware
class MyMiddleware(AgentMiddleware):
async def on_start(self, state, config):
# 在模型调用前运行
return state, config
async def on_end(self, state, config):
# 在模型调用后运行
return state, config自定义中间件在链末尾 ClarificationMiddleware 之前注入。