Steered follow-ups can cause Codex to lose unfinished task context, especially around compaction

Resolved 💬 2 comments Opened Jun 18, 2026 by suprise Closed Jun 18, 2026

What variant of Codex are you using?

CLI / App / app-server behavior around active-turn steering and compaction.

What issue are you seeing?

When a user sends a steer/follow-up message while Codex is still working on an earlier task, Codex can lose continuity with the original unfinished task. This is especially visible when compaction happens soon after the steer input: the compacted context may preserve the steered message but fail to preserve the task Codex was already executing.

This appears related to existing reports:

  • #9734: steer + compaction caused Codex to remember only the steered message and forget the previous task.
  • #24557: steer appears to be accepted while the model is thinking, but behavior looks like the original answer completes first and the steer becomes a separate follow-up.
  • #15842 / #13892: pending steer / queued follow-up state can get confusing or race with turn finalization.
  • #23405 / #22728 / #28341: recent fixes improved pending input ownership and responsiveness, but they do not appear to address the model-facing semantics of mid-turn user input.

The underlying problem seems to be that same-turn steer input is treated mostly as pending user input to be drained into the next model request. That preserves the user's raw message, but it does not clearly encode:

  1. this message arrived while the assistant was already working;
  2. the previous task may still be unfinished;
  3. the assistant should incorporate the new message without dropping the current task;
  4. compaction should retain both the active task and any absorbed/unhandled follow-up.

In other words, steer is currently a transport/runtime concept, but not clearly represented as a first-class "mid-turn follow-up" in the model-facing context or compaction summary.

Why this matters

Steer is most useful during long-running agent work, exactly when there is often an unfinished active task, tool state, subagent state, or pending validation. If a steer message becomes the only salient recent user message, the model may pivot to the new instruction and never resume the old task.

This makes steer risky for:

  • adding a missing constraint during a long task;
  • correcting direction without canceling the task;
  • asking a quick status question while work continues;
  • using steer near automatic compaction;
  • using /goal or subagents where the active work is long-lived.

Suggested direction

Consider upgrading steer from "append pending user input" to a more explicit queued follow-up mechanism:

  1. Store active-turn steer submissions as structured follow-up events with lifecycle state, for example queued, absorbed, deferred, handled.
  2. Absorb them only at safe boundaries, such as after a tool batch, before the next model request, or before a natural stop.
  3. When absorbed into model context, wrap the content with explicit semantics instead of inserting it as a bare user message.

For example:

<user_followup received_while_working="true">
...user's steer message...
</user_followup>

This message arrived while you were already working. Incorporate it without losing the unfinished task. If it changes priority, follow it; otherwise address it and then resume the prior task.
  1. Preserve active-task / follow-up state across compaction. A compacted summary should retain fields like:
active_task: ...
current_phase: ...
absorbed_followups:
- message: ...
  status: pending_handling | handled
deferred_followups:
- message: ...
resume_policy: address_followup_then_resume_unfinished_work
  1. Defer unsafe or structurally complex inputs to the next normal turn rather than consuming them mid-turn.

Prior art / comparison

Claude Code appears to handle concurrent user input as queued commands that later become wrapped user messages, with wording similar to "The user sent a new message while you were working..." and an explicit instruction to address it after the current task.

In another internal agent implementation I reviewed, queued user messages are absorbed at a tool-batch boundary and injected into the next LLM round as:

<user_followup>
...
</user_followup>

The important part is not the exact wrapper string. The important part is making the model-facing context distinguish:

  • original task input;
  • mid-turn follow-up;
  • queued next task;
  • deferred unsafe input;
  • unfinished active work that must be resumed.

Expected behavior

If a user steers while Codex is working:

  • corrections/cancellations should immediately affect the current task;
  • constraints should be incorporated into the current task;
  • unrelated follow-ups should be handled at the appropriate point without erasing the old task;
  • after handling a follow-up, Codex should resume unfinished work unless the follow-up explicitly superseded it;
  • automatic compaction should not summarize away the pre-steer active task.

Additional information

This is not a request to accept an external PR. I am opening this issue to share root-cause analysis and a high-level design direction, since the contribution guidelines ask for discussion and design feedback before any code.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