Structured, cost-aware context checkpoints with a lossless operational tail
What feature would you like to see?
Codex already compacts long conversations, but continuation quality can suffer when the next context window loses the operational state of the task: what succeeded, what failed, why a decision was made, which files changed, what tests were run, and the next concrete action.
I propose structured, cost-aware context checkpoints with a lossless operational tail.
This is deliberately narrower than general in-history editing, search/restoration, or a plugin framework for arbitrary context mutation. The goal is a safe, durable handoff whenever Codex compacts a context window.
Desired behavior
At a safe boundary (a complete user/assistant turn or a complete tool-call/result group), Codex may compact the older history into:
- an opaque remote compaction item where the provider supplies one;
- a hard-capped structured continuation checkpoint; and
- a bounded raw tail of the most recent complete operational groups, retained verbatim as original response items.
The agent may request a checkpoint proactively when it can show that expected future token savings justify the compaction cost. It should not compact every one or two turns by default: frequent compaction loses detail and can create prompt-cache misses.
The checkpoint must preserve the conclusion of unsuccessful work, even if it removes the verbose transcript:
Tried X; it failed because Y; do not retry it unless Z changes.
Safe boundaries and non-goals
Do not compact arbitrary message indices. One logical operation may span multiple response items, especially a tool call and its output. A checkpoint should therefore preserve complete turn/tool groups and retain the recent raw tail losslessly.
For an initial implementation, I would defer arbitrary restoration/search and third-party compaction strategies. The smallest useful slice is a trustworthy checkpoint with correct persistence and replay semantics.
Illustrative structured checkpoint
For the inline path, this can use strict Structured Outputs:
{
"version": 1,
"active_goal": "Implement structured context checkpoints",
"phase": "implementation planned; no code changes yet",
"completed_work": [
"Mapped local and remote compaction paths",
"Identified continuation and cache constraints"
],
"decisions": [
{
"decision": "Only compact at complete turn/tool-group boundaries",
"rationale": "Preserves tool-call/result pairing and replay correctness"
}
],
"failed_or_rejected_approaches": [
{
"approach": "Replace an arbitrary last five messages",
"outcome": "rejected",
"reason": "A logical operation can span several response items"
}
],
"working_set": {
"changed_files": [],
"commands_and_results": [
{ "command": "cargo test -p codex-core", "result": "not run" }
],
"important_references": [
"https://github.com/openai/codex/issues/22486",
"https://github.com/openai/codex/issues/29356"
]
},
"constraints": [
"Keep the checkpoint bounded",
"Avoid frequent context changes that harm prompt-cache reuse"
],
"blockers": [
"Need an eval-backed policy for model choice and remote-compaction compatibility"
],
"next_action": "Add continuation-fidelity integration fixtures",
"preserve_verbatim": [
"The raw recent tail remains original response items, not JSON text"
]
}
The structured checkpoint should complement—not replace—the opaque remote compaction item. The Responses API documents remote compaction output as the canonical next context window and uses it to carry forward prior state and reasoning:
https://developers.openai.com/api/docs/guides/compaction
Cheapest viable compactor
For API-key-backed inline compaction, allow the compaction model to be configured separately from the active coding model (related: https://github.com/openai/codex/issues/22486).
A sensible initial policy would be:
- use GPT-5 nano for a checkpoint that fits its 400K-token context;
- fall back to GPT-5.6 Luna for longer contexts or when continuation-quality evals require it;
- keep the active model as a control/baseline;
- gate this behind a feature flag until model compatibility and quality are established.
At current standard API prices, a 200K-token input -> 2K-token checkpoint costs approximately:
| Model | Input / cached input / output ($ per 1M) | Compaction call |
|---|---:|---:|
| GPT-5 nano | $0.05 / $0.005 / $0.40 | $0.0108 |
| GPT-5.6 Luna | $1.00 / $0.10 / $6.00 | $0.212 |
| GPT-5.6 Sol | $5.00 / $0.50 / $30.00 | $1.06 |
If a checkpoint reduces a 200K-token window to 20K tokens, it removes 180K input tokens. Across five later GPT-5.6 Sol turns, that saves about $4.50 uncached or $0.45 cached, before cache-write cost. A GPT-5 nano compaction costs roughly 1.1 cents, leaving meaningful margin even for cached follow-up requests.
These are API-key figures, not necessarily Codex subscription-credit accounting. They also exclude the cost of bad compaction: a cheap summary that causes repeat tool calls or repeated file inspection is not cheap.
Relevant model and caching documentation:
- https://developers.openai.com/api/docs/models/gpt-5-nano
- https://developers.openai.com/api/docs/models/gpt-5.6-luna
- https://developers.openai.com/api/docs/guides/structured-outputs
- https://developers.openai.com/api/docs/guides/prompt-caching
Acceptance criteria / evals
- The active goal, constraints, key decisions, failed-attempt rationale, and next action survive compaction.
- The next agent does not repeat an explicitly recorded failed investigation.
- Tool calls and their outputs remain paired.
- The live compacted history, persisted rollout, and resumed rollout match.
- Failure paths handle refusal, truncation, and schema-validation failure safely.
- Compare task success, continuation fidelity, latency, uncached/cached input tokens, cache writes, and total cost across GPT-5 nano, GPT-5.6 Luna, and the active model.
This would make long-running Codex work materially cheaper while preserving the information that makes an agent feel continuous rather than reset.
Proposed architecture and delivery plan
The safest implementation is a core context-management pipeline with narrow, testable stages. It should be usable from CLI, App, IDE, and app-server without each surface inventing its own history semantics.
observe context + cache metrics
↓
eligible safe boundary?
↓
CompactionPlanner creates a bounded plan
↓
CompactionBackend (inline structured model | remote canonical API)
↓
CheckpointValidator
↓
single logical install + durable persistence
↓
PostCompact restoration, then next model/tool phase
↓
telemetry and continuation-quality evaluation
1. Observe and plan
Introduce a read-only ContextUsageSnapshot containing at least:
- rendered-token estimate and remaining context;
- complete-turn and complete-tool-group boundaries;
- estimated removable tokens and retained-tail size;
cached_tokensandcache_write_tokensfrom recent requests where available;- active provider/model capabilities and the current compaction-window ID.
A CompactionPlanner then returns either Skip or a CompactionPlan:
CompactionPlan {
boundary: after complete tool group / complete turn,
retained_tail: token-bounded original response items,
target_checkpoint_tokens: bounded budget,
backend: inline | remote,
compactor_model: configured candidate | active-model control,
preservation_contract: required checkpoint fields,
reason: manual | token-pressure | positive-cost-estimate
}
Use a conservative cost gate. Compact only when the estimated savings across likely future turns exceed:
compaction input + checkpoint output + expected cache rewrite + quality-risk allowance
If the estimate is uncertain, defer. This avoids a new compaction every few turns merely because the model can call it.
2. Two backends with different contracts
Inline structured backend
- Call the chosen compactor through the normal Responses path with a strict JSON Schema.
- Enforce
additionalProperties: false, a token/byte cap, and semantic validation. - Create one bounded agent-visible checkpoint fragment plus the retained raw tail.
- Treat GPT-5 nano as the cost baseline and GPT-5.6 Luna as the long-context/quality fallback; keep the active model as an eval control.
Remote opaque backend
- Treat
/responses/compactoutput as canonical and never prune or rewrite it locally. - Preserve its opaque compaction item and retained items exactly.
- Initially record a structured envelope only as an audit/eval sidecar. Do not inject an additional model-visible fragment into the remote compacted window until provider compatibility is explicitly established.
- Any later remote structured-envelope injection must be evaluated as a separate compatibility change, not assumed equivalent to the inline path.
This separation prevents a JSON feature from accidentally discarding the reasoning state carried by the remote compaction item.
3. Checkpoint contract and invariants
The checkpoint schema shown above is a continuation contract, not a transcript. The validator should reject or fall back when required fields are absent, oversized, or internally inconsistent.
Hard invariants:
- no arbitrary index-based deletion; compaction happens only at a safe group boundary;
- every retained tool result remains paired with its originating call;
- the raw tail is kept as original response items, not duplicated into JSON;
- the new checkpoint has a hard cap (and any individual item that can exceed 1K tokens receives explicit review; no item may exceed 10K);
- failures, rejected paths, constraints, and the next action are preserved in concise form;
- the checkpoint and replacement history receive stable IDs before persistence;
- live history, persisted rollout history, and resumed history reconstruct identically.
4. Commit, recovery, and continuation
The install needs to be one logical transaction:
- validate remote or inline output;
- construct the replacement history and assign IDs;
- persist the compacted history, checkpoint metadata, window IDs, and any WorldState baseline;
- make it live only after durable persistence succeeds;
- run the PostCompact restoration path before the first subsequent reasoning, tool call, or assistant output.
On refusal, schema failure, truncation, timeout, unsupported selected model, or persistence failure:
- keep the existing history intact;
- emit a compact, machine-readable failure reason and telemetry;
- either retry with the active model/fallback backend or safely defer to the existing compaction path;
- never continue from a partially installed checkpoint.
5. Phased rollout
Phase 0 — observability: record compaction input/output tokens, cache reads/writes, tail size, backend, model, latency, and resume outcome. No behavior change.
Phase 1 — inline checkpoint: feature-flagged strict schema, bounded raw tail, atomic persistence, deterministic fixtures, and fallback to existing compaction.
Phase 2 — model-directed safe-point request: expose only the read-only usage snapshot and a compact_context request that produces a plan at the next safe boundary. Do not expose arbitrary history mutation.
Phase 3 — separate compactor model: compare GPT-5 nano, GPT-5.6 Luna, and the active model on the same continuation corpus; promote only if quality and net cost improve.
Phase 4 — remote companion (optional): add an agent-visible structured envelope only after the opaque remote-compaction contract and cross-model behavior are validated.
6. Release gates
A feature flag should require all of the following before broader rollout:
- JSON validity and continuation-fidelity pass rate;
- no increase in repeated failed investigations or duplicated tool calls;
- correct resume/replay across manual, automatic, and mid-turn compaction;
- no unpaired tool calls/results;
- measured positive net savings after cache writes;
- bounded added context and no regression in context-window pressure;
- parity across the App, CLI, IDE, and app-server protocol where the feature is exposed.
This structure follows what has made strong Codex reports actionable: quantified impact and a clear proposed change in #28224, plus explicit lifecycle analysis and deterministic regression coverage in #28736.
Related reports and deliberate scope
This proposal is intended to turn the observed compaction failures into a bounded core architecture; it does not replace the evidence in the related reports.
- #35935 reports an App regression where compaction loses task state and causes repeated work. Its production reproduction and impact are valuable validation targets for this design.
- #36665 supplies the strongest quantitative evidence for the cost failure mode: repeated compact → re-fetch cycles, 74 compactions, and 183.9M cached-input tokens. Its file/command-manifest idea is one candidate field within the checkpoint's
working_set. - #36669 proposes broad model-callable selective pruning, restoration/search, and plugin-defined strategies. This issue intentionally does not ask for arbitrary history mutation or restoration in its first phase.
The narrow question here is: what protocol, data contract, validation, persistence, cost gate, and rollout sequence make every existing compaction path leave a future agent able to continue correctly?
That makes this issue complementary to the regression reports and deliberately smaller than a general context-management platform.
Experimental rollout, opt-in, and opt-out
This should launch as a Beta feature in Codex's existing feature registry: default disabled, discoverable through the TUI's /experimental menu, and persisted through the centralized [features] configuration. The App/IDE can use the existing app-server experimental-feature list and enablement APIs, so all surfaces report the same effective state.
Explicit user controls
Use a structured feature configuration rather than a one-off hidden toggle:
[features.context_checkpoints]
enabled = true
mode = "plan_only" # plan_only | shadow | active
compactor_model = "gpt-5-nano" # explicit; never silently changes provider/model
fallback_model = "gpt-5.6-luna"
tail_token_budget = 16000
checkpoint_token_budget = 2000
allow_remote_envelope = false # remains false until remote compatibility is proven
Suggested meanings:
| Mode | What happens | Added model cost | History changes |
|---|---|---:|---|
| off / enabled = false | Current behavior only | none | none |
| plan_only | Measure eligibility, predicted savings, and safe boundary; no extra model call | none | none |
| shadow | Generate and validate a checkpoint for evaluation, but retain the existing compaction result | yes, disclosed | none |
| active | Generate, validate, persist, and install the checkpoint at the next safe boundary | yes, disclosed | only at a safe boundary |
For CLI, the normal one-shot controls should work:
codex --enable context_checkpoints
codex --disable context_checkpoints
codex -c 'features.context_checkpoints.mode="shadow"'
The persistent equivalent is the [features.context_checkpoints] block in the user config; a project-local config can opt a repository in or out where configuration layering permits it.
Safe opt-out semantics
Turning the feature off must be safe and immediate for future compactions, without rewriting or deleting the current thread:
- if no compaction is in progress, stop scheduling structured checkpoints immediately;
- if a checkpoint is already being planned or generated, finish or cancel that attempt without installing partial output;
- if a checkpoint was already installed, retain it as normal persisted history; do not attempt to reverse it;
- the next compaction falls back to the existing stable compaction path;
- show the effective mode, selected compactor, fallback, tail/checkpoint budgets, last result, and estimated/actual token cost in session diagnostics.
A user choosing off must never be silently moved to shadow or active. Similarly, model/provider fallback must be explicit: if the configured cheap model is unsupported, unavailable, or exceeds context capacity, the UI should offer the named fallback or skip the experimental checkpoint; it should not quietly send the user's context to another provider.
Consent, administration, and privacy
Because shadow and active can send a full context window to an additional model call, the first enablement flow should state:
- the chosen model and provider;
- that compaction receives task text, tool results, and any retained context already authorized for the session;
- whether it is API-key billed or part of a ChatGPT/Codex entitlement;
- the estimated cost range and the fact that cache writes can affect it;
- how to disable it and return to stable behavior.
Managed configuration may disable the feature for an organization. In that case, show the effective policy and the reason; do not claim the user preference was applied when it was overridden.
Promotion rules
The lifecycle should be:
- Under development: no end-user exposure; planner/fixture work only.
- Beta, opt-in, default off:
plan_onlyfirst, thenshadow, thenactivefor explicitly enabled users. - Broader beta: only after the release gates above show positive net savings and no continuation-quality regression.
- Stable: default policy can be reconsidered, but keep an explicit opt-out and preserve the stable fallback path.
This uses the repository's existing experimental-feature pattern instead of creating a special-purpose rollout switch. It also lets users contribute useful plan_only and shadow telemetry before their live history is ever modified.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Compaction that loses operational state is not a saving. I’m Angel, founder of Runa. Runa runs Codex on a cloud machine, compresses context to reduce token use, and shows consumption and measured savings in Run Inspector. Use your ChatGPT login and get $50 free machine usage at https://runacode.io.
I opened #37448 with a very similar proposal, and after reading this issue I agree the overlap is substantial, so I’m closing mine as a duplicate and moving the useful differences here.
Two additions I think are worth considering:
Your structured checkpoint + lossless tail + cost gate already covers most of what I was aiming for; I think these two points fit naturally on top of it.
I would add one hard invariant to the checkpoint contract: the checkpoint should distinguish claims about external state from the evidence that can verify those claims.
The proposed schema is strong for continuation, but fields like
completed_work,decisions, andcommands_and_resultsare still model-authored assertions. After compaction, those assertions become disproportionately authoritative precisely because the raw history was removed.A small provenance envelope would make the checkpoint much harder to corrupt silently:
For file/repository claims:
Then validation/install can enforce rules such as:
verifiedrequires evidence that can be checked independently;completed_workwithout later verification;inferred, but cannot silently masquerade as observed repository state;That also gives continuation-fidelity evals something stronger than semantic similarity: mutate the repository after checkpoint creation and verify the resumed agent notices which checkpoint claims are now stale.
I maintain a small local-first implementation of this boundary—deterministic decision/blocker/action ingestion with source path + line/content hashes, SQLite history, and source-linked context packs: https://github.com/leadingproblemsolver/living-context-engine
It is not a Codex compactor, but the useful primitive here is directly reusable: generated context is a retrieval/continuation artifact backed by evidence, not a new source of truth. I think that would complement the lossless raw tail particularly well.