Steered input can look like a standalone latest user request and drop unfinished task context

Open 💬 2 comments Opened Jun 23, 2026 by suprise
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What variant of Codex are you using?

CLI 0.139.0

What issue are you seeing?

When I send a steer message while Codex is already working, Codex can treat the steer as the new main task and lose track of the unfinished task it was previously executing.

Minimal example:

  1. User asks Codex to do task B:

``text
Inspect the repo, make the requested fix, run tests, and report the result.
``

  1. Codex starts task B and runs tools.
  1. Before task B finishes, user sends a steer message A:

``text
Also make sure the final answer is in Chinese.
``

  1. Codex sends the next model request after receiving the steer.

Observed result: Codex may continue with only A in mind, or answer A, but fail to resume the unfinished parts of B.

Expected result: Codex should incorporate A without losing B. If A does not replace B, Codex should continue or resume B after applying A.

Suspected cause

Same-turn steer input is accepted as active-turn pending input and later drained into the next model request as user input. That preserves the raw message, but the model-facing history is too close to:

user: task B
assistant/tool: work in progress
user: steer A

The last message looks like a standalone latest user request. It does not clearly say that A arrived while Codex was already working on B, or that B may still be unfinished.

Suggested direction

When drained steer input is added to the next model request, it should carry explicit mid-turn follow-up semantics instead of looking like a bare standalone user message.

One possible shape:

<user_followup>
The user sent this while Codex was already working:
A

Apply this follow-up without dropping the current unfinished task unless it explicitly replaces that task.
</user_followup>

This should preserve the current cache-friendly behavior of appending new input near the next model-request boundary, without rewriting earlier history.

Areas to investigate in the existing code:

  • active-turn steer input acceptance in Session::steer_input;
  • pending input ownership and drain behavior in InputQueue;
  • the path that records drained TurnInput::UserInput before the next model request;
  • pending-input / steer tests that can assert the next model request contains wrapped follow-up text exactly once.

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #28892

Powered by Codex Action

suprise · 1 month ago

A note on the duplicate warning: #28892 was my earlier, less focused report and has been closed. This issue is the narrower version focused on the active-turn steer path.

I looked through the current code path and the behavior appears to come from this flow:

  • Session::steer_input accepts same-turn steer input and appends it as TurnInput::UserInput.
  • The turn loop later drains pending input before the next model request.
  • Drained TurnInput::UserInput is recorded through the normal user-prompt path, so the next model request effectively sees:
user: original task
assistant/tool: work in progress
user: steered follow-up

The issue is not that the steered text is lost. It is preserved, but it has no model-visible indication that it arrived while the agent was already working, or that the previous task may still be unfinished.

A narrow fix could be:

  1. keep the user-visible steered message unchanged;
  2. when drained active-turn user input is added to model history, add explicit model-visible follow-up context;
  3. add a regression test in the pending-input / steer test suite asserting that the next model request contains the follow-up semantics exactly once.

This would avoid rewriting earlier history and should keep the existing cache-friendly append-at-boundary behavior.

Would the maintainers be open to an invited PR scoped to this regression test and model-visible follow-up marker?