微压缩——精准上下文修剪的艺术

你有没有这样的经历:搬家时把整箱东西封好抬走(自动压缩),但抽屉里那些零散的小东西怎么处理?整箱抬走吧,太占地方;扔了吧,里面可能还有有用的。这时候你需要的是"精准整理"——把该扔的扔,该留的留。
这就是微压缩要做的事。
自动压缩是搬家,微压缩是整理抽屉
上一篇我们聊了自动压缩——当房子快装满时,把整个房间打包成摘要。这很有效,但有点粗暴,就像你把整个书柜封箱,找本书还得开箱翻。
微压缩不一样,它是"精准修剪":
| 自动压缩 | 微压缩 |
|---|---|
| 房子快满时才触发 | 随时发现"垃圾"就清理 |
| 整箱打包 | 精准挑出不需要的 |
| 生成摘要替代原文 | 直接删除或替换内容 |
| 代价高(要调用LLM) | 代价低(直接操作) |
打个比方:
- 自动压缩:搬家时把整个书房装箱
- 微压缩:整理书桌时把用过的草稿纸扔进垃圾桶
两者配合,AI的记忆管理才能既高效又精准。
微压缩的三种"清洁工"
Claude Code其实有三个"清洁工"在轮流值班,各自负责不同的场景:
一号清洁工:时间触发(午休回来后的整理)
想象一下:你上午用Claude Code查了一堆资料,然后去吃午饭。下午1点回来继续——中间隔了3个小时。
这时候发生了什么?服务器的缓存过期了。Anthropic的缓存有效期是1小时,3小时后肯定失效。这意味着你下次提问时,服务器要把你的整个对话历史重新缓存一遍——得花不少钱。
时间触发微压缩的逻辑很直接:既然缓存都过期了,不如先把旧内容清掉,让重写的内容更小更便宜。
它怎么做?
- 检查"上次AI回复"是多久以前(默认超过60分钟)
- 收集所有可压缩的工具结果(搜索、文件读取等)
- 只保留最近的5个,其余的替换为占位符:
[Old tool result content cleared] - 下次对话时,重写的内容小了,省钱
这就像你午休回来,发现桌上的草稿纸已经被保洁阿姨收走了——反正你也不在,留着也没用。
二号清洁工:缓存微压缩(不破坏缓存的精准手术)
时间触发有个问题:它修改了消息内容,导致缓存前缀变了,下次要重新缓存。
但在实时对话中,这不可接受——你刚积累的缓存可能值好几万token,不能说丢就丢。
缓存微压缩用了一个巧妙的方法:不修改本地消息,而是告诉服务器"在缓存里删掉这些内容"。
这叫cache_edits,工作原理像遥控指挥:
AI:服务器你好,帮我把第3、5、7条工具结果从缓存里删掉
服务器:好的,删掉了。缓存前缀还是连续的,下次还能命中
AI:收到,继续对话
这样,本地消息没动,服务器缓存也没被破坏,但内容确实被清理了——两全其美。
这个清洁工在什么时候工作?
- 当积累的可压缩工具结果超过阈值(比如20个)
- 保留最近的几个,其余的标记为"待删除"
- 下次API调用时,通过
cache_edits指令让服务器删除
三号清洁工:API Context Management(声明式管家)
前两个都是"命令式"的——程序决定删什么、什么时候删。API Context Management是"声明式"的:你告诉服务器"超过18万token时,帮我清理一下",服务器自己执行。
你可以这么配置:
- 当输入token超过180000时触发
- 保留最近的40000 token
- 清理这些工具的结果:Bash、Grep、Glob、FileRead等
- 但FileEdit、FileWrite的指令要保留
这就像你请了个智能管家:不用每次吩咐,它会按你定的规则自动打扫。
三种机制的优先级:
- 时间触发最先检查(缓存过期了,其他的都不用做了)
- 缓存微压缩其次(缓存还热,精准清理)
- API Context Management始终存在(声明式基线)
哪些东西会被"扔掉"?
不是所有东西都会被微压缩清理。三个清洁工有不同的"清理清单":
时间触发和缓存微压缩会清理:
Read:文件读取结果Bash:命令输出Grep:搜索结果Glob:文件匹配列表WebSearch、WebFetch:网页内容Edit、Write:文件编辑/写入的结果
API Context Management还会额外处理:
NotebookEdit:笔记本编辑FileEdit、FileWrite的指令(而不仅仅是结果)thinking块:extended thinking模型的思考过程
不会被清理的:
- 对话消息本身(用户和AI的聊天)
- 系统提示词
- CLAUDE.md的内容
- 工具调用指令(什么时候清理结果,不清理调用本身)
这就像保洁阿姨只收走垃圾桶里的纸,不动你桌上的书。
微压缩的精妙设计
微压缩系统有几个值得学习的工程巧思:
1. 缓存中断的协调
有个专门的模块在监控"缓存是否中断"——如果缓存命中token突然下降,就报警。但微压缩故意减少了缓存内容,这不应该算"中断"。
怎么解决?
- 微压缩执行前,通知检测器:“我要删东西了,你别慌”
- 检测器看到标记,就知道这次下降是预期的,不报错了
这就像你跟保安说:“我要扔垃圾,别当我小偷。”
2. 子代理隔离
Claude Code可以fork出子代理(比如专门搜索的agent)。每个子代理有自己的对话历史。
微压缩只对主线程执行。为什么?
如果子代理的工具结果被注册到全局状态,主线程下次执行时会说"我要删第7个工具"——但这个工具在主线程的消息里不存在,导致无效操作。
通过isMainThreadSource()检查,子代理被排除在外,各自打扫各自的房间。
3. 幂等性保证
时间触发可能被执行多次(虽然不应该)。代码里加了守卫:
if (block.content !== TIME_BASED_MC_CLEARED_MESSAGE) {
// 清理并统计
}
如果已经被清理过,就不再统计token节省——避免重复计算。
这就像你记账时,同一笔支出只记一次。
实战:理解AI的"选择性遗忘"
理解微压缩,能帮你更好地使用Claude Code:
场景1:AI说"我不记得那个搜索结果了"
长对话后,AI可能忘了之前某次grep的结果。这不是幻觉,是微压缩把旧结果清掉了。
被清理的结果会变成这样:
[Old tool result content cleared]
如果需要重新参考,直接让AI重新搜索——比让它"回忆"被清掉的内容更靠谱。
场景2:离开一小时回来,AI"失忆"了
如果你离开超过1小时,时间触发可能已经清掉了大部分旧工具结果(只保留最近5个)。这是正常的——因为缓存过期了,清掉旧内容能减少重新缓存的成本。
回来后,让AI重新读取关键文件是正常操作。
场景3:重要信息放哪里才安全?
微压缩只清理工具结果,不影响系统提示词。所以:
- CLAUDE.md:安全,不会被清理
- 工具结果:可能被清理
- 对话历史:安全,但会被压缩
关键的项目信息放CLAUDE.md,就像写在白板上,保洁阿姨不会擦。
场景4:并行搜索时有些结果"丢失"了
当AI同时发起多个搜索,如果总结果超过200K字符限制,某些结果会被持久化到磁盘(提示"Output too large, saved to file")。
这是预算机制在防止上下文膨胀。你可以用更精确的搜索条件减少单次输出。
微压缩 vs 自动压缩:组合拳
两种机制配合,形成完整的上下文管理策略:
| 阶段 | 做什么 | 比喻 |
|---|---|---|
| 日常 | 微压缩清理过时工具结果 | 随手扔垃圾 |
| 接近上限 | 微压缩加速清理 | 勤倒垃圾 |
| 达到上限 | 自动压缩生成摘要 | 打包整箱 |
| 严重超载 | 截断最早的消息 | 扔掉最旧的箱子 |
这就像你房间的管理:
- 平时随手整理(微压缩)
- 周末大扫除(自动压缩)
- 搬家时扔东西(截断)
这对构建AI Agent的启示
如果你想设计自己的AI Agent,微压缩机制值得借鉴:
1. 分层清理策略
不要只有一个"压缩"按钮,而是分层次:
- 细粒度:单个内容的清理(微压缩)
- 中粒度:相关内容的批量清理
- 粗粒度:整体摘要(自动压缩)
2. 区分"可清理"和"不可清理"
明确定义哪些内容可以丢弃:
- 搜索结果:可清理(可以重新搜)
- 文件内容:可清理(可以重新读)
- 用户指令:不可清理(丢了就没了)
- 系统配置:不可清理(影响行为)
3. 利用外部能力
Anthropic的cache_edits让客户端可以远程操作服务端缓存。如果你的API支持类似能力,可以实现"不破坏前缀的清理"。
4. 预期管理
用户需要知道"为什么AI忘了"。可以在UI中显示:
- 哪些工具结果被清理了
- 为什么被清理(时间/数量/大小)
- 如何重新获取(重新执行工具)
总结
微压缩是Claude Code上下文管理的"精细手术刀":
- 三种机制:时间触发(缓存过期后)、缓存微压缩(精准手术)、API Context Management(声明式管家)
- 分层协作:微压缩处理细节,自动压缩处理大局
- 智能取舍:只清理可重建的内容,保留关键信息
- 用户感知:理解"AI忘了"可能是因为微压缩,不是bug
这就像整理房间:
- 自动压缩是换季时的大扫除
- 微压缩是每天随手整理
- 两者配合,房子才能住得舒服
理解微压缩,你就能:
- 理解AI在长对话中的"选择性遗忘"
- 合理安排重要信息的存放位置
- 在自己的AI Agent中实现类似的精细管理
下篇咱们聊聊Token预算——200K怎么花才值。
