Code Agent 的上下文压缩:不是 zip,而是工作记忆管理

拆解四款 Code Agent 的上下文压缩机制------OpenCode、Codex、Claude Code、Pi 各自怎么做,以及它们殊途同归的设计共识。

先搞清楚:这里的「压缩」不是 zip

如果把 AI 编程助手(Code Agent)想成一个帮你写代码的同事,它面前只有一块有限大小的白板。

你让它查文件、跑命令、读日志、改代码------这些全会写到白板上。写满了,新的就放不下了。轻一点答非所问,重一点直接报错停工。

这时候就需要「上下文压缩」。但这里的压缩不是 zip 那种无损打包,而是把旧内容重新整理成一份更短、更适合继续干活的版本 ------本质是有损的任务交接


白板上到底装了什么?

很多人以为上下文只有「聊天记录」。远不止如此:

  • 用户和 AI 的对话
  • 读取过的文件内容
  • 命令行输出和执行日志
  • 工具调用的参数和返回结果
  • 图片、PDF 等附件
  • 项目规则文件(AGENTS.mdCLAUDE.md
  • MCP 工具描述、skill 描述、auto memory

真正把上下文撑爆的,往往不是你说的那句话,而是 AI 干活过程中产生的大量中间产物------尤其是动辄几百行的日志和工具输出。


压缩的正确心智模型:四层记忆

要理解上下文压缩,最好不要把它想成「一刀切的摘要」,而是想成一套分层记忆管理

层次 内容 处理方式
固定层 团队规范、个人偏好、项目规则 放在文件里,不进聊天记录
热数据层 最近几轮对话、刚改的文件 保留原文
温数据层 更早的工作历史 压缩成结构化交接单
冷数据层 大文件全文、历史日志、记忆库 不进当前窗口,按需检索

所有主流 Code Agent 的上下文管理,本质上都在做同一件事:把对的内容放到对的层次上


什么时候触发压缩?

不能等白板满了才动手------那时候已经来不及了。

预防性触发:每轮对话结束后,系统估算当前上下文占了多少空间。接近上限就在下一轮开始前主动压缩。就像开车看油表,剩四分之一就找加油站。

故障性触发:如果模型因上下文太长直接报错,系统也会紧急启动压缩。这是兜底机制------不理想,但至少能让工作继续。

手动触发 :用户主动执行 /compact 命令(Codex 和 Claude Code 都支持),适合你觉得对话已经太长、想清理一下的场景。


压缩前后到底发生了什么?

压缩不是逐条「缩短」旧消息,而是把一整段历史折叠成一个检查点。

压缩前,消息流大概长这样:

text 复制代码
U1  用户:「帮我修一下支付页面的 bug」
A1  Agent:分析代码,调用 read_file、grep_search 等工具
U2  用户:「后端先别改,保持兼容」
A2  Agent:继续排查,执行 bash 跑测试,输出大量日志
U3  用户:「看起来是前端传参问题,帮我改 PaymentForm.tsx」
A3  Agent:修改文件,跑测试验证
     (中间夹杂大量文件内容、终端日志、工具输出......上下文快满了)

压缩后,后续模型实际看到的只有这些:

text 复制代码
U4  [compaction task] "What did we do so far?"
A4  [summary checkpoint]
     ## Goal
     修复支付页面提交报错
     ## Constraints
     后端先不改,保持兼容
     ## Accomplished
     定位到 PaymentForm.tsx 传参为空,已修改前端逻辑
     ## Relevant Files
     src/PaymentForm.tsx, src/api/submitOrder.ts
     ## Next Steps
     补充单元测试,确认异常是否消失
U5  [replay] 用户:「看起来是前端传参问题,帮我改 PaymentForm.tsx」
     → Agent 从这里继续工作

U1-A3 的原始消息仍在数据库里,但已不再进入后续 prompt。A4 这条 summary 就是新的「检查点」,U5 把最后一条真实用户请求重放回来,确保 Agent 不会丢掉当前意图。

这是整个机制最关键的设计------用检查点划定新边界,而不是改写历史


四家产品怎么做?一个一个拆

OpenCode:流水线最清晰

OpenCode 把压缩做成了一条完整流水线,每个环节的职责非常明确。

第一步:先清理噪音。 不是一上来就摘要,而是先对旧工具输出做 prune------保护最近两轮 turn 和最近 40,000 token 的工具结果,更老的降级为一行占位文本 [Old tool result content cleared]。数据还在,但不再吃上下文空间。

第二步:生成交接单。 用专门的 compaction agent(可以自定义模型和提示词)把旧历史压成结构化摘要,格式包括:Goal / Instructions / Discoveries / Accomplished / Relevant files。

第三步:自动续跑。 压缩完不停下来。如果是因为 overflow 触发,系统会找到最后一条真实用户请求重新「重放」(replay),让工作无缝接续。如果找不到可重放的请求,就插入一条「继续下一步」的合成指令。

亮点:压缩是消息流里的一种正式任务类型,和普通 prompt 共用一条主循环,不需要额外的后台状态机。支持插件钩子自定义。

Codex:两条压缩路径并存

OpenAI 的 Codex 比较特殊------它同时存在「本地可读摘要」和「服务端 opaque 压缩」两种机制。

本地侧 :compaction prompt 写得很直接------要求生成给「另一个 LLM 接着干活」的 handoff summary,包括当前进度、关键决策、重要约束、剩余步骤。同时有一个关键常量 COMPACT_USER_MESSAGE_MAX_TOKENS = 20,000:从后往前收集最近用户消息保留原文,更早的部分才走摘要。

服务端侧 :OpenAI API 提供了 context_management + compact_threshold 选项,触发后响应里会出现一个加密的 compaction item ------不是给人读的,而是模型内部的状态压缩。还有单独的 /responses/compact 端点,返回「canonical next context window」,官方明确说应原样使用,别自己乱裁。

特别细节 :Codex 区分了「手动/预轮压缩」和「中途压缩」的摘要放置位置------中途压缩时会把摘要插到最后一条真实用户消息之前,而不是末尾。这不是细枝末节------摘要在 prompt 里的位置会直接影响模型续跑的稳定性

Claude Code:与其压缩,不如少装

Claude Code 最值得学的不是「怎么压缩」,而是从架构层面减少主窗口的负担

Subagent 隔离:阅读大文件、全仓搜索这类任务交给子 Agent 在独立上下文里完成,只有摘要和少量 metadata 返回主线程。主对话从头到尾不会被这些过程污染。

Memory 机制:学到的信息存进 auto memory,需要时再取------本质是 JIT(Just-In-Time)上下文检索,而不是提前全塞进去。默认每次只加载前 200 行或 25KB。

按需加载规则 :父目录的 CLAUDE.md 启动时加载,子目录的 CLAUDE.md 在读到相关文件时才按需加载。

当然,Claude Code 也有 /compact 命令和 API 级别的 compaction(compact_20260112,默认 150,000 input tokens 触发)。但它的核心哲学很明确:与其事后压缩,不如一开始就别把不该进来的东西装进来。

Pi:最适合抄的参考实现

Pi 是一个轻量级的开源 terminal coding harness,没有 OpenCode 或 Codex 那么高知名度,但压缩机制做得非常干净透明,适合二次开发或作为学习参考。

触发公式直白contextTokens > contextWindow - reserveTokens,默认预留 16,384 token,保留最近 20,000 token 原文。

显式状态迁移 :压缩后追加一条 CompactionEntry,用 firstKeptEntryId 标记保留边界------不是偷偷改写对话,而是留下明确的锚点。下次重载只加载「摘要 + 从锚点开始的原始消息」。

工具输出特别处理:序列化摘要输入时,工具结果截断到 2,000 字符,超出部分只标记截掉了多少。

分支摘要 :Pi 通过 /tree 在不同对话分支间跳转时,会把离开的分支总结到目标分支里。还提供 session_before_compact 扩展事件,允许外部扩展自定义摘要逻辑。


横向对比

OpenCode Codex Claude Code Pi
核心策略 先 prune 噪音,再写交接单,自动续跑 保近期原文,摘要老历史,双路径压缩 少装东西 + subagent 隔离 透明可插拔,显式锚点
规则外置 instruction files AGENTS.md CLAUDE.md + auto memory 配置文件
近期保留 最后一条真实请求 replay 最近 ~20k token 用户消息 subagent 保持主线程干净 最近 ~20k token 原文
工具输出 prune 降级为占位文本 服务端裁剪 不进主窗口(subagent 处理) 截断到 2,000 字符
摘要格式 Goal/Instructions/Discoveries/Accomplished Handoff note 含进度+约束+下步 结构化 summary Goal/Constraints/Progress/Decisions/Next
压缩后续跑 自动 replay 或合成 continue 手动/自动均可 /compact 后手动继续 自动
服务端压缩 有(加密 opaque item) 有(compaction block)
开源程度 完全开源 完全开源 有公开仓库和文档 完全开源

方向完全一致:不让 AI 背着全部历史硬跑,而是帮它重新整理工作记忆。


容易踩的坑

1. 摘要太泛。 如果压缩结果只剩「我们讨论了 bug 修复」,几乎等于没说。好的摘要必须包含具体目标、关键决定、文件路径、下一步动作。

2. 丢掉最新意图。 最容易丢的不是旧历史,而是「用户刚刚到底要你做什么」。所以 OpenCode 有 replay、Codex 保留最近用户消息、Pi 有锚点------都是在保护当前意图。

3. 稳定规则靠摘要保留。 团队规范这种东西,如果只写在聊天里,一压缩就可能走样。必须外置到独立文件。

4. 不先处理工具输出。 大量上下文不是被「思考」撑爆的,而是被工具回显撑爆的。OpenCode 和 Pi 都把工具输出当首要治理对象。

5. 同一线程压缩太多次。 多轮压缩后准确性会衰减。Codex 源码里直接建议:长线程不如开新线程。

6. 手动乱裁 API 压缩结果。 OpenAI 的 compaction item 是加密的,Anthropic 的 compaction block 之前内容会被忽略------既然官方已经做了状态迁移,就别自己二次破坏。


一句话总结

Code Agent 的上下文压缩,不是文本压缩算法,而是一套工作记忆管理机制

长期规则外置,近期细节保热,旧历史写成交接单,大噪音优先裁掉,并行任务拆到独立上下文里。

OpenCode 把这条流水线做得最清晰;Codex 同时展示了本地摘要和服务端状态压缩两条路线;Claude Code 说与其事后压缩不如少装东西;Pi 把机制做成了最适合抄的参考实现。

名字叫「压缩」,但和 zip 无关。它真正做的事是------让 AI 知道什么该记住、什么该忘掉、什么该放在别的地方。


写于 2026 年 3 月 28 日

相关推荐
AI程序员2 小时前
OpenAI Frontier 到底是什么:企业 Agent 不只是需要一个更强的模型
人工智能
爱喝白开水a2 小时前
春节后普通程序员如何“丝滑”跨行AI:不啃算法,也能拿走AI
java·人工智能·算法·spring·ai·前端框架·大模型
两万五千个小时2 小时前
解析 OpenClaw AgentSkills:AI Agent 如何通过「技能包」实现专业化
人工智能·程序员·代码规范
热点速递2 小时前
美团2025年“翻车”实录:从盈利王者到赤字领跑!
人工智能·业界资讯
ai产品老杨2 小时前
异构计算时代的架构突围:基于 Docker 的 AI 视频平台如何实现 X86/ARM 与 GPU/NPU 全兼容(源码交付)
人工智能·docker·架构
beyond阿亮2 小时前
OpenClaw在Windows上接入飞书完整指南
人工智能·windows·ai·openclaw
ybdesire2 小时前
通过训练代码来理解DLLM扩散语言模型
人工智能·语言模型·自然语言处理
多年小白2 小时前
Anthropic发布Mythos模型:为什么网络安全板块先跌为敬
网络·人工智能·科技·ai编程
爱丽_2 小时前
多因素最优解到梯度下降:AI 训练的数学主线
人工智能