The first mistake is to treat memory as a larger chat transcript. That would make every future request carry more old text and more ambiguity. Codex takes a different route. The official Memories documentation describes useful context from earlier threads, and the source splits the implementation into memories/read and memories/write: one path brings existing memory into the current thread, while the other turns historical rollouts into local material that future threads can consult.

The central model for this chapter is simple: Codex memory is a local recall layer. It extracts high-signal lessons from eligible rollouts, stores stage outputs in state, consolidates them into ~/.codex/memories/, and later exposes them through a read path with citations and pollution guards. It reduces repeated explanation, but it does not take over the jobs of rules files, replay ledgers, or an unlimited context window.

Reading contract. This chapter follows one lifecycle: which threads may generate memories, how the background writer extracts and consolidates them, how a future turn reads them, and where the boundary sits between AGENTS.md, rollout, Memories, and Chronicle. By the end, you should know where each durable fact belongs.

Evidence boundary. Product behavior comes from OpenAI's Codex Memories, AGENTS.md, and Chronicle docs. Feature gates, configuration, read/write pipelines, citations, and pollution handling come from public openai/codex source. This article does not inspect or cite any local ~/.codex/memories contents, and it does not infer private service behavior.

1. Separate the Surfaces That Feel Like Memory

Several Codex surfaces can make the product feel like it remembers. TurnContext, covered in Part II, is the current runtime snapshot. Rollout, covered in Part X, is durable execution evidence. AGENTS.md is instruction material loaded before work starts. Memories form a separate layer: reusable lessons extracted from previous work and consulted later when they are likely to help.

Surface Owner Lifetime Best fit
Current context TurnContext and model-visible view. One turn, projected and compacted as needed. Inputs, tool results, environment, and instructions the model must see now.
Project rules AGENTS.md / checked-in docs. Read when entering the repository. Rules, commands, permissions, and delivery requirements that must reliably apply.
Execution evidence Rollout / state DB. Written as a thread runs; reused for resume, fork, audit, and recovery. What happened, which tool output exists, and where recovery should restart.
Memories codex-memories-read / codex-memories-write. Generated in the background, stored locally, selectively read by future turns. Stable preferences, recurring workflows, project habits, known pitfalls, and high-leverage steps.
Chronicle Opt-in Codex app research preview. Uses recent screen context to help memory building. Clues about the tools, documents, dashboards, or workflows currently on screen.

Required rules should stay in rules files. Replay evidence should stay in rollout. Memory earns its place when it reduces repeated explanation in future work without pretending to be the only source of truth.

2. Feature Gates Come Before Memory Behavior

The official docs start with the important default: Memories are off by default. The source matches that contract. The feature spec for Feature::MemoryTool uses the key memories, marks it Experimental, and sets default_enabled to false. Configuration therefore has two layers: the feature flag decides whether the system exists, while the [memories] table decides generation, use, external-context handling, and model overrides.

[features]
memories = true

[memories]
generate_memories = true
use_memories = true
disable_on_external_context = true

The three memory-specific switches answer different questions. generate_memories controls whether newly created threads can become future memory inputs. use_memories controls whether existing memory instructions are injected into the current thread. disable_on_external_context can keep threads that used web search, tool search, or memory-polluting MCP servers out of memory generation. In the TUI, /memories follows the same split: if the feature is off, it prompts for enablement; once enabled, it exposes use/generate settings for the thread.

Switch Controls Source anchor
features.memories Whether Memories is enabled at all. Feature::MemoryTool, default off.
memories.generate_memories Whether a new thread may become a memory input. Thread creation writes a memory_mode.
memories.use_memories Whether an active thread can use existing memories. The read extension injects developer instructions only when enabled.
memories.disable_on_external_context Whether external context can mark a thread polluted. Web/tool search and MCP paths can set memory_mode = polluted.

3. Memory Writing Runs in the Background

Immediate summarization would be noisy. A thread may still be in progress, the user may correct the agent, and an error may be temporary rather than reusable. Codex moves memory writing to a background path. After turn/start successfully submits user input, app-server attempts to call start_memories_startup_task. That function exits early for ephemeral sessions, disabled feature flags, non-root agent sessions, or missing state DB.

Once running, the task creates the memories root, seeds extension instructions, prunes stale data, checks rate limits, and then runs Phase 1 followed by Phase 2. This is why the docs warn that memories may not update immediately after a thread ends. The writer is a maintenance path with idle windows, quota checks, and state DB leases, not a synchronous tail attached to every answer.

turn/start accepted
  -> start_memories_startup_task
  -> skip gates: ephemeral / feature off / sub-agent / no state DB
  -> create memories root
  -> prune
  -> rate-limit guard
  -> Phase 1 extraction
  -> Phase 2 consolidation

This placement is also why the memory chapter belongs after the rollout chapter. The write path selects from state-backed rollout records. Without the replay ledger, memory would look like a generic chat summarizer; with rollout in view, it becomes a later extraction layer over execution evidence.

3.1 How One Reusable Lesson Moves

Use a concrete lesson: when article flow changes in a bilingual repository, the matching language pages should be updated together and the mobile layout checked before shipping. If that lesson repeats, the writer does not paste the old conversation into future context. It moves the lesson through several shrinking shapes.

Stage Unit at that moment Owner and visibility Output
Candidate rollout Old user request, file diff, and validation results. The state DB selects by idle window, age, and memory mode. A job Phase 1 may claim.
Phase 1 A reusable lesson extracted from old evidence. The background writer reads the rollout as data. raw_memory, rollout_summary, and rollout_slug.
Phase 2 A workspace patch merged from several raw memories. An internal consolidation agent can only edit the memory workspace. memory_summary.md, MEMORY.md, summaries, or skills.
Future read A memory entry matched by the current task. The foreground agent opens a small number of files under the read-path prompt. A hidden citation records which memory was used.

