第一篇算过:一个 agent 会话的上下文按每步几千 token 增长,50 步就能填满 200K 窗口,原始目标漂到窗口中间。这一篇讲怎么办。答案不是一个开关,是一条代价递增的处理顺序:先不让无关内容进来(卸载、隔离),再清掉已经没用的(清理),最后才用一次模型调用把历史摘要成一段(压缩)——压缩最贵、最有损,放在最后。

这一篇的材料几乎全部来自公开的生产系统:Claude Code 在窗口约 83.5% 处 auto-compact、预留 33K、压缩后 CLAUDE.md 从磁盘重注入而按路径的规则丢失;Codex 先试”会话记忆压缩”不调模型、不够才调服务端的 /responses/compact 拿回一个加密 blob,触发点在轮前与循环边界两处;LangChain Deep Agents 的两个阈值——工具返回超过 20,000 token 就写文件留 10 行预览、上下文过 85% 就把旧的写入调用截成指针;Anthropic API 把 compaction(默认 150K 触发)、context editing、memory tool 做成三个一等功能;Manus 的”文件系统即上下文”与 todo.md 复述;DeepSeek Harness 的 SDK 把压缩策略做成显式配置的”语义检查点”。把它们放在一张表上,能看出一个共同的结构。

本篇要回答的核心问题是:

怎样给上下文的每一层定配额,超了先做什么、再做什么?1 五个公开系统的卸载、清理、压缩各在什么阈值触发、保留什么?2 压缩会丢什么,怎么评测它丢了什么?3

一、总览

1. 处理顺序

%% 图:新内容进入上下文的处理顺序:先判断隔离、卸载或原样进入,接近清理线先清理,仍接近压缩线再压缩
flowchart TB
    IN["新内容要进入上下文<br/>(工具返回 · 检索结果 · 子任务)"] --> Q1{"必须进主窗口吗?"}
    Q1 -->|"探索性 / 大量读取"| ISO["隔离:子 agent 在自己的窗口做<br/>只带摘要回来"]
    Q1 -->|"是,但很大"| OFF["卸载:内容写文件 / 存储<br/>上下文只留引用 + 预览"]
    Q1 -->|"是,且不大"| ADD["原样进入"]
    ADD --> Q2{"总量接近清理线?"}
    OFF --> Q2
    Q2 -->|"是"| CLR["清理:删掉旧的、已被消费的工具返回<br/>保留调用记录与引用"]
    Q2 -->|"否"| GO(["继续下一步"])
    CLR --> Q3{"仍接近压缩线?"}
    Q3 -->|"是"| CMP["压缩:一次模型调用把历史摘要成一段<br/>常驻层重注入 · 目标复述到末尾"]
    Q3 -->|"否"| GO
    CMP --> GO

    classDef step fill:#fff7e0,stroke:#c98a00,stroke-width:2px,color:#222
    classDef dec fill:#eef6ff,stroke:#5b8fd6,color:#222
    classDef stop fill:#f0f0f0,stroke:#888,color:#222
    class IN,ISO,OFF,ADD,CLR,CMP step
    class Q1,Q2,Q3 dec
    class GO stop

四种手段的代价与损失:

四种上下文手段的代价与损失
手段 代价 损失 可恢复?
隔离(子 agent) 一次额外的 agent 运行;摘要的质量 主窗口看不到过程细节 子 agent 的完整轨迹在 trace 里
卸载(外置) 存储;模型要多一步”读回来” 无(内容完整保留在外) 是——留了路径 / URL
清理(删旧返回) 几乎无 被删内容不可再见(除非也卸载了) 若来源可再取(文件、URL)则是
压缩(摘要) 一次模型调用(几万 token 输入);缓存前缀全部失效 有损:摘要没写的都没了 否

顺序由这张表决定:免费且无损的在前,贵且有损的在后。

2. 本文的章节安排

第二章预算表;第三章隔离与卸载;第四章清理;第五章压缩——机制、五个系统的对照、压缩后什么存活;第六章复述与目标漂移;第七章怎么评测压缩;第八章实践建议。

二、预算表

1. 三档参考

以 200K 窗口为例,按第一篇的七层给三类任务的参考配额(比例,可按窗口缩放):

