Codex Context Compaction 全过程深度解析:Agent 压缩后为何不失效仍能执行任务核心原因

2026-06-24阅读 0热度 0
Context
长时间使用代码 Agent,几乎都会遇到这种场景:前半小时还在认真检查仓库、执行测试、解决冲突,下一轮对话就像换了个模型——只记得“在处理一个项目”,但分支名、PR编号、刚才失败的测试是哪个,全忘了。 这种崩溃很少发生在第一轮,而是上下文被压缩之后。 因此,很长一段时间里,大家普遍很保守:上下文快满之前,先让 Agent 写一份交接文档;重要任务做到一半,尽量不要触发自动压缩;能新开会话就新开会话。听着是麻烦了点,但至少可控。 最近 Codex 的风向变了。越来越多人开始把上下文窗口交给系统自己处理。它自动压缩,继续跑,再压缩,再继续跑。最让人意外的不是它“还能回答”,而是它在复杂任务里还能记住不少低层事实:分支、stash、merge commit、构建结果、用户最后一句确认。 这背后不是某个提示词突然写得更聪明了。更准确地说,Codex 把压缩从“一段摘要”做成了一次状态迁移。 *图:长程 Agent 真正需要保住的是现场碎片,而不只是文章主线。*

窗口隐藏了,不代表窗口不重要

Codex App 曾经把上下文窗口的使用比例放在主界面上。后来这个指示器被挪到了二级入口,只能通过 /status/compact 之类的命令查看。这个改动让不少重度用户很不爽。 原因很好理解。对短问答来说,上下文窗口只是一个技术参数;对长程编码来说,它更像油表。你不一定每秒盯着它,但你需要知道车还能跑多远。 Codex 团队当时给出的方向是 “vibe contexting”:用户不再需要主动管理上下文。 这句话如果放在一年前,很像产品经理的漂亮话。因为压缩一直是 Agent 链路里最脆弱的地方。它不是把文本缩短那么简单,而是在决定哪些事实还能活到下一轮,哪些事实永远丢掉。 Codex 敢把窗口感知降级,真正依赖的是下面几层机制:入口截流、远程压缩、系统脚手架重建,以及服务端和模型的配合。

真正进入压缩之前,很多内容已经被处理掉了

很多人以为上下文管理就是“满了以后压一下”。Codex 不是这么干的。 在完整压缩之前,它已经先把一批容易撑爆窗口的内容压住了:
位置Codex 怎么处理这意味着什么
工具输出工具结果进入历史时就做中间截断,保留头尾中间细节可能直接消失
终端输出PTY 原始输出只留头尾,总量有限大日志不会完整进上下文
Hook 结果太大的 hook 输出写到临时文件,只给预览和路径模型需要时可以再读,但不会默认吃满窗口
历史消息清理不成对的工具调用/输出、孤儿输出和不支持的图片保证请求结构干净
系统上下文只追加变化部分,不每轮重复塞满配置降低固定上下文的增长速度
这里有个细节挺重要:很多截断发生在内容进入历史的那一刻。也就是说,它们发生在 prompt cache 形成之前。 这不是洁癖,是成本问题。模型服务端的前缀缓存依赖逐 token 一致。如果一条旧工具结果已经进入历史,后面再回头改它,改动点之后的缓存可能全废。对十几万 token 的长程会话来说,一次 cache miss 可能就是一轮账单和延迟的数量级变化。 Codex 的选择比较硬:先在入口控制住体积。代价也很明确,被截掉的内容未必能回来。

本地压缩:一份交接文档能救简单任务,救不了复杂现场

Codex 压缩的第一条路叫 本地压缩。它的做法并不神秘:让当前模型给后续模型写一份 handoff summary。 流程大概是这样: *图:本地压缩以明文摘要替换旧历史* 这套方案非常像人类工程师写交接文档。写得好,后面的人能接上;写漏了,后面的人只能猜。 本地压缩 最大的问题就在这里:压缩后的替换历史里,很多原始材料不会再出现。助手的中间判断、工具调用的原始结果、推理过程、网络结果,大多只能靠摘要间接留下来。 简单任务还能扛住。比如开一个 GitHub issue、补一条评论、确认几个标签,摘要抓住主线就行。 复杂任务不一样。长程编码里真正致命的常常是小事实: - 当前在哪个分支; - 哪个 stash 是临时绕过签名用的; - 哪个测试 315/315 通过; - 哪个构建失败是 x86_64 slice 缺失; - 用户最后是否已经验收。 这些东西如果没被摘要写进去,下一轮模型不会“自然想起来”。它只能重新查,或者老老实实说不知道。

远程压缩:客户端看不懂,但效果明显不一样

