第 15 章 第二部分:架构原理

上下文管理与 Compaction

为什么需要 Compaction、三层架构、内置策略、训练一致性、自定义策略开发

Nexus Compaction 上下文管理 Context Window 训练一致性

问题

Agent 的多轮对话会不断增长。当对话超过 LLM 的上下文窗口(如 128K tokens),推理会失败。

简单的截断会丢失关键信息。Nexus 的 Compaction 系统提供了更智能的方案。

这里需要先分清一件事:压缩的代价至少有三种。

  1. 信息损失——丢掉的内容让 Agent 答错;
  2. 重获取成本——丢掉的内容让 Agent 再调一次工具去取回来,省下的 token 被重新花掉;
  3. 前缀缓存失效——压缩改写的是提示词前缀,而 agent 流量里绝大部分 prompt token 是重读;前缀一改,原本命中缓存的重读部分要按全价重新 prefill。

第二种代价容易被忽略,却在最坏情况下能抵消甚至超过压缩本身省下的量。对工具密集的 Agent(Nexus 的 ToolExecutor 每轮可能产生多个大体积 tool message)尤其如此。本章后面「第四个维度:压缩的下游代价」一节会给出它的量化形式。第三种代价不是纸面推论:Claude Code 在 v2.1.275(2026-09-17)修的正是这一条——官方原文是「a restored memory file’s age note changing between requests after a compaction or resume, which caused prompt cache misses」。这是生产环境里真实发生过的 cache miss,不是论文模拟。

还要先限定一句,它会影响全章的论证走向:避免上下文溢出只是压缩的一部分理由。AutoCompact(arXiv:2610.02163,2026-10-01)在 256K 窗口下取得 +9.2 个绝对百分点的增益,而论文明确写这个窗口 never overflows——压不压都不是为了装得下。它的解释是:过期的探索历史本身会伤害后续决策,哪怕它装得下。换句话说,压缩同时是思维工具,不只是内存管理。本章后文凡是出现「为避免溢出而压缩」的表述,都应在这个更宽的口径下读。

三层架构

CompactionManager(编排层)
  │  "什么时候做 compaction"
  ▼
CompactionTrigger(触发层)
  │  "当前对话是否需要 compaction"
  ▼
CompactionStrategy(策略层)
  │  "怎么压缩对话"
  ▼
压缩后的 messages

CompactionTrigger

监控 token 用量,决定是否触发:

class CompactionTrigger:
    def should_compact(self, messages, tools, token_count) -> bool:
        # 当前 token 数 > 阈值 → 触发
        return token_count > self.threshold

这一行是全章最容易被读轻的地方:它把「要不要压缩」压成了一个标量与一个常量的比较。生产级实现里,触发至少有四个判据,而且每个判据都有自己独立的失效模式:

判据平台侧实证失效模式
token 数 > 阈值通用阈值必须是 per-model 参数而非全局常量(v2.1.288,2026-10-02:/autocompact 改为按模型保存自动压缩窗口);token 估算误差会被直接放大到触发时机(v2.1.273,2026-09-15:context meter 与 auto-compact 把 advisor-tool turns 按约 2 倍计,导致在真实窗口约一半处就触发)
还能不能被客户端安全分类器审查v2.1.288(2026-10-02)分类器的容量上限是独立于上下文窗口的第二条触发线:auto mode 下对话长到分类器无法审查时改为压缩,而不是每个工具调用都去问一遍或直接失败
最近一次回复上报的 token usagev2.1.288(2026-10-02)上报为 0 会静默关掉触发,长对话直接报 Prompt is too long 而不是自动压缩
是否存在可完整摘要的 exchangev2.1.269(2026-09-11)没有可完整摘要的前序 exchange 时,会话永久卡在 Prompt is too long

还有一条边界情况:新环境的首次请求、或换模型之后的那一次请求,用的是内置窗口与输出上限而不是服务端下发的(v2.1.288,2026-10-02),该请求最多等待 1.5 秒——窗口未知时的引导问题也要算进触发器的健壮性。