三类任务的七层预算参考
层 单轮问答 / RAG 多轮对话助手 长程 agent
① 系统指令 2–4% 2–4% 3–5%
② 工具与技能定义 0–2% 2–5% 5–8%(渐进披露后)
③ 长期记忆 0–1% 3–5% 3–5%(Claude Code 上限 25 KB ≈ 6K token)
④ 对话历史 0 30–40% 30–40%(含思考块)
⑤ 检索结果 30–50% 10–15% 5–10%
⑥ 工具返回 0 5–10% 20–30%(最大、最该管)
⑦ 当前输入 1–5% 1–5% 1%
预留给输出(含思考) 10–15% 15% 15–20%

最后一行是最常被忘的:Claude Code 预留约 33K(16.5%),因为压缩摘要本身要用模型生成、模型回答也要空间;推理模型的思考 token 也算输出(L1 第三篇)。触发线 = 窗口 − 预留,Claude Code 的 83.5% 就是 100% − 16.5%。

2. 三条线

为整体设三条线,从低到高:

  • 清理线(如 70%):开始删旧的工具返回;
  • 压缩线(如 83.5%):触发摘要;
  • 硬线(窗口 − 输出预留):拒绝再加内容,否则请求会 400。

线之间要有距离:从清理到压缩之间应能再走几步,否则每步都在压缩。Deep Agents 的 85% 是清理 / 截断线,摘要在其后;Claude Code 的 83.5% 是压缩线,在它之前有对旧工具返回的”微压缩”。

%% 图:长程 agent 在 200K 窗口里的七层预算与三条线——常驻层 ①②③ 约 12%,历史 ④ 30–40%,工具返回 ⑥ 20–30% 是最大最该管的一层,预留 15–20% 给输出含思考;清理线 70%、压缩线 83.5%、硬线 = 窗口 − 预留
%%{init: {"xyChart": {"width": 760, "height": 340, "plotReservedSpacePercent": 60}, "themeVariables": {"xyChart": {"plotColorPalette": "#c0392b, #5b8fd6, #4d9a5c"}}}}%%
xychart-beta
    title "长程 agent 的七层预算(200K 窗口,千 token,取区间中值)"
    x-axis ["① 系统指令", "② 工具定义", "③ 长期记忆", "④ 历史", "⑤ 检索", "⑥ 工具返回", "⑦ 当前输入", "预留输出"]
    y-axis "千 token" 0 --> 80
    bar [8, 13, 8, 70, 15, 50, 2, 34]
%% 图:三条线的位置与它们之间要留的距离——清理线(70%)开始批量删旧工具返回,压缩线(83.5%)触发摘要,硬线(窗口减输出预留)之后请求会 400;清理到压缩之间要能再走几步,否则每步都在压缩
flowchart TB
    Z["0"] --> A["… 正常增长 …"] --> L1["清理线 70%(140K)<br/>批量删已消费的工具返回"] --> B["再走几步"] --> L2["压缩线 83.5%(167K)<br/>一次模型调用做摘要"] --> C["预留 33K:摘要生成 + 回答 + 思考"] --> L3["硬线 200K<br/>再加就 400"]
    classDef ok fill:#eefaf0,stroke:#4d9a5c,color:#222
    classDef warn fill:#fff7e0,stroke:#c98a00,color:#222
    classDef bad fill:#fdecea,stroke:#c0392b,color:#222
    class Z,A,B ok
    class L1,L2,C warn
    class L3 bad

三、隔离与卸载

1. 隔离:子 agent

最有效的预算手段,因为噪声从未进入主窗口。Claude Code 的时间线里,一个研究性子任务由子 agent 在自己的窗口读几十个文件,主窗口只收到一段摘要与一小段元数据。适用:探索性搜索(”找出所有调用这个函数的地方”)、大文档阅读、并行的独立子任务。代价:子 agent 的摘要质量决定主窗口拿到什么——摘要指令要明确(”返回文件路径列表与每处的一句话说明,不要贴代码”);以及子 agent 自己也要预算。L4 讲子 agent 作为运行时机制,这里只讲它作为上下文隔离的那一面。

2. 卸载:可恢复的压缩