第二条路是 远程压缩。这里开始变得有意思。 Codex 会根据 provider 判断能不能走远程压缩。OpenAI 原生 provider 和 Azure Responses provider 支持;常见第三方 provider、中转站、本地模型入口默认不支持。分流逻辑大致是: *图:不同 provider 下的远程压缩路径* 远程 V1 走专用 /v1/responses/compact 端点。远程 V2 则把压缩触发器塞进普通 Responses 流:输入末尾多一个 CompactionTrigger,服务端返回一条特殊的压缩项。 两条远程路径最后都会产生类似的东西:encrypted_content。 客户端不会拿到一段可读摘要。它拿到的是一块 opaque state,一段加密内容。后续请求继续带上它,由服务端解密并组装给模型。 *图:encrypted_content 在服务端完成状态迁移* 这也是 远程压缩本地压缩 的本质区别:本地留给客户端一份“文本交接”;远程留给服务端一份“状态块”。 *图:远程压缩的关键变化,是把压缩从文本摘要推进到服务端状态承载。*

实验最刺眼的地方:差距不是 5 分,而是一个等级

如果只看机制,很容易陷入猜测。真正有说服力的是同一批长程任务分别走本地、远程 V1、远程 V2 后的恢复效果。 一类简单任务里,远程比本地稳定一些,但差距还不算夸张:
测试内容本地远程
主线和决策链恢复89.796.6
反事实判断88100
低层事实定位84.092.3
禁用工具后的续跑8692
允许工具后的最小验证8895
平均87.195.2
真正拉开差距的是复杂编码任务。比如持续处理一个 Multi-Mac PR:合并上游、解冲突、stash 管理、构建验证、真机测试、用户验收,全都混在同一条会话里。
压缩路径客观评分关键事实命中
本地压缩约 28/1005/24
远程 V1约 94/10023/24
远程 V2约 92/10023/24
本地的失败很克制,但也很致命。它没有大规模编造,而是大量 unknown。它知道自己不知道。可对执行任务来说,这几乎等价于失忆。 远程 V1/V2 则能恢复仓库、分支、merge commit、PR #137、stash 内容、测试通过数量、真机型号和用户确认。这里面不少事实都不是“文章主旨”,而是现场碎片。长程任务能不能接上,往往就靠这些碎片。 所以 远程压缩 的优势不像是 prompt 稍微好一点。它更像保留了本地摘要留不住的状态。

服务端黑盒:提示词之外还有多少操作空间

有人用 prompt injection 研究过 远程压缩 的服务端流程。能看到的大致是这样:服务端有一个压缩器 LLM,它读入系统提示和会话历史,写出一份明文摘要;随后服务端把这份摘要加密成 blob。下一轮请求时,服务端再解密 blob,拼上交接提示,交给模型继续执行。 麻烦也在这里。泄露出来的压缩提示,和 本地压缩 开源出来的那段提示词非常接近。既然提示词差不多,为什么复杂任务里一个接近失忆,一个还能恢复大部分现场? 更合理的理解是,把 prompt injection 看到的东西理解成“表层文本”,不是完整机制。服务端真正能动手脚的地方,比那几行 prompt 多得多。 *图:远程压缩可能包含隐藏信号和上下文重组* 第一种可能,是服务端给压缩器的输入里夹了额外信号。比如工具调用的结构化摘要、关键实体列表、对话的元数据标注。它们不一定会以自然语言形式出现在 prompt 里,所以即使用注入方式套出了提示词,也看不到这些中间信号。 第二种可能,是加密 blob 里不只有一段普通摘要。表面实验看到的是交接文本,但服务端在加密前完全可能追加后处理结果:工具输出摘要、关键决策节点、甚至某种更适合恢复任务状态的结构化表示。客户端只拿到 encrypted_content,没法判断里面到底装了什么。 第三种可能,是远程的压缩器本来就不是用户当前正在用的模型。本地压缩 只能调用当前配置模型来写交接文档;远程压缩 的压缩器由服务端选择,它可能针对压缩任务做过优化,更擅长从一堆工具调用和对话碎片里抓住任务状态。这个猜测没法从客户端证实,但能解释为什么同一套提示词会拉开这么大差距。 第四种可能,发生在解密之后。能看到摘要被放在交接提示后面,但服务端组装最终上下文时是否还有检索、重排、裁剪或额外注入,外部很难观察。换句话说,压缩不是一次“模型写摘要”就结束了,后面还有上下文组装这一步。 所以 远程压缩 的强点未必是“提示词更好”。更可能是服务端掌握了从压缩、加密、保存、解密到重新组装上下文的整条链路。客户端只能看到加密 blob 进来、模型状态恢复出去,中间发生了什么基本不可见。 这也是它最让人不踏实的地方:效果确实强,但不可审计。你不知道它保住了哪些事实,也不知道哪些事实已经在黑盒里丢了。

只靠压缩还不够,系统规则必须重新搭起来

长程 Agent 压缩后容易出问题,还有一个原因:它不只会忘任务,也会忘规则。 比如项目里的 AGENTS.md 怎么要求,当前沙箱策略是什么,哪些工具可用,哪些技能已安装,工作目录和 git 状态是什么。这些东西如果也靠摘要传递,压几次以后迟早变形。 Codex 的做法是:系统约束不交给摘要。 压缩完成后,Codex 会清掉一个基线标记。下一轮开始时,它发现基线不存在,就重新构造初始上下文。这个脚手架会把开发规则、权限策略、可用工具、MCP、插件、环境信息、协作模式等重新注入。 *图:任务状态与系统脚手架在下一轮重新合流* 这点很关键。摘要只需要记住“任务发生了什么”。至于“当前系统要求模型怎么工作”,下一轮重新搭。 换句话说,Codex 的恢复不是一条腿走路: - 压缩负责迁移任务状态; - prompt scaffold 负责恢复执行环境和规则。 很多人只盯着摘要,就会低估第二层机制的作用。

