摘要:Hermes-agent的生产事故里,
curl返回空body但exit code是0;同一个fleet中,9条和19条消息被静默改坏。问题不在压缩会丢信息,而在于丢的方式让Agent无法察觉,并且把截断后的历史当成事实继续执行。这不是一个bug,是一条管道上的六个结构性缺口。
一、静默损坏的三个机理
机理一:截断发生在模型载荷里,持久化记录没有被保护。 Hermes-agent的context_compressor.py是一个约2,650行的有损压缩引擎。_truncate_tool_call_args_at的触发条件极低:工具调用参数超过500字符,每个长字符串叶子被截到头部200字符,尾部完全不保留。致命的地方不是丢内容,是JSON仍然合法 ------json.loads能成功解析,下游API不报错,日志里什么都没有。Agent看到的历史"长得完整、读起来顺、但缺了关键行",它无法区分"参数本来就这么短"和"参数被截断了"。
机理二:还没发出去的工具调用也会被裁。 _pressure_demote_tail运行在pre-send路径上。一个刚刚构建好、还没来得及发送的工具调用,如果参数超过500字符,也会被裁到200字符。子Agent收到的是被截断的指令,不会报错,它们基于"看起来完整"的残缺规格开始行动。
机理三:截断标记本身是可复制的内容。 旧版逻辑在截断后追加...[truncated]。当模型从被压缩的历史中重新发出补丁时,会把标记一起粘贴到写入的文件里,直接制造SyntaxError。PR #83735修掉了"标记可复制",但200字符截断本身并没有被移除------损坏路径从"标记污染"变成了"无声的残缺内容"。
二、六个结构性角度,按实施成本从低到高
| 角度 | 核心动作 | 已有实践 |
|---|---|---|
| 效果型参数保护 | 写入、执行、网络请求类参数不进入有损压缩;超预算时拒绝调用并报错,而非静默截断 | Hermes-agent guard层拒绝含压缩标记的参数执行;tooltrim在工具输出进入上下文前压缩,完整输出留在content-addressed store可回取 |
| 载荷与记录分离 | 压缩只改发给模型的上下文载荷,持久化transcript字节不变 | Codex保留原始事实,压缩改变的是"下一次模型看到的投影";chrono-ctx为上下文源做版本控制,原始事件不可变 |
| 分层渐进压缩 | 多水位线,便宜规则先上,昂贵LLM摘要留到最后 | codeAgent七层流水线:时间清理→L1裁中间→L2单条折叠→L2.5按段聚合→L2.6总量预算→L3.5整段折叠→L4 LLM摘要 |
| 预压缩 | 工具输出进入上下文之前就处理 | tooltrim是drop-in库,内容类型路由压缩HTML/JSON/日志,benchmark中39,575 token压到1,111,5/5情况下"针"都被保留 |
| 摘要加回取路径 | 原始内容归档到外部存储,上下文中保留可回取引用 | tooltrim的shortref机制;chrono-ctx的Git mirror backend,回滚和diff是一等操作 |
| 版本化 | 压缩产物是带版本号的派生视图,不是新的权威事实源 | chrono-ctx定位为"Version control for an agent's context sources";最低起步是一个compacted_from字段,不原地修改消息 |
投入产出比最高的一步:列出Agent中所有会写入磁盘或执行代码的工具,检查它们的参数是否被压缩器触及。这是六条路径里成本最低、收益最高的一条。
三、边界与检验
| 边界 | 表现 | 检验条件 |
|---|---|---|
| 保护名单需要维护 | 新工具加入时需同步更新 | 用"是否写入/执行"作为判断标准,而非枚举工具名 |
| 回取有延迟 | 归档加引用方案中回取原文不适合每轮推理 | 适合调试和审计,不适合热路径 |
| 版本化可能过度设计 | 小型Agent不需要完整VCS | 最低起步是一个compacted_from字段 |
| 分层需要调优 | 每层阈值和策略依赖任务类型 | 从"零成本Snip加回取"开始,逐步加层 |
一条命令检验你的管道 :跑一个超过压缩阈值的会话,让它编辑一个参数超过500字符的文件。读回文件,检查两件事:文件里是否出现...[truncated];文件是否通过语法检查。如果出现标记但Agent没有报错,你的压缩器就在制造静默损坏。
四、核心判断
压缩当然会丢信息。但丢信息的方式,决定了Agent是"知道自己不知道",还是"自信地做错"。
默认实现的问题不是不够智能,而是把截断后的历史当成了新的权威事实。当Agent无法区分"原始内容"和"压缩产物"时,每一次推理都在一个被悄悄改写的世界里进行。
修一个bug不够。需要的是从"效果型参数保护"到"版本化派生视图"的六层结构性约束,让压缩从"原地改写"变成"可追溯的投影"。
查看原文
以上仅为核心速览。完整版包含:Hermes-agent事故的完整复盘、
_truncate_tool_call_args_at与_pressure_demote_tail的代码级分析、六个角度每个的完整实施步骤与配置示例、tooltrim的@compressed_tool装饰器用法、chrono-ctx的MCP接入方式、codeAgent七层压缩的逐层阈值设计,以及六个开源项目的完整链接汇总。本文首发于微信公众号「阿Q的AI笔记」,点击下方链接阅读全文:
关注公众号
如果你想持续追踪Agent上下文管理的真实事故、工程实践与开源方案评测,欢迎关注公众号「阿Q的AI笔记」。