Manus 把它叫”文件系统即上下文”:上下文窗口是有限的,文件系统是无限的、持久的、模型可以自己读写的。原则是压缩必须可恢复——删掉网页的正文但保留 URL,删掉文件的内容但保留路径,模型需要时再读回来。Deep Agents 给了具体阈值:工具返回超过 20,000 token → 写入文件系统,上下文里替换为文件路径加前 10 行预览。10 行预览让模型知道里面是什么,路径让它能取回全部。

卸载的对象是第一篇的 ⑥(工具返回)与部分 ⑤(检索结果)。实现上要注意:卸载后模型多了一步”决定要不要读回来”,这一步的判断质量依赖预览的信息量;预览应包括结构性信息(行数、字段名、大小),不只是前几行。

%% 图:卸载 = 可恢复的压缩——一次 SQL 返回 28K token,超过 20K 阈值就写进文件,上下文里只留路径 + 行数 / 字段名 + 前 10 行预览(约 300 token);模型看预览判断要不要读回来,需要时用路径取回全部,内容一个字不丢
flowchart TB
    T["工具返回:SQL 结果<br/>20,000 行 ≈ 28K token"] --> Q{"> 20K token?"}
    Q -->|"否"| IN["原样进上下文"]
    Q -->|"是"| W["写入 /tmp/q7.csv"]
    W --> REF["上下文里只留:<br/>路径 · 20,000 行 × 6 列 · 字段名 · 前 10 行预览<br/>≈ 300 token"]
    REF -->|"模型判断要看细节"| RD["read /tmp/q7.csv(或只读某几行)"]
    RD --> W
    classDef step fill:#fff7e0,stroke:#c98a00,color:#222
    classDef dec fill:#eef6ff,stroke:#5b8fd6,color:#222
    classDef ok fill:#eefaf0,stroke:#4d9a5c,color:#222
    classDef ext fill:#f0f0f0,stroke:#888,color:#222
    class T,IN,RD step
    class Q dec
    class REF ok
    class W ext

3. 常驻层的渐进披露

对 ②(工具与技能)的”卸载”是设计时的:完整 schema 与技能正文不常驻,常驻的只有一行描述,用到时再加载(tool search、SKILL.md 的 description / 正文分离)。这是把第一篇的原则用在发布时而不是运行时。

四、清理

1. 清什么

工具返回的时效很短:模型读了一次文件、做了一个决定,之后这段内容对后续步骤价值急降。清理就是删掉这些已被消费的工具返回,保留工具调用的记录(模型仍能看到”我在第 7 步读过 foo.py”)与卸载时留下的引用。

2. 三个实现

  • Anthropic API 的 context editing:请求里声明策略(如 clear_tool_uses),服务端在上下文超过触发阈值时自动清掉最旧的工具返回,可配保留最近几个、保留哪些工具的;清理后的 usage 反映在响应里。Anthropic 的 cookbook 里一个研究 agent 的例子:335K token 的上下文里 96% 是文件读取结果——清理对这种负载几乎是免费的十倍压缩。
  • Deep Agents 的截断:上下文过 85% 时,旧的 write / edit 工具调用(其内容已在磁盘上)被截成指针——因为文件本身就是”可恢复”的存储。
  • Claude Code 的微压缩:在大压缩之前对旧的工具返回做局部清理(第三方分析称之为 micro-compact / snip),把大压缩推后。

3. 清理与缓存

清理修改了历史中间的内容——缓存前缀从清理处起失效(第五篇)。所以清理不该每步做,应批量做(到清理线一次清一批),让前缀在两次清理之间稳定。服务端实现(Anthropic 的 context editing)在这一点上有优势:清理在服务端发生,客户端送的历史不变,供应商可以更聪明地处理缓存。

五、压缩

1. 机制

压缩(compaction)是用一次模型调用把对话历史摘要成一段结构化文本,替换原历史。它是有损的:摘要没写进去的信息就没了。所以压缩的核心不是”什么时候触发”,是摘要 prompt 要求保留什么:任务目标、已完成的步骤与结论、未完成的事项、关键的文件路径与 id、用户的偏好与约束、当前的阻塞。Anthropic 的服务端 compaction 允许替换默认的摘要 prompt,文档建议针对自己的负载写——研究 agent 要保留引用,coding agent 要保留改过的文件列表与测试状态。