Claude Code 的思路不同:它更像在维护一张视图

拿 Claude Code 对比,会更容易看出 Codex 的设计取舍。 Codex 像 checkpoint/rebase:压缩后生成一段替换历史,把旧历史换成新基线。 Claude Code 更像数据库视图:原始记录尽量追加写入,模型看到的是预算、外置、折叠、缓存编辑之后的投影视图。
维度CodexClaude Code
大工具输出入口截断,简单直接外置到 sidecar 文件,保留读取路径
完整压缩前的减压主要靠入口控制和历史清洗工具预算、精简、微压缩、上下文折叠多层处理
压缩提示极简交接100+ 行审计清单式提示
服务端协作方式返回 opaque encrypted statecache_editscontext_management 等声明式能力
客户端透明度低,服务端空间大高一些,但客户端逻辑复杂
两边没有绝对优劣。Codex 把更多事情委托给服务端,效果可以很强,但黑盒感重。Claude Code 把更多控制留在客户端,工程复杂,调试空间也更大。 更愿意把这个看成两种架构性选择,而不是两种摘要写法。

Prompt Cache 是这套设计里最现实的约束

为什么 Codex 不在历史中间做细粒度修改?为什么 Claude Code 那么在意外置决策“冻结”?绕不开 prompt cache。 长程会话里,单次请求十几万 token 并不稀奇。上一轮已经出现过的前缀,如果这一轮逐 token 一致,就可以命中缓存。命中的 token 便宜得多,也快得多。 但缓存很脆。你改了历史中间某个旧工具结果,从那里往后的 token 都可能失去命中。 所以两个系统都在避免“中间切一刀”:
设计动作背后的 cache 考虑
Codex 在内容入史前截断还没形成缓存,不破坏旧 prefix
Codex 完整压缩时替换整段历史不做局部手术,直接建立新基线
Claude Code 冻结外置决策保证后续线格式不变
Claude Code 用 cache_edits让服务端动缓存层,不改客户端消息内容
这也是上下文压缩最容易被忽略的地方。不是“文本越短越好”。信息保留、窗口大小、缓存命中率三者之间一直在互相拉扯。

更大的变化:模型和 Harness 正在绑在一起

远程压缩 不是一个孤立功能。它其实暴露了 Agent 竞争的下一层:模型和 Harness 正在变成一套东西。 过去大家更关心“哪个模型更强”。现在越来越多体验差异来自模型外面的那层系统:工具协议、上下文压缩、缓存策略、权限模型、IDE 集成、历史状态恢复。 OpenAI 有 Codex 的 encrypted_contentCompactionTrigger。Anthropic 有 Claude Code 的 cache_editscontext_management。这些能力并不是裸模型 API 的简单包装,而是服务端、客户端、训练数据一起配合出来的。 第三方 Agent 当然还能做得很好,但它要追的东西变多了:协议细节、服务端 beta 能力、模型后训练习惯、真实用户长程数据。任何一个环节慢半拍,体验都可能差一点。 这也是为什么 “Model + Harness = Agent” 会越来越像行业共识。只提供模型,不做 Harness,就等于把最终用户体验交给别人,也失去了最有价值的交互数据。

结语:上下文压缩已经不是摘要问题

Codex 多次压缩后还能继续跑,原因大概可以拆成三层: 1. 入口层先控制工具输出和历史膨胀,避免窗口太快被噪声吃掉。 2. 远程压缩 把任务状态交给服务端处理,用 opaque state 承载比明文摘要更强的恢复能力。 3. Prompt scaffold 在压缩后重建系统规则,让摘要不必背负所有环境约束。 这套机制当然还有黑盒问题。encrypted_content 里到底有什么?服务端压缩器是什么模型?解密后怎样重组上下文?外部只能猜个轮廓。 但实验结果已经足够说明一点:长程 Agent 的能力,很多时候不只取决于模型会不会推理,还取决于它怎么保存现场、怎么遗忘、怎么在遗忘后重新接上。 所谓 “vibe contexting”,表面上是用户不用管上下文了。底下其实是一堆很不 vibe 的工程。

推荐阅读

Dynamic Workflows 深度解析:Claude Code 为什么把多 Agent 编排写进可执行代码 Claude Opus 4.8 Agent 交付力拆解:为什么它更像工程负责人? 为什么 AI Coding 难进生产环境?深入了解 Everything-Claude-Code! 平台智能化到了分水岭:为什么配置代码化才是 AI Coding 的下一代接口 Agent Runtime 九个关键设计:状态外化、上下文压缩与多智能体协同
免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策