Hermes Agent 为什么会反复进入 Preflight compression
解释 Hermes Agent 长会话中 preflight compression 反复触发、压缩超时的原因、解决方法,以及对记忆、会话和功能的影响。
Hermes Agent 为什么会反复进入 Preflight compression
如果你在 Feishu、Telegram 或其他网关里长时间和 Hermes Agent 处理同一个项目,看到这样的提示:
📦 Preflight compression: ~165,575 tokens >= 136,000 threshold. This may take a moment.
这基本不是「模型突然坏了」,也不是单纯的网络卡顿。它说明当前会话的历史内容已经接近 Hermes 认为危险的上下文压力线。Agent 在真正处理你这条新消息之前,先停下来压缩旧对话,避免把一个过大的 transcript 直接塞给模型。
你这次看到的 136,000 threshold 很有代表性。Hermes 的网关层有一个预处理压缩保护:按源码和开发文档,它默认在模型上下文窗口的 85% 处触发。136,000 正好对应 160,000 上下文长度的 85%。也就是说,当历史对话、工具输出、文件内容、日志、推理留下的消息堆到大约这个规模时,网关会先压缩,再继续执行任务。
真正原因:长期会话把上下文吃满了
Hermes Agent 有两层压缩机制。第一层在 agent 内部,默认在上下文窗口 50% 左右触发,用来做正常的长期任务管理。第二层在 gateway 层,也就是你通过 Feishu、Telegram 这类入口发消息时的「session hygiene」。这层更像安全阀,默认 85% 触发,用来处理那些已经变得很大的长期网关会话。
源码里的注释写得很直白:长期 gateway session 会不断累积历史,新的消息会把过大的 transcript 重新加载进来,可能导致反复截断或上下文失败,所以要在 agent 开始处理之前主动压缩。这个逻辑还会优先使用上一轮 API 返回的实际 prompt tokens;没有实际值时,再用粗略估算。
所以,你的判断是对的:聊天内容过多,是这个问题的主要触发条件。时间越长、项目越复杂、工具调用越多,这个问题出现得越频繁,也越容易卡在压缩上。
为什么压缩会很慢,甚至超时
上下文压缩不是简单删消息。Hermes 的默认 ContextCompressor 会把中间一大段旧对话交给一个辅助模型,让它生成结构化摘要。摘要里要保留目标、约束、进度、关键决定、相关文件、剩余工作和关键错误信息。最近的若干消息会被原样保留,头部少量消息也会保留,中间部分才会被摘要替换。
这一步天然比普通回复慢,尤其当旧会话里有大量工具输出、代码、日志、长文件、图片或多轮失败重试时。官方开发文档还特别警告:用于压缩的辅助模型上下文窗口必须至少和主模型一样大,否则摘要请求可能因为上下文不够而失败。失败后,压缩器可能只能插入 fallback marker,旧的中间上下文就不再以可用摘要的形式留在当前窗口里。
公开 issue 和 PR 也能看到这不是个孤立体验。Hermes 仓库里有用户报告过「context compression can be interrupted by gateway messages」,会导致 fallback summary marker;随后有 PR 专门保护压缩过程,避免它被新的 gateway 消息打断。另一个 PR 把默认辅助压缩 timeout 从 120 秒提高到 300 秒,因为大型 Codex/compression pass 容易超时。还有 issue 讨论过 preflight compression、智能路由、小上下文模型阈值、auxiliary.compression 配置、OAuth 401、custom provider context_length 等边界问题。
一般怎么解决
最有效的办法不是无限提高阈值,而是改变长期会话的使用方式。
1. 在项目阶段边界主动开新会话
一个大任务做完一段,例如调研结束、实现结束、发布结束,就用 /new 或 /reset 开一个干净会话。不要把一个 Feishu 或 Telegram topic 当成无限期项目数据库。旧会话不会因此从磁盘消失,后续仍可通过 session_search 或会话记录检索,但当前模型窗口不必每次都背着几天甚至几周的历史。
2. 给压缩模型配置足够稳、足够长上下文的后端
检查 config.yaml 里的 auxiliary.compression。压缩模型最好满足三个条件:上下文长度不小于主模型,速度稳定,timeout 不要太短。Hermes 新近 PR 已经把默认压缩 timeout 提高到 300 秒;如果本机配置里仍是 120 秒,长会话更容易压缩失败。实践上可以把 timeout 调到 300 或 600,并选一个可靠的辅助模型,而不是让 auto 误选到不可用、过小或鉴权状态不稳定的模型。
3. 正确设置 context_length
如果使用 custom provider 或非官方模型端点,context_length 配错会让压缩太早或太晚触发。太小会频繁压缩;太大则可能直到 API 报错才开始救火。Hermes 仓库里有相关 issue 指向 custom provider context_length 和 auxiliary compression feasibility 的问题,所以这项配置值得单独核对。
4. 减少会话里的大块工具输出
长文件、完整日志、测试输出、网页全文、图片说明,都会进入会话历史。真正需要长期保存的内容,应该写到项目文件、计划文件、issue、PR 描述或知识库里,而不是一直留在聊天上下文里。复杂任务可以用 delegate_task、cron、kanban 或子会话拆开,让每个 agent 只带自己需要的上下文。
5. 保持 Hermes 更新
这类问题近几个版本一直在修。公开记录里已经出现过与 preflight compression 预算、gateway 消息打断压缩、默认压缩 timeout、Telegram topic 绑定、auxiliary compression 鉴权和上下文长度有关的修复或问题讨论。如果你经常跑超长任务,更新到最新版本比单独调一个阈值更稳。
不要把 compression 直接关掉
可以临时关闭 compression 做排查,但不建议长期关闭。关闭后,短期看起来少了一次等待,长期会更容易直接撞上模型上下文上限,表现成 API 报错、工具调用失败、回复质量下降或丢失前文。压缩本身是保护机制,只是现在你的会话规模和压缩模型配置让保护机制变成了瓶颈。
解决后会影响哪些内容
先说不会受影响的部分:Hermes 的长期 memory、USER profile、skills、磁盘文件、代码仓库、cron job、kanban board,不会因为普通上下文压缩被删除。压缩处理的是当前会话要送进模型窗口的消息列表,不是把你的机器状态清空。
会变化的是当前会话的「活跃上下文」。旧消息中间段会被摘要替换,最近消息会保留,头部少量消息会保留。压缩后,模型看到的是摘要加最近上下文,而不是完整逐字历史。细碎的临时细节、没有写进文件的中间判断、某次工具输出里的小数值,都可能不再逐字存在。Hermes 的实现也会在压缩后创建或切换新的 session_id,并把压缩后的 transcript 写入新 session;旧 transcript 仍留在会话存储里,可用于检索和追溯。
还有一个性能影响:压缩会改变消息前缀,因此被压缩区域的 prompt cache 会失效。官方开发文档说明,系统提示缓存通常还能保留,但滚动消息缓存需要一两轮重新建立。这意味着压缩刚发生后的下一两轮可能更慢或成本更高。
我的建议
把这个问题当成「项目上下文治理」来处理,而不是只当 bug。一个健康的工作流应该是:长期事实进 memory 或 skill;项目状态进文件、issue、PR、计划文档;聊天会话只负责当前阶段的执行。阶段完成就开新会话,必要时让 agent 通过 session_search 或项目文件找回旧信息。
如果要立刻处理你现在遇到的卡顿,我会优先做三件事:第一,升级 Hermes;第二,检查 auxiliary.compression.model、provider、context_length 和 timeout;第三,把已经跑了很久的 Feishu 话题切成新会话。这样不会牺牲长期记忆,也不会删除项目文件,但会明显减少每次新消息前被迫压缩的概率。
参考资料
- Hermes Agent developer docs: Context Compression and Caching
- Hermes Agent source: agent/context_compressor.py
- Hermes Agent source: gateway/run.py session hygiene logic
- PR #23752: raise default compression timeout
- Issue #23975: compression interrupted by gateway messages
- PR #24001: protect context compression from session interrupts
- PR #22871: honor preflight compression pass budget
- Issue #23670: preflight compression and Codex OAuth 401
- Issue #7798: smart model routing and preflight compression threshold
- Issue #14690: context auto-compression threshold bug
- Issue #19539: custom provider context_length and auxiliary compression
More from WayDigital
Continue through other published articles from the same publisher.
Comments
0 public responses
All visitors can read comments. Sign in to join the discussion.
Log in to comment