把这些列出来的意义不在照抄,而在指出一个方向:触发失败不是「那就先不压」,而是直接变成硬错误。上表四条里有三条的失效结局都是 Prompt is too long。触发器的健壮性与压缩策略本身同等重要,而 §CompactionStrategy 那 968 行里没有一行是为它写的。

CompactionStrategy

实际的压缩逻辑。compaction_strategy.py 有 968 行——这是整个 compaction 目录里最大的文件。

内置策略:

策略注册名方法适合场景
Keep Recentkeep_recent保留 system + 最近 N 条消息简单快速,信息损失大
Summarysummary用 LLM 总结历史,替换为摘要信息保留好,但增加 LLM 调用
Rolling Summaryrolling_summary增量式 LLM 总结在 summary 基础上避免重复总结
RL-learned(实验性)通过 RL 训练 compaction 策略模型高保真压缩,但训练成本高

这张表有一个空格:keep_recent / summary / rolling_summary 三条手写策略都不做因果判断,而 RL-learned 那一条要求训练。对 Nexus 这种「不重新训练策略模型」的框架,中间那一格——不训练也能超过手写策略——此前是空的。FOCUS(arXiv:2609.37590,2026-09-29,Microsoft)填的就是这一格:它不问「压缩到多少比例」,而是问「下一步决策因果依赖于哪些过去的交互单元」,保留那些、丢掉其余;完全在测试时进行,无需离线数据采集或微调,架构无关,可以作为模块化压缩层挂在闭源 API 前面。官方摘要报的口径是峰值上下文削减最多 48%、依赖削减 73%,相对不压缩的完整执行任务成功率提升最多 8.9 个百分点。注意最后这个分母:对照是「不做压缩」,不是「别的压缩器」。训练无关是它在工程上最重要的属性——本节其余方案要么靠手写规则、要么靠训练,FOCUS 是唯一可以直接接进闭源链路的一条。

RL-learned 策略是新兴的研究方向,不再由人工设计压缩规则和 prompt,而是通过 RL 训练一个策略模型来决定何时压缩、保留什么:

  • FoldAct:分离损失计算(summary token 和 action token 分别计算 PPO surrogate loss)+ 全上下文一致性损失,解决梯度稀释和自条件崩溃问题。量化数据:无一致性损失版本 49.6× 加速 + 80.7% 内存削减;完整版 5.19× 加速;长轨迹(10+ 轮)压缩至约 25% 初始长度
  • SUPO(ICLR 2026 提交):推导出支持端到端优化 tool-use 行为和 summarization 策略的策略梯度公式,通过 advantage broadcasting 实现长程信用分配
  • ActiveContext:解耦式架构——轻量 ContextCurator(7B)通过 RL 学习主动信息熵减,为冻结的 TaskExecutor 策展工作记忆
  • CompactionRL(Yujiang Li、Zhenyu Hou、Yi Jing、Jie Tang、Yuxiao Dong;清华大学,前三位作者在 Z.AI 实习期间完成,2026-07-06,arXiv:2607.05378):把 context compaction 纳入 RL 训练,联合优化任务执行与摘要生成,用 token-level loss normalization(解决 summary token 梯度稀释)+ cross-trajectory GAE(跨压缩边界的信用分配)。GLM-4.5-Air(106B-A30B)达 SWE-bench Verified 66.8%(+7.0)、Terminal-Bench 2.0 24.5%(+3.1);GLM-4.7-Flash(30B-A3B)达 56.0%(+5.5)、20.2%(+6.8)。已部署到 GLM-5.2(750B-A40B)的 RL pipeline。
  • ContextPilot(Zhuoshi Pan、Qizhi Pei 等 7 位作者;脚注区一级证据 Affiliation: 1 Tsinghua University 2 Tencent Youtu Lab 3 Shanghai AI Lab,2026-08-28,arXiv:2608.28476;代码 github.com/Tencent/ContextPilot,权重 huggingface.co/collections/panzs19/contextpilot):把上下文管理做成模型习得的行为,而不是框架里的固定策略。三件事——① 扩展工具集(论文工具语义含 readChunk / searchChunk / writeMemory,覆盖 global planning、structured long-term memory、soft context offloading);② Context-Aware Partial Rollout:用 context 与 entropy 的变化定位高影响的上下文编辑决策,把探索预算集中到这些分支上采样;③ Snapshot-level Credit Assignment:把所有下游分支轨迹的结果并入动作级 advantage。基座为 Qwen3-8B / Qwen3-14B / Gemma4-E4B-it(长上下文 QA)与 WebSailor-7B / WebExplorer-8B(深度搜索)。主表与 5.2 节数字:仅用 32K 上下文窗口就超过 128K 窗口的基座;ContextPilot-8B-RL 在四个长上下文 QA 基准上平均超过 StateLM-8B-RL 3.55 分,比自身 SFT 版本再涨 3.62 分,在最难的 BrowseComp+ 上 RL 增益达 5.34 分(该基准平均输入约 552K token,NovelQA 约 119K——论文据此指出 RL 收益随任务难度增大);深度搜索上在两个基座上平均超过 SUPO 1.51 分。token 效率:取 ≥15 轮的轨迹看每轮输入,WebExplorer-8B 在 BrowseComp 上近线性增长到约 30K,ContextPilot-8B 稳定在约 8K–10K
  • AutoCompact(arXiv:2610.02163,2026-10-01):把 compact() 做成 agent 动作空间里的一个动作,训练它决定何时压、保留什么工作态、压完之后怎么继续。训练数据的构造方式值得单独记一笔——先跑基座 agent,用一个 judge 在线审阅它的压缩决策、摘要与压缩后的动作,把有问题的替换成修正版再放进环境里执行,于是每条轨迹都从被修正过的决策继续;这些轨迹先做 SFT,再用二元任务成功奖励做 RL,奖励里没有任何 compaction-specific 项。基座 Qwen3-Coder-30B-A3B-Instruct:SWE-bench Verified 绝对 +9.2 个百分点、SWE-PolyBench Verified 绝对 +5.0。行为侧的读数更能说明问题:SFT 后 agent 已在 44.3% 的任务上主动调用 compact(),RL 后升到 58.5%,同时摘要遗漏关键状态的比率从 3.1% 降到 0.2%、遗漏下一步动作的比率从 8.2% 降到 2.2%。两个方向同时改善——用得更多,错得更少。

