codex - 💡(How to fix) Fix /goal: chat "stop" message causes silent token burn until usage limit (autonomous tick ignores LLM-level self-restraint)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When a goal is in Active state and the user sends a chat message instructing the agent to stop (e.g. "STOP", "pause your work", "do not continue"), the LLM enters a reactive self-restraint mode and emits a "Paused. No action taken..." reply on each autonomous continuation turn. However, the goal's ThreadGoalStatus remains Active, so maybe_continue_goal_if_idle_runtime keeps scheduling continuation turns. Each turn invokes the LLM, and the per-turn output (including the "Paused" message) consumes tokens. Token usage climbs steadily until the 5-hour / weekly usage limit is hit, at which point the goal transitions to UsageLimited.

User-visible: the goal appears paused (model says so on every turn) but tokens continue to burn until quota exhaustion.

Root Cause

A common usage pattern: long-running goal, user wants to redirect midway, types wait or stop in chat. They reasonably expect the goal to halt. Instead it appears halted but silently drains quota — sometimes hours of token budget gone with no observable work happening.

The "Paused. No action taken" message itself, repeated over hundreds of turns, is the smoking gun: the wording varies between turns, confirming each is a fresh LLM call producing identical-meaning output, with full per-turn token cost.

RAW_BUFFERClick to expand / collapse

Summary

When a goal is in Active state and the user sends a chat message instructing the agent to stop (e.g. "STOP", "pause your work", "do not continue"), the LLM enters a reactive self-restraint mode and emits a "Paused. No action taken..." reply on each autonomous continuation turn. However, the goal's ThreadGoalStatus remains Active, so maybe_continue_goal_if_idle_runtime keeps scheduling continuation turns. Each turn invokes the LLM, and the per-turn output (including the "Paused" message) consumes tokens. Token usage climbs steadily until the 5-hour / weekly usage limit is hit, at which point the goal transitions to UsageLimited.

User-visible: the goal appears paused (model says so on every turn) but tokens continue to burn until quota exhaustion.

Repro

  1. Start a goal: /goal start <multi-step objective> (any objective that requires >30 minutes of continuations).
  2. After at least one continuation turn fires, send a chat message such as: STOP. Do not continue this goal until I explicitly resume it.
  3. Observe the model's reply: Paused. No action taken. The prior STOP still controls; automatic goal continuation is not an explicit restart. (Wording varies per turn — confirming each tick is a fresh LLM call, not a CLI hardcoded line.)
  4. Wait. Subsequent autonomous continuation turns produce the same "Paused" reply repeatedly.
  5. Eventually: Goal hit usage limits (/goal resume). Tokens used + elapsed time reflect the goal kept ticking at full frequency the entire interval.

Expected

Any of:

  • (a) LLM self-restraint should pair with a runtime back-off — after N consecutive turns producing no tool calls and no objective progress, exponentially extend the continuation poll interval (e.g. 1 min → 10 min → 1 hour) until the next user message.
  • (b) The model should be encouraged via system prompt to call update_goal(status="blocked") when it self-restrains in response to a stop instruction, so the runtime stops scheduling continuations.
  • (c) Add a request_pause tool action so the LLM can cooperatively halt the runtime when it chooses to self-restrain, without having to misuse complete / blocked.

Actual

The autonomous tick (maybe_continue_goal_if_idle_runtime in codex-rs/core/src/goals.rs:1289) only checks ThreadGoalStatus::Active (lines 1311–1319 of the same file) before scheduling another continuation. The LLM has no way to set status to Paused via tool call — update_goal's status enum only accepts complete and blocked (codex-rs/core/src/tools/handlers/goal_spec.rs:65). The user-facing /goal pause TUI command (codex-rs/tui/src/chatwidget/goal_menu.rs) is the only path to set Paused.

Users who instruct the agent via chat (rather than slash commands) therefore have no way to actually pause a goal. The LLM's reactive self-restraint silently burns the full remaining quota.

Why this matters

A common usage pattern: long-running goal, user wants to redirect midway, types wait or stop in chat. They reasonably expect the goal to halt. Instead it appears halted but silently drains quota — sometimes hours of token budget gone with no observable work happening.

The "Paused. No action taken" message itself, repeated over hundreds of turns, is the smoking gun: the wording varies between turns, confirming each is a fresh LLM call producing identical-meaning output, with full per-turn token cost.

Notes

  • Tested on Codex CLI built from a recent clone of openai/codex main.
  • Plan: Pro Lite. Both 5-hour and weekly limits affected.
  • This is not the /goal pause command path — that one works correctly and does halt the tick.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix /goal: chat "stop" message causes silent token burn until usage limit (autonomous tick ignores LLM-level self-restraint)