2. 五个系统

五个系统的压缩机制
系统 触发 第一步 第二步 摘要形态 之后
Claude Code 约 83.5% 窗口(预留 33K;新版本按窗口大小调整预留) 微压缩旧工具返回 auto-compact:模型生成结构化摘要 可读文本,替换历史
  • system prompt 不变
  • 根目录 CLAUDE.md 与自动记忆从磁盘重注入
  • 路径规则、子目录 CLAUDE.md 丢失直到再触发
Codex CLI 轮前检查 + 长工具链的循环边界 会话记忆压缩:用已结构化的任务状态(改过的文件、决定)替代摘要,多数情况不调模型 POST /v1/responses/compact:服务端返回 type=compaction 的加密 item 不可读(AES 加密,只有 OpenAI 服务端能解),保留模型的内部状态 待处理的用户请求重放进压缩后的窗口
Anthropic API 可配阈值,默认 150K,最低 50K context editing(可单独启用) 服务端 compaction:返回 compaction 块 可读摘要块,客户端原样送回 可替换默认摘要 prompt
Deep Agents 工具返回 > 20K → 卸载;85% → 截断 卸载到文件(路径 + 10 行预览) 截断旧写入为指针 只有以上都不够时才摘要 文件系统是持久层
Manus 上下文增长中持续 可恢复压缩(留 URL / 路径) todo.md 复述 不以摘要为主 保留失败记录不清除
DeepSeek Harness 由压缩插件配置 JSONL 会话持久化 “语义检查点”策略显式组合 压缩摘要有独立的 token 上限 一切是插件,可替换

三个观察。第一,成熟系统都把压缩放在最后,前面至少有一步更便宜的(Codex 的会话记忆、Claude Code 的微压缩、Deep Agents 的两级)。第二,摘要有两种形态:可读文本(Claude Code、Anthropic API)与不可读的加密状态(Codex)——后者保留了模型自己的”理解”(工具调用的恢复数据、内部状态标记),前者可审计、可替换 prompt、可跨供应商。第三,常驻层的重注入是压缩的一部分:Claude Code 把 CLAUDE.md 从磁盘重读,是因为它的真身在文件里——第一篇说的”可恢复”在这里再次出现。

3. 压缩后什么存活

以 Claude Code 为例,按第一篇的七层:

Claude Code 压缩后七层的存活情况
层 压缩后
① 系统指令 不变(不在消息历史里)
② 工具与技能定义 不变
③ 长期记忆 根目录 CLAUDE.md、自动记忆:重注入;带 paths: 的规则、子目录 CLAUDE.md:丢失,直到再读匹配文件
④ 对话历史 替换为摘要
⑤ 检索结果 摘要里提到的保留为引用,其余丢失
⑥ 工具返回 丢失;卸载过的保留为路径
⑦ 当前输入 Codex 把待处理请求重放;Claude Code 的下一条用户消息在摘要之后

给自己的系统写这张表,是压缩设计的验收标准。

%% 图:压缩前后七层的命运(Claude Code)——①② 不在消息历史里所以不变;③ 的真身在磁盘上,根目录 CLAUDE.md 与自动记忆重注入,按需加载的路径规则丢失;④ 被摘要替代;⑤⑥ 丢失,卸载过的只剩路径;这张表是压缩设计的验收标准
flowchart LR
    B1["① 系统指令"] --> A1["不变(不在消息历史里)"]
    B2["② 工具定义"] --> A2["不变"]
    B3["③ 长期记忆<br/>根目录 CLAUDE.md · 自动记忆 · paths: 规则"] --> A3["根目录部分从磁盘重注入 ✓<br/>paths: 规则丢失,直到再读匹配文件 ✗"]
    B4["④ 40 轮历史(含思考块)"] --> A4["一段结构化摘要<br/>思考块全部丢失"]
    B5["⑤ 检索结果"] --> A5["摘要提到的留为引用,其余丢"]
    B6["⑥ 工具返回 × 50"] --> A6["丢失;卸载过的留为路径"]
    classDef keep fill:#eefaf0,stroke:#4d9a5c,color:#222
    classDef part fill:#fff7e0,stroke:#c98a00,color:#222
    classDef lost fill:#fdecea,stroke:#c0392b,color:#222
    classDef n fill:#f0f0f0,stroke:#888,color:#222
    class B1,B2,B3,B4,B5,B6 n
    class A1,A2 keep
    class A3,A5,A6 part
    class A4 lost