需要把一处可能的误读挡在前面。AutoCompact 的 Introduction 把 CompactionRL 明确归为 length-triggered 一类并点名批评,原文是:这类方法只在剩余上下文预算跌破固定阈值时压缩,“ties compaction to context length rather than task progress: stale exploration accumulates until the threshold is reached, and compaction may then occur in the middle of an unresolved stage whose evidence is still needed”。本章上一条刚把 CompactionRL 作为工业部署案例写入,两处看似打架,其实是触发时机归谁决定这一件事的两种答案:归框架(阈值,与任务进度无关)还是归策略(学出来的,随任务进度走)。CompactionRL 的价值在于它把压缩接进了 RL 的目标函数并已落地到 GLM-5.2;AutoCompact 的价值在于它把「何时压」本身也交给了策略。两者不是谁推翻谁,而是同一个坐标轴上的两个位置。顺着这条轴,本章后文「手写规则是框架决定何时压,ACM 是 Agent 决定何时压」那条二方对照可以升级成三方:框架阈值 / 可学习策略 / 固定 rubric。

RL-learned 策略已开始进入工业部署(CompactionRL 已集成到 GLM-5.2 的 RL pipeline),但尚未成为通用可配置的 compaction strategy。但其对训练一致性的影响深远——FoldAct 的分离损失计算直接解决了 policy-dependent compression 的 RL 训练不稳定问题(详见下文训练一致性扩充)。