4. Phase 1 Turns Rollout into Raw Memory

Phase 1 extracts structured memory from a bounded set of recent, idle, eligible rollouts. The state-layer claim query excludes threads whose memory_mode is not enabled, excludes the current thread, applies age and idle windows, and bounds startup work through scan and claim limits. This is not "summarize everything." It first narrows the candidate set.

The prompt template adds a second gate. If a rollout has no reusable insight, the memory writer may return all-empty fields. High-signal memories are stable user preferences, high-leverage procedures, task maps, decision triggers, and reliable environment facts. Routine status notes should not occupy future attention.

{
  "raw_memory": "When changing article flow in this repository, update matching zh/en pages and run a mobile visual check before shipping.",
  "rollout_summary": "A prior edit improved a Codex article only after the bilingual page and narrow mobile layout were checked together.",
  "rollout_slug": "bilingual-article-visual-check"
}

The important word is evidence-based. The Phase 1 prompt treats rollout text and tool output as data, not instructions. It forbids storing secrets, discourages large output copies, and prefers no-op when no future agent would plausibly act better because of the saved memory.

5. Phase 2 Consolidates a Local Memory Workspace

Phase 2 turns stage-1 outputs into the file-based memory workspace. The README describes a very concrete sequence: claim a global lock, select bounded stage-1 inputs by usage and recency, sync raw_memories.md and rollout_summaries/ into ~/.codex/memories/, maintain a git baseline for the workspace diff, and exit if nothing changed.

When the workspace does change, Codex spawns an internal consolidation agent. It runs with no approvals, no network, and local write access only; collaboration is disabled to prevent recursive delegation. That makes the boundary clear: consolidation is local state maintenance, not foreground project work.

File or directory Role Read behavior
memory_summary.md Dense navigational summary. Provided to the read path as the first quick signal.
MEMORY.md Searchable handbook. Grep by relevant keywords before opening deeper files.
rollout_summaries/ Compressed evidence and lessons per rollout. Open only a small number when MEMORY.md points there.
skills/ Reusable procedures or scripts. A deeper progressive-disclosure layer.
raw_memories.md Merged Phase 1 input. Primarily used by Phase 2 consolidation.

6. The Read Path Brings Memory Back into Future Turns

Reading is provided by an extension. MemoriesExtensionConfig is enabled only when Feature::MemoryTool is enabled and memories.use_memories is true. The thread context contributor then builds memory developer instructions and injects them as a developer-policy prompt fragment.

The read-path prompt does not tell the agent to open every memory file. It first asks whether the user query is likely to benefit from memory. If yes, it performs a quick memory pass: skim the provided memory_summary.md, search MEMORY.md, and only then open one or two pointed rollout summaries or skills. It is the same progressive-disclosure discipline this series has already seen in skills and context management.

future user query
  -> memory_summary.md hints
  -> grep MEMORY.md
  -> open 1-2 rollout_summaries or skills
  -> answer with hidden memory citation
  -> record usage for future selection

Memory citation closes the loop. When memory is used, the read-path prompt requires a hidden <oai-mem-citation> block at the end of the final reply. MemoryCitation stores citation entries and rollout ids. The streaming layer strips the hidden markup from visible output, parses the citation, and records usage for the underlying stage-1 outputs. The user sees a clean answer; the runtime learns which memories actually helped.

7. Why polluted Exists

The dangerous failure mode is not simply forgetting. It is remembering unstable material too confidently. If a thread depends on web search, tool search, or an MCP server that may pollute memory, that external context may be stale or only valid for the current task. Codex provides disable_on_external_context: when enabled, matching response items or MCP tool calls can mark the thread as polluted.

The Phase 1 state query only selects threads with memory_mode = 'enabled' and history_mode = 'legacy'. Once a thread is marked polluted, it no longer looks like a normal memory input. External context can still be useful for the current answer; it simply should not become long-term preference or workflow memory by default.

Compare it with the lesson above. "Keep matching language pages in sync" is a stable workflow candidate. "A web page showed the latest price as 19.99 dollars today" is a one-time external fact with a short shelf life. The first may enter memory; the second is better kept in the current turn with its source.

This boundary transfers well to any agent runtime: temporary external facts may answer the current task, but they should not automatically become durable preference memory. If they must be saved, require clearer source, freshness, and confirmation boundaries.

8. Put Durable Material Back in the Right Place

The memory system is easier to reason about once each durable material has an owner. Memories do not replace context management or AGENTS.md. They stand after rollout: old thread evidence is extracted into reusable lessons, consolidated into a local workspace, and selectively read by future turns.

Information Where it belongs Reason
Team requirements, delivery flow, mandatory validation. AGENTS.md or checked-in docs. Must load reliably; cannot depend on whether memory extraction hits.
What exactly happened in a thread. Rollout / state DB. Resume, fork, audit, and recovery need replayable evidence.
Recurring preferences, workflows, and known pitfalls. Memories. They reduce repeated explanation while remaining verifiable and replaceable.
What is currently visible on screen. Chronicle or explicit current-turn tool reads. Useful for locating context; not automatically suitable for durable memory.

That completes the long-state side of the Codex route. Part II asked what the model sees now. Part X asked how an old thread can be replayed. Part XII asks which old lessons deserve to travel into a new thread. They are connected, but their owners are different. Keeping those owners separate prevents memory from becoming an ever-growing prompt and prevents mandatory rules from being entrusted to probabilistic recall.

Sources