openai / openai/codex

Code Mode dispatch worker stops at sampling end while yielded cells still need subsequent tools

Open
#45,945 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI tool-calls
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of Codex CLI is running?

Installed upstream CLI: 0.154.0. Source inspection below is pinned to upstream main 4701aa4b4239c70063ab6f2fcb835324f9c109f4. The end-to-end fix validation was on a local fork; this is not a claim of a fresh stock-0.154.0 runtime reproduction.

What subscription do you have?

ChatGPT Pro

Which model were you using?

The proposed failure mechanism is in the tool dispatch lifecycle, rather than a specific model's output. Model for a fresh upstream reproduction: not yet recorded.

What platform is your computer?

Linux 7.0.0-31-generic x86_64 unknown

What terminal emulator and version are you using (if applicable)?

Not recorded.

Codex doctor report

Not collected for this source-level report.

What issue are you seeing?

A yielded Code Mode cell may remain alive after the assistant ends its turn, but subsequent nested tool calls cannot be dispatched while the thread is idle. The first already-dispatched tool can finish; the next awaited tool then waits for a receive worker from a later sampling request.

This is separate from automatically waking the model: even without any completion wake, the Cell's JavaScript should be able to finish sequential non-interactive tools while idle.

What steps can reproduce the bug?

Suggested minimal reproduction (stock-current-version runtime confirmation still pending):

  1. In interactive CLI with Code Mode available, ask for one Cell containing the following JavaScript.
  2. Have the assistant finish its turn after the Cell yields. Do not call wait or send another user message during the sleeps. Ensure each command is permitted without additional approval.
  3. Observe whether the second command starts after the first returns, without another sampling request.
// @exec: {"yield_time_ms": 1000, "max_output_tokens": 1000}
const first = await tools.exec_command({
  cmd: "sleep 8", yield_time_ms: 10000, max_output_tokens: 100
});
text({step: 1, result: first});
const second = await tools.exec_command({
  cmd: "sleep 8", yield_time_ms: 10000, max_output_tokens: 100
});
text({step: 2, result: second});

The outer Cell yields after one second, but each inner tool has time to finish before its own yield. A deterministic regression should gate the first tool result until after the parent reaches idle, then assert that the second tool dispatches before any further model request. Our local fork has such an HTTP MCP regression, in addition to a manual two-sleep success test on the patched binary.

What is the expected behavior?

Ordinary nested tools requiring no new approval should continue until the live Cell completes, without keeping the model busy. This does not ask for idle approval UI, unlimited tool timeouts, or an automatic model continuation.

Additional information

Source inspection at the pinned upstream commit:

These lifetimes explain the observed boundary in our investigation; the suggested stock repro above has not yet been rerun in this reporting session.

A possible approach is to retain the existing dispatch worker while unfinished Cells exist, releasing it on completion/teardown and respecting existing sampling-boundary replacement. Approval provenance and cancellation need explicit handling; retaining the worker alone exposes previously unreachable idle prompt paths.

Reference experiment: fork commit af1f26f725. This sits on top of separate completion-wake changes and is not an independent upstream-ready patch or a PR request.

Related, but distinct:

  • #34122 concerns lost Cell handles across native goal continuations.
  • #40041 concerns visibility/order of nested command activity.
  • #38495 concerns Cell completion push and polling cost.
  • #32188 concerns waking on background command completion.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the sampling worker in codex-rs/core/src/session/turn.rs and the receive and drop paths in codex-rs/core/src/tools/code_mode/delegate.rs. Run the suggested two-sleep Code Mode reproduction, then add or run a deterministic regression that gates the first result after the parent becomes idle. Done means sequential non-interactive nested tools dispatch through Cell completion without another sampling request.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.