RL-learned compaction 的应用场景也正从”对话历史压缩”扩展到更广的维度:

  • 检索观察压缩:RECON(arXiv:2510.10448)在 RL-trained search agent 的每次检索后插入 learned summarizer,压缩器在 RL 训练期间保持冻结以维持策略稳定。集成进 Search-R1 流水线后,总上下文长度减少 35%,训练速度提升 5.4%,推理延迟降低 30.9%,平均 exact-match 在 3B agent 上 +14.5%、7B agent 上 +3.0%
  • 记忆构建:LazyMem(arXiv:2607.22690)提出 query-time memory construction——写时存原始消息,查询时才用 4B 小模型做 KEEP/DROP + 压缩决策。在 LongMemEval 上以 213 个 answer-context memory token 达到 0.85 的 LLM-judge 准确率,相比 retrieval-only 少 68.7×、相比最强非 oracle 基线少 21.0×
  • 记忆管理 RL 化的两条同期线索(📌 仅登记,未抓全文核数字):Hindsight Memory-PRM(arXiv:2608.29605,2026-08-30,17 位作者)用可审计的 hindsight credit 监督记忆管理;Selective Forgetting(arXiv:2608.28978,2026-08-29,3 位作者)用图基遗忘做长期 Agent 记忆修剪。两者与 RECON / LazyMem 同属”把记忆的留弃交给学习”这一方向

summary 策略的 prompt:

Please summarize the above history concisely.
Target length: approximately {ratio}% of original length.
Preserve key facts, decisions, tool call results, and context
needed for continuing the conversation.
Focus on tool call and tool response.

训练一致性

Compaction 对训练数据有重大影响——压缩后的对话和原始对话不同。如果训练时的 compaction 行为和推理时不一致,模型会学到错误的分布。

基础保障

  1. HyTuner 集成:CompactionManager 在 compaction 发生时产生新的 segment。HyTuner Processor 记录 compaction 前后的 token 序列,确保训练时能精确复现
  2. 确定性:相同输入 + 相同 compaction 配置 → 相同输出。Cache 系统也包括 compaction 步骤的缓存

Policy-Dependent Compression 的深层挑战

基础保障解决了”可复现性”问题,但未触及更根本的 RL 训练不稳定性问题——compaction 本身是 policy-dependent 的(摘要内容由当前策略决定),这引入了三个系统性挑战:

1. 分布偏移(自条件崩溃)

Compaction 后的摘要成为下一步推理的输入,而摘要内容取决于当前策略。策略更新 → 摘要变化 → 输入分布偏移 → 策略进一步更新,形成自条件循环。FoldAct 将其形式化为”自条件崩溃”——策略的微小变化通过 compaction 放大为输入分布的巨大偏移。

2. 梯度稀释

在 PPO 训练中,summary token 在整条轨迹中占比很小(通常 < 5%),但其质量直接影响后续所有 action token 的输出。标准 PPO 的 surrogate loss 对所有 token 一视同仁,导致 summary token 的梯度信号被 action token 稀释。FoldAct 的解法是分离损失——summary token 和 action token 分别计算 surrogate loss。

3. 信用分配

多轮 compaction 后,最终结果的奖励如何分配给早期 compaction 决策?这是长程信用分配问题。SUPO 通过端到端策略梯度 + advantage broadcasting 解决:compaction 决策的 advantage 不仅来自当前轮的即时反馈,还传播后续轮次的累积奖励。

解耦方案:ContextCurator + TaskExecutor

ActiveContext 提出了一种架构解耦:轻量 ContextCurator(7B)通过 RL 学习主动信息熵减,为冻结的 TaskExecutor 策展工作记忆。这种解耦的优势是:

  • TaskExecutor 的策略保持稳定(不受 compaction 干扰)
  • ContextCurator 可以独立升级(不影响主策略)
  • 7B ContextCurator 即可匹配 GPT-4o 的上下文管理性能

与 Nexus 的关系:Nexus 的 CompactionManager + Agent 分离与此思路类似,但 CompactionManager 使用手写规则而非 RL 训练。理论上,CompactionManager 可以被替换为一个 RL-learned 的 ContextCurator,通过 register_compaction_strategy 注册为自定义策略。

Agent 自主管理压缩时机(ACM)

与”RL-learned ContextCurator”(训练策略模型)不同的另一条路线是 ACM(Agent-managed Context)——把压缩时机与内容纳入 agent 的 action space,通过 manage_context + query_memory 两个工具让 Agent 自己决定”何时压缩、保留什么”。压缩摘要携带唯一标识关联外部存储的原始消息,可随时回查,声称”无损上下文管理”——原始消息不被永久丢弃。