4. 压缩与推理状态

L1 第三篇讲过:推理模型的思考块跨轮保留,编辑历史中间会让校验失败或丢失推理状态。压缩替换了整段历史,必然丢掉思考块——所以压缩只能在一个思考链结束处做(模型给出最终回答之后、下一个用户请求之前),不能在工具循环中间。Codex 的”循环边界”触发点正是这个约束的体现:它等所有工具结果收齐、循环闭合,再压缩,再重放待处理请求。

%% 图:压缩只能在思考链的边界做——Codex 的做法:轮前检查发现超线,先等当前工具循环闭合(所有工具结果收齐、模型给出最终回答),再调 compact,再把待处理的用户请求重放进压缩后的窗口;在循环中间压缩会丢思考块、让签名校验失败
flowchart TB
    U["新用户请求到达"] --> C{"轮前检查:超过压缩线?"}
    C -->|"否"| RUN["正常执行"]
    C -->|"是"| W["先让当前工具循环闭合<br/>思考 → 调用 → 结果 → … → 最终回答"]
    W --> CMP["compact:历史 → 摘要(或加密状态)"]
    CMP --> RP["把待处理的用户请求重放进新窗口"]
    RP --> RUN
    X["✗ 在循环中间压缩:<br/>思考块丢失 · 签名校验失败 · 模型「忘了刚才怎么想」"] -.-> W
    classDef step fill:#fff7e0,stroke:#c98a00,color:#222
    classDef dec fill:#eef6ff,stroke:#5b8fd6,color:#222
    classDef ok fill:#eefaf0,stroke:#4d9a5c,color:#222
    classDef bad fill:#fdecea,stroke:#c0392b,color:#222
    class U,W,CMP,RP step
    class C dec
    class RUN ok
    class X bad

5. 压缩与缓存

压缩后前缀完全变了(历史被摘要替代),缓存全部失效一次,之后以短前缀重新累积(L1 第四篇第五章)。这是压缩的隐藏成本之一:紧接压缩的那一步是全价 prefill 加写入费。压缩频率因此不宜高——它与”压缩线离硬线要有距离”是同一个考虑。

六、复述:对抗目标漂移

压缩解决的是”放不下”,另一个问题是”放得下但忘了”:第一篇第四章的漂移——原始目标漂到窗口中间、注意力最差的位置。Manus 的解法是复述(recitation):让 agent 维护一个 todo.md,每一步末尾重写它——已完成的打勾、当前在做的标出、剩下的列出。效果是把目标与进度从窗口中间搬到末尾,每一步都在注意力最好的位置。Claude Code 的 todo 工具、Codex 的会话记忆里的任务状态是同一个思路的实现。

复述有两个附带收益:它是压缩摘要的现成材料(任务状态已经结构化了——Codex 的会话记忆压缩正是靠它多数情况不调模型);它让人在环上时能看到 agent 认为自己在做什么(L7)。

Manus 还有一条相关的经验:保留失败。agent 犯错后的错误信息、失败的工具返回不要清掉——它们是模型调整行为的证据,删了模型会重复同样的错。清理策略要区分”已消费的成功返回”(可清)与”失败记录”(保留到任务结束或压缩时写进摘要)。

七、怎么评测压缩

压缩是有损的,损了什么要测,不能凭感觉。方法与 L1 第五篇的评测集同源:

  1. 探针问题:为一类任务准备一组”任务进行到中途时应该知道的事”的问题(目标是什么、改过哪些文件、用户说过哪个约束、上一个失败的原因)。
  2. 压缩前后各问一遍:在同一个会话的压缩点之前与之后,分别把探针问题发给模型,比较回答的正确率——差值就是压缩的损失。Anthropic 的 cookbook 把这叫”探测摘要里什么存活了”。
  3. 按类别统计:目标类、状态类、约束类、引用类各自的存活率,告诉你摘要 prompt 该加强哪一类。
  4. 端到端:同一批任务在”不压缩(大窗口)”与”压缩”两种配置下的完成率与成本,压缩带来的完成率下降是否在成本节省能换回的范围内。

