Codex上下文改用换窗,不再生成摘要

openai/codex 仓库里三个已经合入主干的拉取请求,把 Codex 上下文窗口管理的改造方向摆了出来:会话超出窗口时,系统不再生成摘要来压缩历史,改为直接启用一个全新窗口继续工作。相关能力统一挂在 Feature::TokenBudget 这个特性开关后面,尚未正式上线。

现在的做法是摘要式压缩。窗口快满时,系统请求服务端把此前的对话浓缩成一段摘要,用它替换原始历史。这套办法有两笔固定开销:生成摘要本身要烧 token,而压缩是有损的,接口约定、路径名、几轮前敲定的取舍,都可能在浓缩过程中被抹平。用 Codex 跑过长任务的人对后一种失败模式不陌生——模型忘了两小时前定下的规矩,还答得挺自信。

模型可以自己申请换一张纸

第一步是 6 月 11 日合入的 #27488,标题就叫”Add new context window tool”。它给模型加了一个 new_context 工具,只对模型自己开放,作者在描述里把它称作当前窗口变得不好用时的”escape hatch”。

请求被记在 AutoCompactWindow 上,采样之后消费掉,同一轮里紧接着的后续请求就落在新窗口里。新窗口的起点是一个不带摘要的压缩检查点,只保留初始上下文,此前的对话历史不再跟着走。

手动清理也走同一条路

第二步是 6 月 23 日合入的 #29743。它把手动压缩和自动压缩统一进 compact_token_budget 这一条生命周期,在 token budget 开启时,压缩不再去服务端要摘要,而在本地直接装载一套全新的初始上下文。

这一步的工程细节里藏着克制:对外可见的行为被保住了,compact 钩子照常触发,ContextCompaction 生命周期事件照常发出。也就是说,依赖这些事件的客户端不用改,底下换的是实现。

找回来的部分交给历史和笔记

前两步只解决了”扔掉”,8 月 21 日合入的 #39827 才补上”捞回来”。这个 PR 的描述写得直白:token budget 会话需要一条路子来恢复此前的对话上下文,并在窗口切换之间保住工作状态。

它加了两组工具。历史工具负责列出窗口和条目、读取某个条目、在会话内容里搜索;笔记工具负责列、读、搜、追加和写入持久笔记。调用走 Codex 后端,需要 OpenAI 提供方和后端鉴权,同样挂在特性开关 features.token_budget.use_history_notes_history 之下。

工程上做了几处限流:输出按截断感知处理,请求参数有边界。自动审阅提出的意见集中在明文结果的 1 万 token 上限、笔记操作的参数绑定限制,以及建议分阶段灰度。

换掉的到底是什么

摘要压缩和换窗加检索,本质上是两种记忆策略。前者是隐式的有损压缩,模型不知道自己丢了什么,也没有办法找回来;后者是显式的无状态重启,模型清楚地知道旧内容还在某个地方,需要就去查。

代价也跟着换了个位置。有损压缩的失败是悄悄发生的,换窗的失败会变成”该查的时候没去查”或者”查了但没查准”。前者难以调试,后者至少能在日志里看见。对做长任务的 Agent 来说,可观测的失败比沉默的失败好处理得多。

省下来的钱是另一头的收益。摘要要走一次模型调用,长会话里这笔支出会反复发生;换窗不产生这次调用,检索只在需要时按条目取。对每天跑满额度的重度用户,这是实打实的账。

需要说清楚的是节奏:PR 合入不等于功能上线。这三个改动全部藏在特性开关后面,自动审阅还在建议分阶段放量。从 6 月的第一版工具到 8 月的历史与笔记补完,OpenAI 在这条路上磨了两个多月,开关什么时候打开、打开给谁,仓库记录里没有答案。

参考来源:openai/codex 仓库三份已合入的拉取请求、CocoLoop、GitHub 自动审阅意见;工具名、特性开关名与合入状态按仓库记录逐条核对。