LEARN CLAUDE CODE
S06: Context Compact — 三层压缩保持 Agent 不失忆
这一课解决什么问题
前 5 课解决了「让 Agent 能做事」的问题,但还有一个致命问题没解决:messages[] 无限增长。
每一轮循环都往 messages[] 里追加消息。一个复杂任务可能跑 50 轮,到后面 messages[] 膨胀到 100k+ token。模型处理超长上下文的质量会急剧下降——关键信息被淹没在大量中间过程里,回复变慢、变贵、变蠢。最终可能直接超出上下文窗口限制而报错。
S06 提出三层渐进式压缩方案:
核心机制
┌─────────── 三层压缩架构 ───────────────────────────┐
│ │
│ Layer 1: micro_compact (自动, 每轮) │
│ ═══════════════════════════════════════════ │
│ 触发: 每次工具调用返回结果后 │
│ 做法: 把旧的 tool_result 替换成摘要 │
│ │
│ 之前: tool_result = "文件内容...3000行代码..." │
│ 之后: tool_result = "[已读取 src/auth.ts, 142行, │
│ 包含 AuthProvider 类和 3 个方法]" │
│ │
│ 效果: 单条消息从 ~3000 tokens → ~50 tokens │
│ ───────────────────────────────────────────── │
│ │
│ Layer 2: auto_compact (自动, 阈值触发) │
│ ═══════════════════════════════════════════ │
│ 触发: messages[] 总 token 超过阈值(如 80k) │
│ 做法: 调用 LLM 生成整段对话的结构化摘要 │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ messages = [ │ │
│ │ system_prompt, │ │
│ │ {role: "user", │ │
│ │ content: "对话摘要: │ │
│ │ 1. 用户要求重构 auth 模块 │ │
│ │ 2. 已完成文件结构分析 │ │
│ │ 3. 已修改 auth/provider.ts │ │
│ │ 4. 待完成:测试更新 │ │
│ │ 关键决策:采用策略模式..."}, │ │
│ │ ... 最近几轮的原始消息 ... │ │
│ │ ] │ │
│ └─────────────────────────────────────────┘ │
│ │
│ 效果: 80k tokens → ~15k tokens │
│ ───────────────────────────────────────────── │
│ │
│ Layer 3: manual compact (手动触发) │
│ ═══════════════════════════════════════════ │
│ 触发: 用户输入 /compact 命令 │
│ 做法: 同 Layer 2,但可附带自定义指令 │
│ │
│ 例: /compact "只保留 API 设计相关的上下文" │
│ │
│ 效果: 用户主导的精确压缩 │
└─────────────────────────────────────────────────────┘
三层关系:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Layer 1 │ │ Layer 2 │ │ Layer 3 │
│ 微观 │──▶│ 宏观 │──▶│ 手动 │
│ 每轮 │ │ 阈值 │ │ 按需 │
│ 局部替换 │ │ 全局摘要 │ │ 精确控制 │
│ 无损信息 │ │ 有损压缩 │ │ 用户主导 │
└──────────┘ └──────────┘ └──────────┘
低 高
←────── 压缩力度 ──────→
关键概念解释
- micro_compact最轻量的压缩——不调用 LLM,只是用一个规则把旧的 tool_result 内容替换成一句描述。比如读取了一个 500 行的文件,过了 3 轮之后,那个文件内容就被替换成「[已读取 xxx 文件, 500 行]」。因为模型已经看过了,保留完整内容只是浪费。 — 零成本的垃圾回收。
- auto_compact当 messages[] 总 token 超过设定阈值时自动触发。调用 LLM(通常是更便宜的模型或同一模型)生成一段结构化摘要,替换掉大部分历史消息,只保留最近几轮。这是有损压缩——一些细节会丢失。 — 自动的「大扫除」,用 LLM 做摘要压缩。
- manual compact用户通过 /compact 命令手动触发的压缩。可以附带自定义指令告诉 LLM 「只保留什么」「忽略什么」,实现精确的上下文裁剪。 — 用户拥有最终控制权。
对应到 Claude Code 官方的什么
/compact + auto-compact 服务
Claude Code 的上下文管理和 S06 高度对应:
- /compact 命令 — 用户手动触发上下文压缩(Layer 3)
- auto-compact — 当 token 用量超过阈值时自动压缩(Layer 2)
- tool_result 截断 — 对过大的工具输出自动截断或摘要(类似 Layer 1)
- 压缩时保留:system prompt、最近 N 轮消息、todo 状态、关键决策
- 压缩时丢弃:中间的 tool_result 细节、已解决的讨论、冗余分析
变更对比表
| 维度 | S05(无压缩) | S06(三层压缩) |
|---|---|---|
| 上下文增长 | 只增不减,线性增长 | 三层控制,维持在阈值内 |
| 长任务能力 | 50+ 轮就会撞墙 | 可持续运行数百轮 |
| 响应质量 | 上下文太长时质量下降 | 压缩后信噪比更高 |
| 成本 | 每轮 API 调用越来越贵 | 压缩后每轮成本可控 |
| 用户控制 | 无 | /compact 命令 + 自定义指令 |
| 新增组件 | — | micro_compact + auto_compact + /compact 命令 |
权衡警告:压缩是有损的。Layer 2 的 LLM 摘要可能丢掉你认为重要的细节。这就是为什么 Layer 3(手动 compact)存在——当自动压缩丢了关键信息时,你可以手动指定保留什么。在实践中,建议在做重大决策前手动 /compact 并明确保留条件。