一个常见结果:默认摘要 prompt 对”用户的约束”(”不要改测试文件”)存活率最低——它们在对话里只出现一次、不像文件路径那样反复被引用。针对性地在摘要 prompt 里加一条”逐条列出用户提出的约束”,能把这一类的存活率从一半提到九成以上。

八、实践建议

  1. 写预算表与三条线:按第二章给你的应用各层定配额,设清理线、压缩线、硬线,把当前各层的实际占比上仪表盘。
  2. 先做卸载:给工具返回设一个阈值(Deep Agents 的 20K 是好起点),超过就写存储留引用与结构化预览;这一项通常把压缩触发点推后三到四倍(第一篇自测 3)。
  3. 再做清理:批量清已消费的成功返回,保留失败记录;用服务端实现(Anthropic 的 context editing)时确认它与你的缓存策略配合。
  4. 压缩 prompt 按负载写:列出你的任务必须存活的五类信息,写进摘要 prompt;在思考链结束处触发;写”压缩后什么存活”的表作为验收。
  5. 加复述:让 agent 维护任务状态文件并每步更新;它同时是压缩的材料。
  6. 测:探针问题压缩前后各问一遍,按类别看存活率;端到端比完成率与成本。

九、本文小结

  • 处理顺序按代价递增:隔离(子 agent,噪声不进来)→ 卸载(写文件留引用 + 预览,可恢复)→ 清理(删已消费的工具返回,保留失败记录)→ 压缩(一次模型调用,有损,缓存全失效)。
  • 预算:七层各有配额,长程 agent 里工具返回 20–30% 是最该管的一层,输出(含思考)预留 15–20%;三条线——清理、压缩、硬线——之间要有距离。触发线 = 窗口 − 预留,Claude Code 的 83.5% = 100% − 33K/200K。
  • 五个系统:Claude Code 微压缩 → 83.5% auto-compact,CLAUDE.md 重注入、路径规则丢失;Codex 会话记忆压缩优先、不够才 /responses/compact 得加密 blob,轮前与循环边界触发;Anthropic API compaction 默认 150K、可换摘要 prompt,context editing 清工具返回(一个研究 agent 96% 是文件读取);Deep Agents 20K 卸载、85% 截断;Manus 可恢复压缩 + todo.md 复述 + 保留失败;DeepSeek Harness 压缩策略为插件。
  • 压缩只能在思考链结束处做;压缩后缓存全失效一次;摘要 prompt 决定什么存活,”用户约束”最容易丢。
  • 复述把目标搬回窗口末尾,同时是压缩的材料;评测压缩用探针问题前后对比,按类别看存活率。