与 Nexus 的关系:这是比 RL-learned 更轻的落地路径——无需训练策略模型,只需给 Agent 增加两个管理工具,通过 register_compaction_strategy 即可接入。它与 CompactionManager 手写规则形成对照:手写规则是”框架决定何时压”,ACM 是”Agent 决定何时压”。

需要补一句:轻不等于终态。ContextPilot(见上文 RL-learned 策略)表明工具接口可以先定下来,之后要不要用 RL 训练模型来使用这些工具,是独立的第二步——先有 manage_context 式的动作空间,才谈得上训练;工具集设计得越完整(规划 / 长期记忆 / 软卸载),后续训练的上限越高。在 Nexus 里先把工具接口开出来,与日后的 RL 路线并不冲突,反倒是其前置条件。

📌 同期线索登记(2026-10-06,未回源,不作断言):Context Language Models(CLM,2026-10-01)让模型把上下文当文件来编辑,而不只是压缩,并配套 Suffix Cache Reuse 处理「编辑破坏前缀缓存」的问题。它是「agent 自主管理上下文」这一方向更强的形态,与本节 ACM 同源但走得更远。此处只登记方向与来源,不写具体数字,ACM 本身的待验证状态不因这条线索而改变。

自定义策略

from nexus.extensions.compaction.compaction_strategy import (
    CompactionStrategy, register_compaction_strategy,
)

@register_compaction_strategy('my_custom')
class MyCustomCompaction(CompactionStrategy):
    def compact(self, messages, tools, target_tokens, token_count_fn):
        # 你的压缩逻辑
        # 返回压缩后的 messages 列表
        ...

然后在配置中使用:

agent_config:
  compaction_strategy: "my_custom"

压缩提示优化

summary 策略的 prompt 是固定的,但压缩质量高度依赖 prompt 的表达。ACON(Agent Context Optimization)提供了一种不修改框架代码、仅优化压缩提示的方法:

ACON 迭代优化流程

  1. 收集失败案例:找到全上下文成功但压缩上下文失败的案例
  2. 分析丢失内容:LLM 分析压缩过程中丢失了什么关键信息
  3. 更新压缩提示:修改 summary prompt,要求保留该类信息
  4. 迭代直到收敛:重复 1-3,直到压缩准确率达标
  5. 可选蒸馏:将优化后的提示策略蒸馏到小模型

ACON 实验结果:26-54% 峰值 token 减少,95%+ 任务准确率保留。值得注意的是,ACON 蒸馏到小模型后仍保留 >95% 准确率,且显著增强小模型作为长程 agent 的能力——AppWorld +32%、OfficeBench +20%、Multi-objective QA +46%。这意味着 ACON 蒸馏后的小模型可作为 Nexus ContextCurator 的轻量实现路径:用 7B 级蒸馏模型替代 GPT-4o 级摘要模型,在不牺牲压缩质量的前提下大幅降低成本。

Factory Anchored Iterative Summarization

Factory 的 anchored iterative summarization 在评估中最优(4.04 分 vs Anthropic compact API 3.74 vs OpenAI 3.43)。核心差异:增量合并到持久锚定状态而非每次全量重建摘要。

与 Nexus 的 rolling_summary 对比:

  • rolling_summary 是增量式的,但每次重新生成完整摘要(非锚定)
  • Anchored 方法维护一个持久状态,每次只追加增量变更,减少信息损失

实践建议:直接在 summary 策略的 prompt 基础上应用 ACON 优化,是最小成本提升压缩质量的方式。无需修改 Nexus 框架代码。

压缩比量化对比

策略预期压缩比信息保真度适用场景
keep_recent~10×低(丢弃历史)短任务、对历史不敏感
summary~3-5×中等通用场景
rolling_summary~3-5×中等偏上长对话、需要历史连贯性
RL-learned~16×高(98%+ QA 保真)实验性,Near-Lossless 论文报告

注:RL-learned 的 16× 压缩比来自 Near-Lossless Context Compression via RL 论文(ACL ARR 2026 提交),7B/32B 模型在 120k-token 上下文上匹配全上下文性能。手写策略的数据基于经验估计。

