一条经验从历史任务想要进入长期记忆,要经过两次判断。第一次面向单个任务,从任务运行记录中找出可能有用的候选内容;第二次把新的候选内容与已有记忆合并、去重和更新。Codex 在源码中把这两个阶段称为 Phase 1 和 Phase 2。
记忆生成流程什么时候启动
当用户在 Codex 中发起新一轮任务时,系统会异步尝试启动记忆生成流程。后台处理不会阻塞当前回答,用户正在进行的任务可以继续执行。
流程启动后,程序会先检查记忆功能是否开启、当前任务是否为临时任务或子 Agent 任务、状态数据库是否可用,以及当前调用额度是否允许继续。条件不满足时,本轮后台处理直接结束。
Phase 1:把一个历史任务变成候选记录
每个 Codex 任务(thread)都有一份任务运行记录(rollout)。它按事件保存用户消息、Agent 回复、工具调用、工具输出和任务中的其他交互。它是任务实际发生过程的记录。
发送给提取模型之前,程序会先整理这份记录。用户消息、Agent 回复、工具调用、工具输出和 Agent 间协作会作为任务证据保留;开发者消息、模型内部推理,以及 AGENTS.md 和技能说明等运行时上下文会被过滤,避免把 Codex 自己的运行规则当成用户经验。
整理后的任务记录会交给提取模型。Phase 1 是一次结构化模型调用,它不修改长期记忆文件,只为当前来源任务生成一条候选记忆记录。
| 记录内容 | 源码字段 | 作用 |
|---|---|---|
| 候选经验 | raw_memory | 提炼可能跨任务复用的经验 |
| 任务摘要 | rollout_summary | 保留理解候选经验所需的背景和证据 |
| 文件名标识 | rollout_slug | 用于生成任务摘要的文件名 |
raw_memory 和 rollout_summary 会在一次有效的 Phase 1 输出中成对产生,但两者承担的职责不同。候选经验面向后续复用,任务摘要则保留理解这些经验所需的背景、过程和证据。rollout_slug 不保存记忆内容,只用于为任务摘要生成便于识别的文件名。提取模型判断当前任务没有值得沉淀的内容时,三个字段都会返回空值,Codex 将本次任务标记为「提取成功但没有输出」,不保存候选记录。
候选记录如何进入 Phase 2
Phase 1 可以同时整理多个历史任务,Phase 2 却需要从全局视角统一维护记忆。系统因此要先记下每个任务产生的候选记录和处理进度,再交给 Phase 2 集中读取。
Codex 把这层中间状态保存在原有的状态数据库中。后台流程由此知道哪些任务已经处理、哪些仍在等待或需要重试,也能避免重复处理同一个任务。Phase 1 可以并行提取候选记录,Phase 2 则保证同一时间只有一个整合流程修改全局记忆。
Phase 2:整合长期记忆
Phase 2 从中间状态中选取一批候选记录,再把它们与已有长期记忆一起交给内部整合 Agent。这个 Agent 从整个记忆库的视角判断哪些内容应该新增、合并、更新或清理,最终刷新记忆目录。
memories/
├── memory_summary.md
├── MEMORY.md
├── rollout_summaries/
└── skills/
memory_summary.md 和 MEMORY.md 保存经过整合的长期结论。前者为后续任务提供快速入口,后者记录更具体的经验和证据索引。rollout_summaries/ 保留来源任务的背景,供 Agent 需要时回查;其中出现的信息并不会自动成为未来任务的默认事实。skills/ 只在候选经验中出现值得复用的操作流程时生成。
两个阶段,解决两种不同的问题
Phase 1 负责从单个任务中找出可能有用的经验,Phase 2 负责判断这些候选经验放到整个记忆库中是否仍然成立。历史任务经过这两次判断,才可能成为后续任务可以使用的长期记忆。