刚开始使用Codex时,很多任务其实非常顺。
你给它一个明确Bug:
登录接口返回500,帮我定位原因并修复。
Codex读取几个文件,找到问题,修改代码,跑测试。
整个过程可能非常干净。
但任务一旦变长,情况就开始发生变化。
第一次修改没有解决问题,于是继续调查。
接着读取更多文件。
又发现另一个模块可能相关。
再补充新的要求。
中途改变一次方案。
然后让它顺便处理另一个问题。
几十分钟以后,你可能会发现一个非常熟悉的现象:
Codex好像越来越“听不懂”最开始的要求了。
它开始:
重复读取已经看过的文件;
重新讨论已经确认过的问题;
把旧方案和新方案混在一起;
修改原本明确说过不要修改的模块;
忘记某个阶段已经完成;
甚至重新解决一个早就已经解决的问题。
这时候很容易得出一个结论:
是不是上下文太长以后,模型变笨了?
问题没有这么简单。
Codex本身已经具备面向长任务的上下文压缩、线程、项目、Goals等机制。OpenAI在长时任务实践中也明确指出,真正决定长任务能否保持连贯的,不只是一个“大Prompt”,而是模型所运行的整个Agent Loop;Codex还会通过Compaction压缩已有上下文,让任务能够跨越更长的执行周期。
但是:
能够保存更长的上下文,不等于上下文里的信息始终是正确、相关和有用的。
这就是长任务里另一个非常容易被忽略的问题:
Context Pollution——上下文污染。
这里的“上下文污染”不是OpenAI某个正式错误名称,而是一个很实用的工程描述:
Agent当前能够看到的信息越来越多,但真正与当前决策有关的信息比例越来越低。
最终导致的问题不是:
没有上下文。
而是:
上下文太杂。
一、上下文不是“记忆越多越好”,而是Agent当前的工作现场
很多人第一次理解Context,会把它想象成:
Agent的记忆。
于是自然产生一个逻辑:
记得越多 = 知道得越多 = 表现越好但工程Agent不是这样工作的。
对于一个具体任务来说,它真正需要的是:
当前目标 + 项目规则 + 相关代码 + 已经确认的事实 + 当前执行状态 + 下一步需要的信息而不是:
所有历史对话 + 所有读取过的文件 + 所有讨论过的方案 + 所有失败尝试 + 所有临时猜测 + 所有无关需求两者差别非常大。
可以把Agent上下文理解成开发者桌面。
刚开始:
桌面上只有:
Bug描述 Login.tsx auth.ts 测试结果非常容易工作。
随着任务继续:
Bug描述 Login.tsx auth.ts router.ts database.ts config.ts 20条Terminal输出 3个失败方案 2次需求变化 一些临时讨论 另一个Bug此时Agent拥有的信息更多了。
但真正的问题是:
Signal / Noise开始下降。
信息数量在增加,
有效信息比例却可能在下降。
所以真正影响Agent长任务稳定性的,并不只是:
Context Window有多大。
而是:
Context里到底装了什么。
二、第一种污染:把已经失效的结论一直留在任务里
这是长任务最典型的问题。
假设一开始我们认为:
登录失败可能是Token过期造成的。
于是Codex围绕Token进行了大量分析。
后来经过测试已经证明:
Token正常 真正问题在Cookie SameSite配置理论上,后续任务应该以新的事实为基础:
Token问题 → 已排除 Cookie配置 → 当前Root Cause但历史上下文中仍然保留着大量:
Token猜测 Token分析 Token修改方案 Token相关日志如果后续又出现一个类似错误,Agent仍然可能重新关注Token。
这就是:
Stale Context——过期上下文。
它最大的危险不是信息错误。
而是:
这个信息曾经是合理的。
因此比明显错误的信息更容易继续影响判断。
更好的方式
当一个关键假设被排除以后,不只是继续往下做。
应该明确更新任务状态:
已确认: Token正常,不再作为当前排查方向。 当前Root Cause: Cookie SameSite配置。 后续不要重新修改Token逻辑, 除非出现新的直接证据。这实际上是在做一件很重要的事情:
Context Garbage Collection。
不是删除历史,
而是明确告诉Agent:
哪些历史已经失效。
三、第二种污染:把“项目长期规则”和“当前任务要求”混在一起
例如一个项目长期存在以下规则:
统一使用pnpm 禁止直接修改生产数据库 修改后必须运行lint和test 公共API需要保持兼容这些属于:
Durable Context。
它们长期有效。
但今天这个任务可能还有:
只修改Login模块 暂时不要处理UI 不要升级React这些属于:
Task Context。
任务结束以后,这些限制可能就失效了。
如果所有信息全部放在一个巨大的Prompt里:
项目规范 + 当前需求 + 临时限制 + 测试要求 + 历史决策 + 个人说明时间长了以后,Agent越来越难区分:
哪些规则是永久的?
哪些只是这一次有效?
OpenAI目前推荐通过AGENTS.md向Codex提供项目级持久指导,并明确建议保持这类说明精简;OpenAI在自身Agent-first工程实践中也总结过一个非常重要的经验:给Codex的是“地图”,而不是一份上千页的说明书。
所以更合理的设计是分层。
Durable Context
放长期规则:
AGENTS.md 项目结构 测试命令 编码规范 禁止事项Task Context
放当前任务:
当前Bug 允许修改范围 完成标准 当前约束Runtime Context
只保留执行过程中产生的临时信息:
Terminal结果 当前失败 临时假设 中间Diff这三种信息的生命周期不同。
把它们混在一起,就是上下文污染的重要来源。
四、第三种污染:任务不断扩张,却始终留在同一个线程
这是Codex特别容易出现的问题。
开始时:
修登录Bug。
完成以后用户继续:
顺便检查一下注册流程。
然后:
再看看用户权限。
接着:
用户权限既然看了,把后台权限也优化一下。
最后:
顺便把TypeScript错误处理掉。
从人类角度看:
这些事情都属于同一个项目。
于是很自然地继续在同一个Thread里做。
但是从Agent任务结构来看:
它们实际上已经变成了:
Task A 登录Bug Task B 注册流程 Task C 用户权限 Task D 后台权限 Task E TypeScript修复而不是:
一个Task。
Codex App目前专门把Agent工作组织为项目下的独立线程,不同Agent可以在独立Thread中并行执行任务,用户再分别查看修改和Diff。
这种设计背后的一个重要思想就是:
Project可以共享,但Task不一定应该共享同一个对话历史。
所以一个非常实用的判断方法是:
如果任务目标没变
继续当前Thread。
例如:
修登录Bug ↓ 第一次失败 ↓ 继续调查 ↓ 验证合理。
如果目标已经变了
新开Thread。
例如:
登录Bug已经完成 ↓ 现在开始优化支付模块就没有必要继续背着前一个任务的大量历史。
这其实和程序设计里的:
Single Responsibility
非常像。
一个Thread最好也有一个相对明确的责任。
五、第四种污染:不断给Codex追加要求,却没有重新定义“Done”
这是一个更隐蔽的问题。
最初任务:
修复登录Bug。
Done定义很清楚:
登录恢复正常 + 相关测试通过中途用户增加:
顺便处理错误提示。
然后增加:
登录页面也整理一下。
接着:
再增加一个Loading状态。
于是最终任务已经变成:
Bug Fix + Error Handling + UI Cleanup + Loading State但Agent原来的Completion Criteria可能仍然围绕:
登录Bug是否修好。
此时容易出现两个极端。
第一种
Bug修好以后,Agent认为:
Done。
但用户觉得:
我后面说的东西还没有做。
第二种
Agent不断继续工作。
因为新的要求越来越多,
它找不到明确结束点。
所以长任务不仅需要维护:
Context。
还需要维护:
Goal。
OpenAI在2026年的Codex实践中已经提供Goals这一类持久目标机制,用于让一个线程跨多个回合持续围绕明确结果工作,并通过完成条件判断任务是否达到目标。
即使不用专门功能,也可以手工维护一个非常简单的状态:
当前目标: 修复登录流程。 完成标准: 1. 登录请求正常; 2. 错误提示正确; 3. Loading状态正确; 4. 相关测试通过。 不属于当前任务: 注册; 权限系统; UI整体重构。这样Agent每执行一段时间,都有一个:
North Star。
否则上下文越长,目标反而越容易模糊。
六、第五种污染:失败尝试越来越多,却没有沉淀成“结论”
这是长任务中非常常见的一幕。
Codex尝试:
方案A
失败。
然后尝试:
方案B
失败。
然后:
方案C
部分成功。
再尝试:
方案D
失败。
如果历史只是不断累计:
尝试A 日志A 尝试B 日志B 尝试C 日志C 尝试D 日志D那么Agent后面必须自己重新理解:
哪些已经证明无效?
哪些仍然可能有效?
这会浪费大量上下文。
更好的方式不是保留完整探索过程作为主要工作状态。
而是在阶段节点形成:
Decision Log。
例如:
已排除: 1. Token过期; 2. API路由错误; 3. 数据库用户不存在。 已确认: Cookie没有被浏览器保存。 当前方向: 检查SameSite与Secure设置。 不要重复: Token刷新逻辑。这样几十条历史消息,被压缩成了几个:
State Facts。
这也是为什么长任务真正重要的不是:
让Agent永远记住所有过程。
而是:
让Agent记住正确的状态。
七、第六种污染:一次性塞太多文件,以为这样最保险
很多开发者担心Codex“不知道项目背景”,于是开始疯狂补上下文:
README 架构文档 数据库Schema API文档 十几个源文件 测试文件 历史Issue PR说明想法是:
我把信息全部给你,你总不会理解错了吧?
结果往往相反。
因为当前任务可能只是:
修改订单按钮的Loading状态。
真正需要的信息也许只有:
OrderButton.tsx useOrder.ts 对应测试过量上下文的核心问题不是Context Window一定装不下。
而是:
Attention被稀释。
OpenAI在Agent-first工程实践中专门强调Context Management是复杂Agent任务的核心挑战之一,并总结出“给Agent地图,而不是巨型说明书”的做法;Codex的Skills设计也采用按需加载机制——先暴露技能名称和描述,只有当Agent判断需要时才加载完整SKILL.md,而不是把所有说明一次性塞进上下文。
这背后其实是同一个原则:
Just-in-Time Context。
需要什么,
什么时候再加载什么。
而不是:
Just-in-Case Context。
因为担心以后可能需要,
所以现在全部塞进去。
八、Compaction能解决上下文污染吗?
Codex现在会自动进行Context Compaction。
简单理解就是:
当上下文越来越长时,系统会压缩之前的历史,把关键状态保留下来,让Agent能够继续执行更长的任务。OpenAI明确把Server-side Compaction用于长时间Agent运行,帮助有限Context Window承载更长的任务历史。
这非常重要。
但Compaction并不意味着:
上下文管理已经不需要人管了。
因为Compaction主要解决的是:
历史越来越长 ↓ 怎样压缩 ↓ 继续工作而上下文污染解决的是:
当前信息很多 ↓ 哪些仍然有效 ↓ 哪些已经过时 ↓ 哪些根本不属于当前任务这是两个不同问题。
例如:
一个错误结论如果一直被当成重要信息,
即使被压缩以后,
它仍然可能继续存在于任务状态中。
所以:
Compaction解决容量问题,Context Management解决信息质量问题。
这也是长任务里非常重要的区别。
九、真正稳定的长任务,需要四层上下文
如果把前面的问题重新整理,我更建议把Codex上下文分成四层。
第一层:Durable Context
长期有效。
例如:
项目结构 编码规范 测试方式 架构边界 安全规则适合放:
AGENTS.md等项目级配置。
第二层:Task Context
当前任务有效。
例如:
当前Bug 任务范围 禁止修改项 完成标准任务结束以后可以丢弃。
第三层:Execution State
当前执行进度。
例如:
已经检查什么 已经排除什么 当前Root Cause 当前修改方案 测试结果这是长任务最需要维护的部分。
第四层:Evidence
用来证明任务完成。
例如:
最终Diff 测试结果 Build结果 未验证项 剩余风险最终形成:
Durable Context ↓ Task Context ↓ Execution State ↓ Evidence这比把所有东西放在一个大Prompt里稳定得多。
十、什么时候应该果断开一个新Thread?
一个非常现实的问题:
到底什么时候继续原来的Codex对话,什么时候应该开新任务?
我通常看五个信号。
1. Root Goal已经改变
从:
修登录Bug
变成:
重构权限系统
直接新开。
2. 当前任务已经Done
新的需求即使属于同一个项目,
也可以开新的Thread。
Codex App本身就是按项目组织多个独立Agent线程,以便在不同任务之间切换而不丢失各自上下文。
3. 历史里已经存在大量失效假设
如果你发现Codex频繁重新提到已经排除的问题,
与其继续补充:
我刚才不是说了吗……
不如重新建立一份干净Task Context。
4. 文件范围已经完全变化
前半段:
frontend。
后半段:
database migration。
本质上已经是另一个任务环境。
5. 你自己已经说不清当前线程到底在做什么
这是最好用的判断标准。
如果让你用一句话回答:
这个Thread当前唯一目标是什么?
你自己都需要想半天,
那么这个Thread通常已经太复杂了。
十一、一个更适合Codex长任务的Context Checkpoint
如果任务预计持续比较久,可以每完成一个阶段,就主动生成一次Checkpoint。
例如:
【Current Goal】 修复用户登录后Cookie没有持久化的问题。 【Confirmed Facts】 1. 登录API正常返回200; 2. Token生成正常; 3. 浏览器没有保存Cookie; 4. 问题与数据库无关。 【Changes】 修改 auth/cookie.ts。 【Verification】 unit test通过; Chrome本地测试通过。 【Remaining】 检查Safari兼容性。 【Do Not Revisit】 Token刷新逻辑; 用户数据库查询。这几十行内容的价值,可能比继续保留几万Token的探索历史更高。
因为它实际上完成了一次:
State Compression。
不是简单压缩文字。
而是把:
History变成:
State这是长任务稳定性的关键。
十二、上下文工程真正解决的不是“记忆”,而是决策质量
所以回到最开始的问题:
为什么Codex任务越做越乱?
很多时候并不是:
模型突然变差。
也不一定只是:
Context Window不够。
更常见的是:
过期信息没有淘汰 + 不同任务混在一个Thread + 长期规则与临时要求混合 + 失败尝试没有形成结论 + 目标不断变化 + 无关文件持续进入上下文最终Agent拥有大量信息,
却缺少一份清晰的:
Current State。
所以真正应该优化的不是:
怎么让Codex记住更多东西?
而是:
怎么让它在每一个决策节点,都看到当前真正重要的信息。
这也是为什么未来AI编程越来越值得关注的概念,不只是:
Prompt Engineering。
还包括:
Context Engineering。
Prompt解决的是:
这一刻你怎么跟Agent说。
Context Engineering解决的是:
Agent整个任务生命周期里,应该持续知道什么、忘掉什么、什么时候加载什么。
从Prompt Engineering到Context Engineering
把上一篇的执行问题和这一篇的上下文问题放在一起,其实可以看到Codex工程化正在形成一个更完整的结构:
Environment ↓ Permission ↓ Task ↓ Context ↓ Verification ↓ EvidenceEnvironment决定:
Agent在哪里工作。
Permission决定:
Agent能做什么。
Task决定:
Agent应该完成什么。
Context决定:
Agent当前基于哪些信息做判断。
Verification决定:
怎么检查结果。
Evidence决定:
怎么证明任务真正完成。
真正长期使用Codex以后,会发现模型本身反而只是这套系统中的一个组件。
模型越来越强以后,
开发者真正需要学习的是:
怎样给Agent建立一个稳定的工作环境和信息环境。
因为一个拥有巨大Context Window、能够运行几个小时的Agent,如果工作状态里一直混着过期结论、无关文件和不断变化的目标,
它只会:
更长时间地在错误上下文里工作。
而一个Context被持续整理、状态被不断更新、任务边界清楚的Agent,
即使面对复杂长任务,
也更容易保持:
目标一致、状态清楚、决策稳定。
这才是Codex从短任务走向Long-Horizon Agent之后,真正需要解决的问题。