第四个维度:压缩的下游代价

上表比较的是”压缩掉多少”与”保真度如何”,隐含假设是省下的 token 就是净收益。TRACER(arXiv:2608.29363,2026-08-29)指出这个假设不成立,并把缺口命名为 compression–consequence gap:分配保留预算时不考虑”删掉某个工具输出”的下游后果,而激进压缩可能触发该工具被重新调用,重调用的开销反过来抵消、甚至超过省下的 token。论文给的量级感很直接——单次 SQL 结果就可以超过一万 token,而一个典型任务要调五到十次工具。

它的做法是把压缩重定义为逐工具的序列决策:轻量 REINFORCE 策略输出 query-conditioned 的保留比例(Beta 分布参数化),奖励一并计入任务成功、总 token 消耗与压缩后的工具重调用次数;再用一个学到的 outcome model 做单工具反事实(“如果全部保留这个工具输出会怎样”)来稠密化信用分配。

策略是否计入下游代价
keep_recent❌ 只按新旧丢弃
summary / rolling_summary❌ 只看压缩比与信息保真
RL-learned(FoldAct · SUPO · CompactionRL)部分——奖励计入任务成功,但不含重调用惩罚
TRACER✅ 奖励显式含”压缩后的工具重调用次数”

但「下游代价」这个词在本章里只开了一格,而它其实至少有三格。上表问的是「谁在计重调用」,下面这张表问的是「代价有几种类型」:

代价类型谁在计实证
工具重调用TRACER ✅;其余 ❌TRACER 论文(见上)
前缀缓存失效全部 ❌v2.1.275(2026-09-17)生产环境 cache miss;agent 流量里重读占比高,压缩改写前缀后这部分要全价重算
副作用被重复触发全部 ❌v2.1.271(2026-09-14):压缩后仍在运行的后台命令(watch 任务、dev server)被启动了第二份

第三行尤其值得单独说。TRACER 的代价模型是「被删掉的工具输出会不会被重新取回」,它长在工具调用的账本上;而 v2.1.271 的代价是「压完之后某个还活着的进程被复制了一份」——这件事根本不在工具调用的账本上,用再好的工具级信用分配也看不见。同理第一行与第二行也不共用账本:一个是「重跑一次工具」的显式开销,一个是「缓存不命中」的隐式开销。把三格摆在一起的含义是:「是否计入下游代价」不是一个是非题,而是一张清单,任何只填了一格的压缩器都还可以被继续追问。

数字(均回 arxiv.org/html/2608.29363v1 正文与表 3 核对):在真实生产查询、三种压缩器后端上,相对”全保留”省下 29–46% token 且任务成功率持平或更高——摘要式压缩收益最高(46%),截断 31%、AGORA 式后端 34%、Self-Info 29%;相对”按工具类型固定比例”的静态策略再省 15–18%(原文是 token 节省的百分比,不是百分点);跨 agent backbone 与压缩器架构迁移仍为正收益;5 个 held-out LOCA-bench 环境上省 18–25%。学到的 per-tool 信用分与实测的单工具后果相关:Spearman ρ = 0.66、top-3 命中 82%、方向符号正确率 84%。另有一个容易与前者串台的数——outcome model 自身在留出 episode 上的 Spearman ρ = 0.72(Brier 0.07),那是模型精度,不是反事实验证的相关性。

限制必须随数字一起读:验证集只有 120 条生产查询,按难度分三档——25 条简单查询、55 条”schema 检索 + SQL”多步查询、40 条多表权限查询;训练/留出划分为 80/40,留出集按 7/19/14 分层。查询来自单一企业的单一 Agent 栈。补充材料明确不含生产 agent、数仓与知识库内容、原始 prompt 与工具输出、事件日志与轨迹、训练 checkpoint,也不含 LOCA-bench 与商业模型端点,外部无法复现。部署门槛同样实在:训练前需先录一份”全保留”的重放基线,即每查询 5 次参考运行——对 Nexus 用户来说,这条是可操作性上的硬门槛,不是论文里的脚注。

