Skip to content

fix(codex): proactive context-pressure retire + handoff on app-server runtime (#36801) - #48485

Closed
ahmadalzaro1 wants to merge 1 commit into
NousResearch:mainfrom
ahmadalzaro1:fix/codex-proactive-compaction
Closed

fix(codex): proactive context-pressure retire + handoff on app-server runtime (#36801)#48485
ahmadalzaro1 wants to merge 1 commit into
NousResearch:mainfrom
ahmadalzaro1:fix/codex-proactive-compaction

Conversation

@ahmadalzaro1

Copy link
Copy Markdown
Contributor

Fixes #36801.

Problem

The Codex app-server runtime (run_codex_app_server_turn) hands each turn to a persistent codex app-server subprocess that owns its own conversation thread. Unlike the chat-completions path — which runs a preflight compaction check in build_turn_context() before every model call — the codex path had no proactive compaction. Sessions grow unbounded inside the subprocess until codex hits its hard context ceiling and silently hard-resets, losing all context. The failure is silent: the operator only notices after context is already gone (and on metered Codex seats the retained context is also a per-turn budget burn).

Compressing Hermes' messages list (the naive fix) does not help — codex holds the real history internally; run_turn() only forwards the new user message. The only lever is to retire the thread and reseed a fresh one.

Fix

A proactive, post-turn guard on the codex path:

  1. After _record_codex_app_server_usage() — where the real prompt-token count and codex-reported model_context_window are both known — compute prompt_tokens / context_window.
  2. When it reaches compression.codex_retire_threshold (new config, default 0.85, 0 disables), build a structured handoff summary from Hermes' projected messages via the auxiliary summary model (not codex — so the summarization itself can't overflow the already-full window), then retire the codex thread (close() + drop) and stash the summary.
  3. On the next turn, the respawned (blank) codex thread is reseeded by prepending the summary to the first user input — so Goal/Discoveries/Files survive instead of a cold history=0 reset.

This implements the flow proposed in the issue (extract usage → proactive threshold → handoff-on-retire) plus the structured-summary handoff suggested in the thread.

Notes

  • Opt-out / tunable via compression.codex_retire_threshold (0 disables).
  • Reuses existing summary machinery via a small public ContextCompressor.build_handoff_summary() seam.
  • Best-effort: if summarization is unavailable it still retires (announced via logger.warning) rather than ride an over-full window into a hard reset.
  • No behavior change on the chat-completions path, or when the codex window/usage is unknown.

Tests

New tests/agent/transports/test_codex_proactive_compaction.py (10 cases): over/under threshold, summary-less retire, disabled (flag + threshold=0), unknown window, already-retired session, and the build_handoff_summary seam (empty / delegate / error-swallow). All pass; existing test_context_compressor.py + test_codex_app_server_session.py (154 tests) remain green.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openai OpenAI / Codex Responses API codex P2 Medium — degraded but workaround exists labels Jun 18, 2026
@ahmadalzaro1
ahmadalzaro1 force-pushed the fix/codex-proactive-compaction branch from e5a7dc6 to 1bac1f3 Compare June 18, 2026 15:30
… runtime

The Codex app-server runtime hands each turn to a persistent subprocess that
owns its own conversation thread; unlike the chat-completions path it had no
proactive compaction, so sessions grew unbounded until codex hard-reset and
silently lost context.

Add a post-turn guard: when a turn's prompt tokens reach
compression.codex_retire_threshold (new, default 0.85) of the codex-reported
context window, summarize Hermes' projection via the auxiliary summary model,
retire the codex thread, and reseed the respawned thread with the summary on
the next turn — so Goal/Discoveries/Files survive instead of a cold history=0
reset. Threshold 0 disables.

Fixes NousResearch#36801.
@ahmadalzaro1
ahmadalzaro1 force-pushed the fix/codex-proactive-compaction branch from 1bac1f3 to 08c05df Compare June 22, 2026 08:07
@ahmadalzaro1

Copy link
Copy Markdown
Contributor Author

Ready for review. This is rebased onto current main (5ff11a689) and conflict-free.

The codex app-server path still has no proactive compaction, so long sessions keep growing until codex hits its hard ceiling and silently resets (#36801). This adds a post-turn guard: when prompt tokens reach compression.codex_retire_threshold (new config, default 0.85, 0 disables), it summarizes via the auxiliary model, retires the codex thread, and reseeds the next turn with the summary instead of a cold history=0 reset.

10 new unit tests; existing test_context_compressor.py + test_codex_app_server_session.py remain green. Happy to adjust the default threshold or split this down if that's easier to review.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused investigation and tests. This is now superseded by the Codex-native compaction implementation on current main.

This is an automated hermes-sweeper review.

@teknium1 teknium1 closed this Jul 14, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists provider/openai OpenAI / Codex Responses API sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex app-server runtime: long sessions grow unbounded → hard context reset (no proactive compaction)

3 participants