十、自测

  1. 一个 agent 在 200K 窗口上运行,团队把压缩线设在 95%、输出预留 5K。会出什么问题?

    答案

    两个:压缩摘要本身要模型生成,5K 的预留不够(Claude Code 预留 33K),压缩调用可能被截断或 400;推理模型的思考 token 也算输出,正常回答在 95% 之后几乎没有空间,会频繁 max_tokens 截断。压缩线应设在窗口 − 输出预留(含思考与摘要)之下,如 80–85%。详见第二章。

  2. 工具返回 30K token(一份日志)。按处理顺序,该做什么?上下文里应留下什么?

    答案

    卸载:超过 20K 阈值,写到文件 / 存储,上下文里只留路径、大小、行数、字段名与前 10 行预览(结构性预览让模型能判断要不要读回)。若这段日志只服务于当前一步的判断,下一步后可清理;可恢复(路径在)所以清理无损。不要原样进入再靠压缩处理——压缩有损且贵。详见第三章、第四章。

  3. 为什么 Codex 在”长工具链的循环边界”触发压缩,而不是在任意一步?

    答案

    推理模型的思考块跨轮保留,压缩替换整段历史会丢掉思考链中间的状态;在循环中间压缩会让模型失去”为什么调用了这些工具”的上下文。等所有工具结果收齐、循环闭合(一个思考链结束)再压缩,损失最小;待处理的用户请求随后重放进压缩后的窗口。详见第五章。

  4. 压缩后模型忘了用户说过”不要改测试文件”。用第七章的方法定位并修复。

    答案

    准备探针问题(”用户提出过哪些约束?”)在压缩前后各问一遍,确认”约束类”存活率低;原因是默认摘要 prompt 不特别保留只出现一次的约束。修复:摘要 prompt 加”逐条列出用户提出的所有约束与偏好”,再测存活率;同时把约束写进复述的任务状态文件,让它每步都在末尾。详见第六章、第七章。

  5. Codex 的加密压缩 blob 与 Claude Code 的可读摘要各有什么优劣?对做多供应商 fallback 的应用意味着什么?

    答案

    加密 blob 保留模型自己的内部状态(工具调用恢复数据、状态标记),损失可能更小,但不可读、不可审计、不可替换 prompt,且只有 OpenAI 能解——绑定供应商。可读摘要可审计、可按负载定制 prompt、可跨供应商携带,但只保留摘要写出来的东西。做多供应商 fallback 的应用必须有一份自己可读的会话状态(复述文件、结构化任务状态),不能只依赖某家的服务端压缩。详见第五章。

  1. 按七层给配额(长程 agent:系统 3–5%、工具定义 5–8%、记忆 3–5%、历史 30–40%、检索 5–10%、工具返回 20–30%、输入 1%、输出含思考预留 15–20%),设清理线、压缩线、硬线三条线且留距离(触发线 = 窗口 − 预留,Claude Code 83.5% = 100% − 33K/200K)。超了按代价递增处理:隔离(子 agent 在自己的窗口做探索,只带摘要回来)→ 卸载(大返回写文件,留路径 + 结构化预览,可恢复)→ 清理(批量删已消费的成功返回,保留失败记录与调用记录)→ 压缩(一次模型调用把历史摘要成一段,有损,缓存全失效,只在思考链结束处做)。详见第一章、第二章。 ↩

  2. Claude Code:微压缩旧工具返回 → 约 83.5% 处 auto-compact(预留 33K),system 不变、根目录 CLAUDE.md 与自动记忆重注入、路径规则与子目录 CLAUDE.md 丢失。Codex:轮前与循环边界两处触发,先用会话记忆的结构化任务状态替代摘要(多数不调模型),不够才调 POST /v1/responses/compact 拿回只有 OpenAI 能解的加密 compaction item,再重放待处理请求。Anthropic API:context editing 清旧工具返回(研究 agent 335K 里 96% 是文件读取);服务端 compaction 默认 150K、最低 50K,返回可读 compaction 块,可换摘要 prompt。Deep Agents:工具返回 > 20K 写文件留 10 行预览;85% 把旧写入截成指针;最后才摘要。Manus:可恢复压缩(留 URL / 路径)、todo.md 复述、保留失败。DeepSeek Harness:压缩策略为可配置插件,摘要有独立 token 上限。详见第五章。 ↩

  3. 压缩丢掉摘要没写的一切:历史细节、未卸载的工具返回、检索结果、思考块;常驻层里有磁盘真身的(CLAUDE.md、自动记忆)可重注入,按需加载的(路径规则、子目录 CLAUDE.md)丢失直到再触发;缓存前缀全部失效一次。最容易丢的是只出现一次的”用户约束”。评测:准备探针问题(目标、改过的文件、约束、上一个失败原因),在压缩点前后各问一遍比正确率,按类别统计存活率以定位摘要 prompt 要加强的类;端到端比”不压缩 vs 压缩”的完成率与成本。修复靶向:摘要 prompt 加”逐条列出用户约束”,并把约束写进复述文件。详见第五章、第七章。 ↩

这篇对你有用?

本文由 arganzheng 创作,采用 CC BY 4.0 许可协议。在保留原文作者、署名以及完整原文链接(https://arganzheng.life/context-budgeting-offloading-and-compaction.html)的前提下,欢迎各种形式的转载、翻译或商业引用。


COMMENTS

评论存放在 GitHub Discussions, 用 GitHub 账号登录即可发表,支持 Markdown。 想针对正文某句话说?选中那段文字,点浮出的「评论」即可划线评论;觉得哪里写错了,发表时勾上「同时提交 Issue」。 有人回复你时 GitHub 会按你的通知设置发邮件,不用守在这里。

×