对 Nexus 的含义:ToolExecutor 天然知道每次工具调用的来源与体量,Ch17 的 tool_output_truncation: 10000 已经是逐工具的粗粒度版本(按字符截断),TRACER 给的是”按工具输出的后验价值决定保留比例”的升级版。最小落地可以很轻——在 post_iteration_hook 或自定义 CompactionStrategy 里给 tool message 打上”该工具后续是否被重调用过”的标签,先把这个特征攒下来,再谈策略。

平台级 Compaction 与自建 Compaction 的关系

OpenAI 于 2026.02 在 Responses API 中发布 server-side compaction,配合 GPT-5.4 的 1M token 上下文窗口。这标志着压缩从”框架级策略”升级为”平台级能力”。对 Nexus 的影响需分短期和长期分析:

短期影响:使用 OpenAI 模型的 Nexus Agent 可受益于平台 compaction,减少触发自建 CompactionManager 的频率。1M 上下文窗口改变了压缩触发阈值——许多当前需要主动压缩的场景可能被更大窗口直接容纳。

机制层事实:平台侧的 compaction 已经是一等可观测事件,而不只是一个内部动作。以 Claude Code 的 OTel 事件为例,claude_code.compaction 带 trigger(auto / manual)、success、duration_ms、pre_tokens、post_tokens、error,以及 precompute_reuse——自动 compaction 会在上下文窗口填满之前于后台预先生成一份摘要,手动触发时记录是否复用:命中为 hit;未命中给出三种理由 miss_custom_instructions(自定义指令变了)、miss_hook(hook 干预)、miss_not_ready(还没算完)。该属性要求 v2.1.153+。

这条记录揭示平台还做了第三件事:预计算 + 可失效复用。于是 §Factory Anchored Iterative Summarization 之后那条”两条路”的对比可以扩成三条:

方案何时算失效模式
rolling_summary每次触发时全量重算重复消耗 + 信息损失累积
Factory Anchored增量合并到持久锚定状态锚定状态污染
平台 precompute窗口填满前于后台先算好,用不上就作废三种 miss(自定义指令 / hook 干预 / 尚未就绪)
迭代式再压缩压完仍超长就再压一次,每次保留更少的最近对话抖动:压了没用、再压还没用,直到把上下文压到不可用

第四条路来自 v2.1.284(2026-09-28):官方原文是「Fixed “Prompt is too long” errors that persisted after compacting: when the compacted request is still too long, Claude Code now compacts once more, keeping less of the recent conversation」。它和前三条不在同一个维度上——前三条是「一次压缩怎么算」,第四条是「一次不够怎么办」,因此它可以和前三条任意一条叠加。

它的失效模式在生产里已经有名字了。v2.1.286(2026-09-30)的官方条目里出现了 autocompact-thrashing 这个错误名,并说明模型 fallback 会把上下文窗口从 1M 掉到 200K——窗口骤降会诱发抖动,抖动又会把上下文压到不可用,两者互为因果。对 Nexus 的直接含义是:CompactionManager 需要一个重试上限 + 抖动检测,判据可以很轻——连续 N 次压缩后 token 数下降比例低于某个阈值时,报 COMPACTION_THRASHING 而不是继续压。没有这个分支的话,“再压一次”这条恢复路径本身就会变成新的死循环。

三条路各有各的失效模式,选哪条取决于你更怕哪一种。

压缩的第三种角色:窗口强制

前面把压缩定位成两件事:溢出前的补救,以及训练数据的采集口径。平台侧还有第三个定位——它是执行窗口策略的手段,压缩不是窗口快满了才来救火,而是被拿去主动把会话压回某个目标窗口。

两条官方事实可以钉住这件事。CLAUDE_CODE_DISABLE_1M_CONTEXT 在 v2.1.223(2026-08-05)被改成:对所有原生 1M 窗口的 Claude 模型,通过 auto-compaction 把它们压回 200K,而不只是作用于一份固定名单;启动时若发现 auto-compaction 没能把会话压在 200K,会给出警告。更早的 v2.1.172(2026-06-10)是同一套逻辑的雏形:使用 1M 上下文但没有额度的会话会永久卡住,修法是让会话自动压回标准上下文限制以内。同一版本还加了另一条:auto-compact 会把使用未知 model ID 的会话维持在假定窗口之内,而不是任其膨胀。

