Codex Desktop 去掉 context usage indicator,不是因为 context window 消失了。更可能的解释是:OpenAI 不再希望用户亲自管理它。

争议来自这个 GitHub issue:Codex Desktop no longer shows visible context/token usage indicator。长时间 coding 时,这个数字原本很有用。快到上限,就手动 compact、少贴日志,或者另开一个 thread。

OpenAI developer 的回复大意是:移除是有意的。

Codex context window indicator discussion

用户仍可通过 /status 查看状态,也可以执行 /compact。改变的是默认心智。Codex 希望 context management 像虚拟内存一样退到系统内部,而不是成为用户持续盯着的仪表。

物理限制当然还在。工具输出会占 token,历史消息也要进入模型。所谓「无限 context」,只是 runtime 尽量让一次任务在多次压缩后继续运行。

Agent 通常怎样压缩 Context

最简单的手段是截断工具输出。Shell、search 和 API response 很容易吃掉大部分 context。可以只保留头尾,把完整内容写进文件:

command output:
  first N lines
  ... truncated ...
  last N lines

full output saved at:
  /tmp/run-logs/build-2026-05-30.txt

另一种办法是丢掉旧消息,只保留当前任务、最近几轮对话和仍然有效的约束。

再往前一步,是让模型给历史写 handoff summary。context 到达阈值后,runtime 把前面的交互压成一段高密度摘要,再从摘要继续。

真实系统通常混用这些方法:裁剪工具输出,过滤历史,生成 summary,把状态写入文件,再按需 retrieval。判断标准只有一个:压缩以后,agent 还能不能把任务接着做对。

Codex 的两条 Compaction 路径

Codex 开源代码里能看到 local 和 remote 两条路径:

let _ = if crate::compact::should_use_remote_compact_task(ctx.provider.info()) {
    if ctx.features.enabled(codex_features::Feature::RemoteCompactionV2) {
        crate::compact_remote_v2::run_remote_compact_task(session.clone(), ctx).await
    } else {
        crate::compact_remote::run_remote_compact_task(session.clone(), ctx).await
    }
} else {
    crate::compact::run_compact_task(session.clone(), ctx, input).await
};

provider 支持 remote compact 就走服务端,否则在本地生成摘要。两条路径的区别不只是运行位置。

Local Compact:给下一轮写交接

Local compact 本质上是让当前模型给下一个模型写交接。

它先把 compaction prompt 追加到 history,再通过普通的 ModelClientSession::stream() 请求模型。如果输入超出 context window,就从最旧的 item 开始删除并重试。

模型返回的最后一条 assistant message 会成为 summary。runtime 给它加上 handoff prefix,再附上最近的真实 user messages,用这组内容替换原 history。

prompt 写得很直白:

You are performing a CONTEXT CHECKPOINT COMPACTION.
Create a handoff summary for another LLM that will resume the task.

summary 要记录进度、决定、约束、用户偏好、剩余步骤和关键引用。前缀则告诉下一轮模型:前一个模型已经做过一部分工作,不要从头再来。

这套方法简单,也确实能用。缺点同样直接:summary 是一段明文,质量取决于模型抓重点的能力。每压一次都会丢信息,多次压缩还会累积误差。所以 local compact 会提醒用户,长线程可能降低准确性。

Remote Compact:客户端只拿到 Opaque State

Remote V1 会把当前 history 和完整 prompt 发给 `POST /v1/responses/compact`。服务端返回一组 ResponseItem,其中包括 Compaction { encrypted_content }。

客户端会过滤过期的 developer message、原始工具输出、reasoning 和 web search,只留下真实 user message 与这段 encrypted content。

encrypted_content 值得注意。它不是给人读的 summary,客户端也不解析,只在下一次请求中继续携带。

所以从客户端能确认的只有一点:remote compact 返回的是一段 opaque state,不是普通文本摘要。里面究竟有什么,开源客户端无法告诉我们。

V2:Compaction 成了协议事件

Remote Compact V2 不再调用单独的 compact endpoint。它在普通 Responses 输入末尾加一个 trigger:

let mut input = prompt_input.clone();
input.push(ResponseItem::CompactionTrigger);

请求仍走正常 stream。服务端在流里返回 Compaction { encrypted_content }。

这个变化看起来像协议重构,实际边界变了。compaction 不再是 agent loop 外部的维护任务,而是 Responses 协议中的原生 item。模型请求、agent state 和 compaction 开始走同一条链路。

服务端到底保留了什么

公开信息不够,不能下结论。

它可能包含摘要、引用、索引、历史片段指针或工具状态,也可能和 Responses API 的 conversation state 绑定。但 opaque payload 本身不能证明其中有哪一种结构。

能确定的方向是:context 压缩已不只是客户端删 prompt。服务端开始持有恢复任务所需的状态。用户是否还需要看到 context 百分比,取决于这套恢复机制到底有多可靠。

Prompt 泄露说明 Runtime 比 Prompt 更重要

Kangwook Lee 曾用 prompt injection 尝试暴露 remote compact 的 prompt:相关文章。泄露内容据称和开源的 prompt.md、summary_prefix.md 很接近。

如果 local 和 remote 用的 prompt 相似,remote 的优势在哪里?

我认为差别在 runtime。Local compact 只能处理客户端提供的 history,产物也是一段明文。Remote compact 可以接触 Responses state、历史 item 和服务端协议。即使 prompt 相同,它能保存什么、下一轮怎样恢复,仍可能不同。

这只是基于架构的推断。encrypted state 没公开,就不该把推断写成事实。

Context Management 正在进入模型厂的 Harness

以前做 agent,我们很容易把 context compression 当成 provider-independent 的模块。OpenAI、Anthropic、Gemini 或 DeepSeek 都提供模型;harness 自己负责 pruning、summary 和 retrieval。

Remote compact 指向另一种分工。模型、工具 schema、reasoning item、compaction item 和 server-side state 可以由同一家一起设计。第三方 harness 仍能做压缩,但未必拿得到模型厂内部的状态管理能力。

这和 The Harness: The Moat for AI Model Providers? 的观点很接近:模型在某种 harness 里接受 post-training。它熟悉的工具格式、编辑协议、memory 方式和 compaction 边界都会影响最终行为。

因此,「只换模型」越来越不像换一个 API endpoint。你也在替换模型默认依赖的 runtime。

其他信号也在出现。Kimi 介绍 K2.6 时强调 agent swarm:发布推文。DeepSeek 也开始招聘 harness engineer:相关推文。单个消息答得多好,已经不足以定义 agent 产品。

真正决定完成率的,是整套运行环境:tool schema、sandbox、编辑协议、权限、event stream、memory、compaction、retrieval、sub-agent dispatch 和 verification loop。

我现在的判断

移除 indicator 对普通用户可能是好事。用户应该描述任务,在关键节点 review,而不是一直计算还剩多少 token。

但 agent 开发者不能因此忽略 context。恰恰相反,需要把状态分得更清楚:

  • 什么必须进入模型 context
  • 什么应该写进外部 memory
  • 什么由服务端保存
  • 什么可以压成 summary
  • 什么必须保留原文
  • 什么应该在需要时再 retrieval

聊天机器人也许用一段 summary 就够。Coding agent、long-running agent 和 multi-agent runtime 不够。它们需要的是 state management,不是一个更聪明的总结 prompt。

所以这个 UI 变化真正说明的是:context window 仍然存在,只是管理它的人正在从用户变成 harness。谁能让这个过程可靠,谁就更接近所谓的「无限 context」。