这也解释了为什么窗口一变,压缩触发点就整体跟着动:v2.1.287(2026-10-02)把 Opus 4.7+ 与 Fable 在 Bedrock / Vertex / Foundry / Claude apps gateway 上默认切成 1M 窗口后,v2.1.247(2026-08-26)已经先把 Sonnet 5 的默认自动压缩窗口从约 934K 提到约 967K——窗口上限与压缩策略在平台侧是同一个旋钮的两面。

对 Nexus 的含义是一条具体的设计要求:CompactionManager 应当支持目标窗口而不只是触发阈值。两者的差别是方向性的——阈值只能被动响应(超了才压),目标窗口可以主动下压(为了把会话维持在某个尺寸而压)。只有阈值这一个旋钮时,「给这个 agent 限定 200K 工作集」这类需求是表达不出来的。

第三个平台:Gemini CLI 把压缩触发开放成配置项。 前面两家各有各的形态——OpenAI 是服务端 compaction 加 1M 窗口,Claude Code 是 OTel 一等事件加后台预计算。Gemini CLI 补上的是第三种形态:它把压缩触发阈值直接开放成一个可写进配置的数。model.compressionThreshold 的官方定义是「触发上下文压缩的上下文使用占比(例如 0.2、0.3)」,默认 0.5;配套的 model.maxSessionTurns 限制单会话轮数,默认 -1(不限)。

要点不在那个默认值,而在参数化方式:它用的是占比,不是绝对 token 数。这个差别在窗口会变的年代是实的——占比口径天然随窗口缩放,绝对 token 口径在窗口从 200K 变成 1M 时必须手工改一次。本章已经有现成的例子:Sonnet 5 的自动压缩点从约 934K 被提到约 967K(v2.1.247),正是绝对口径下的手工维护。建议 Nexus 自建路径采用占比口径,把阈值写成窗口的分数而不是 token 常数。

长期影响:自建 compaction 的核心价值仍在于训练数据采集。HyTuner Processor 需要精确的压缩前后 token 序列来构建训练数据,平台 compaction 对客户端透明,无法提供此能力。此外,token 成本仍随长度线性增长——即使 1M 窗口不触发截断,长上下文的推理成本也随 token 数增加,压缩的经济价值不减。

结论:平台 compaction 是 Nexus compaction 的补充而非替代——平台处理”能容纳多少”,Nexus 处理”应该保留什么”以及”训练数据怎么采”。再补一层:平台还不只是”能容纳多少”,它在用预测性预计算掩盖压缩延迟。Nexus 若要在自建路径上对齐,最小成本是给 CompactionManager 增加”预算 + 复用”分支——token 接近阈值时先生成摘要,真正触发时直接复用,并把命中率记成一个可观测指标(对应上表的 hit 与三种 miss)。

本轮未采纳与待核实(2026-10-06 编辑)

  • KV-streams(vLLM 0.19 fork,作者自述 agentic RL 中压缩后重新 prefill 改为从 live cache 驱逐 16-token block、训练快近 2×):无正式论文,本轮未取到一手源。它本可作为「前缀缓存失效」那一行代价的量级证据,但正文只用 v2.1.275 的一手 changelog 支撑该行,不引用此数字。
  • Galahad(2026-10-02,测得 prompt token 中 98.7% 是重读):同样未回源。本章开篇已经用「agent 流量里绝大部分 prompt token 是重读」的非数字表述保留了这一论点,等拿到一手源再补百分比。
  • CLM 的具体数字(BrowseComp-Plus +11.4%、21.5% 更少 FLOPs、Suffix Cache Reuse 服务端算力 −35%):按低置信度纪律只登记方向不写数字,见 §ACM。
  • Claude Code 版本锚点:本轮全部版本事实回 code.claude.com/docs/en/changelog.md 一手核对,版本日期取 npm registry 的 time 字段,最新为 2.1.289(2026-10-03)。其中 v2.1.223 的提案标注日期为 08-06,npm 实际为 2026-08-05T22:51Z,本章按 npm 写。