Skip to content

/review consumed 15M+ input tokens in a few minutes on Codex #2519

Closed

Description

@dgrcode

I hit extremely high Codex usage while running gstack /review on a ~422-line diff.

I inspected the persisted Codex token_count events and can account for at least 15.2M input tokens from this single review:

Thread Input tokens
/review parent 11.74M
5 spawned review agents 2.83M
nested codex exec 0.62M
Observed total 15.19M+

This accumulated very quickly. In the parent thread:

16:28:28   6,191,588 input tokens
16:33:58  10,490,863 input tokens

That's 4.3M input tokens in 5m30s (~782k/min), with one shorter interval reaching roughly 1M input tokens/minute.

The parent repeatedly made calls with ~170k–235k input tokens, mostly cached. It also spawned:

testing_review
maintainability_review
security_api_review
design_review
adversarial_review

and, while already running under Codex, invoked Codex again via:

codex exec ...
codex exec resume ...
codex review ...

One of those nested reviews was eventually detected by the parent itself as a:

runaway nested Codex review process that is consuming tokens

and terminated.

I also noticed the parent reading large overlapping portions of review/SKILL.md more than once during the run.

Parent thread:

019fe744-086c-7882-bf60-7a2cbad58146

I can provide the parent rollout, token-counter export, five child rollouts, and nested Codex rollout if useful.

It looks like /review may be repeatedly reprocessing a very large parent context while also spawning subagents and nested Codex reviews. Is this expected behavior when gstack is running under Codex?

More context for the agent

Context

I observed unexpectedly high Codex usage while running gstack's /review on August 9, 2026.

The review was for a relatively modest code change (~422 changed lines), but Codex usage dropped extremely quickly. I inspected Codex's local session data afterward to understand where the tokens went.

The main Codex thread was:

019fe744-086c-7882-bf60-7a2cbad58146

Its rollout is:

~/.codex/sessions/2026/08/09/rollout-2026-08-09T17-03-43-019fe744-086c-7882-bf60-7a2cbad58146.jsonl

The timestamps inside the rollout are UTC (Z).


Parent thread usage

The final persisted token_count for the parent reports:

{
  "input_tokens": 11742801,
  "cached_input_tokens": 11389184,
  "cache_write_input_tokens": 0
}

So the /review parent alone processed:

  • 11,742,801 input tokens
  • 11,389,184 cached input tokens

Almost all of the input was cached, but Codex's persisted total_token_usage.input_tokens continued increasing on each model call.


How quickly the usage accumulated

This wasn't accumulated over hours.

The parent's persisted counters show:

16:28:28  6,191,588 total input tokens
16:33:58 10,490,863 total input tokens

That's:

4,299,275 input tokens in 5m30s
≈ 782k input tokens/minute

A shorter interval:

16:31:08  7,655,369
16:33:58 10,490,863

is:

2,835,494 input tokens in 2m50s
≈ 1.0M input tokens/minute

Individual model calls during this period became very large:

input      cached input
168,319    167,680
175,709    168,704
178,081    174,848
180,804    177,920
181,520    179,968
182,402    182,016
194,426    182,016
194,806    194,304
206,348    194,304
218,035    205,568
218,546    217,856
230,244    217,856
231,471    229,120
231,602    231,168
232,938    231,168
233,326    232,192
233,877    233,216
235,354    233,216

This looks like the parent context grew to >200k tokens and then continued making many model calls while carrying most of that context forward.

That is an observation from the token counters, not yet a claim about what gstack should or should not be doing.


Spawned review agents

The parent made five spawn_agent calls:

testing_review
maintainability_review
security_api_review
design_review
adversarial_review

The corresponding child threads found in Codex's thread_spawn_edges table were:

019fe749-4872-7790-80bb-bf225da2f59b
019fe749-6b4f-7c03-9fb5-74294310e346
019fe749-8423-7190-8507-ff9be0e19070
019fe755-fa73-7151-bb02-9b97a1faf434
019fe756-1e93-7cf3-9d92-aaa08ecb04b1

The task → thread mapping below is inferred from spawn order / UUID timestamps:

testing_review
  019fe749-4872-7790-80bb-bf225da2f59b
  input: 250,378
  cached: 200,192

maintainability_review
  019fe749-6b4f-7c03-9fb5-74294310e346
  input: 330,165
  cached: 242,688

security_api_review
  019fe749-8423-7190-8507-ff9be0e19070
  input: 406,393
  cached: 355,328

design_review
  019fe755-fa73-7151-bb02-9b97a1faf434
  input: 515,028
  cached: 455,936

adversarial_review
  019fe756-1e93-7cf3-9d92-aaa08ecb04b1
  input: 1,326,464
  cached: 1,223,936

Together:

2,828,428 input tokens

This is important because the five spawned agents do not explain the parent's 11.74M input-token count. Their rollouts have their own counters.


Nested Codex invocation

The /review parent was itself already running in Codex, but it also executed Codex from inside the session.

One command was essentially:

codex exec \
  'Review the repository changes since commit 045bb8e. ...' \
  -C /Users/daniel/projects/macos/Recadio \
  -s read-only \
  -c 'model_reasoning_effort="high"' \
  --enable web_search_cached

It later resumed that nested session:

codex exec resume \
  019fe75c-4b6f-78e2-bc66-eec14fac12f5 \
  'Return only the final findings from your review ...'

That nested Codex session has its own rollout:

~/.codex/sessions/2026/08/09/rollout-2026-08-09T17-30-13-019fe75c-4b6f-78e2-bc66-eec14fac12f5.jsonl

Its final counter is:

{
  "input_tokens": 620864,
  "cached_input_tokens": 535808,
  "cache_write_input_tokens": 0,
  "output_tokens": 11035,
  "reasoning_output_tokens": 8093,
  "total_tokens": 631899
}

Later, the parent launched another nested command:

codex review \
  'Review only git diff 045bb8e..HEAD. Do not inspect skill files. ...' \
  -c 'model_reasoning_effort="high"' \
  --enable web_search_cached

The parent subsequently attempted to interrupt it several times with write_stdin(... "\u0003" ...), inspected running Codex processes, and eventually sent SIGTERM to one nested Codex process.

The parent-generated command justification described it as:

"the runaway nested Codex review process that is consuming tokens"

Important: that phrase is generated by the parent agent itself; it is not evidence of an independent Codex mechanism detecting a runaway process.

I have not yet identified/added the separate token total for this second nested codex review, so the total below is a lower bound.


Minimum observed token usage

Known persisted input-token totals:

/review parent              11,742,801
five spawn_agent children    2,828,428
nested codex exec              620,864
                            ----------
minimum observed total      15,192,093

So there are at least 15.19M input tokens directly visible in known rollouts associated with this one review.

This is not necessarily equivalent 1:1 to ChatGPT subscription quota consumption. It is the sum of Codex's persisted input_tokens counters for the identified sessions.

There may also be accounting/duplication semantics around forks that should be verified before treating this number as a billing total.


Parent activity

The parent rollout contains:

75 custom_tool_call -> exec
19 function_call
  - 5 spawn_agent
  - 14 wait

One thing visible in the transcript is repeated loading of gstack's review instructions.

It initially reads review/SKILL.md in chunks approximately covering:

1-240
241-520
521-1040
1041-1560
1561-2080

Later it reads large overlapping portions again:

1-760

1-500
501-1000
1001-1500
1501-1900

The parent also loads:

review/checklist.md
review/greptile-triage.md
review/design-checklist.md
review/specialists/testing.md
review/specialists/maintainability.md
review/specialists/security.md
review/specialists/performance.md
review/specialists/api-contract.md

and substantial amounts of repository code/diffs.

For example, before the parent reaches ~125k input tokens it has already:

  • read large parts of the gstack skill;
  • inspected multiple parts of the git diff;
  • read substantial portions of several Swift files;
  • loaded review specialist definitions.

Afterward it continues running tests, builds, repository inspections, review agents and nested Codex reviews while its per-call context grows toward ~235k.

This repeated skill loading might be relevant, but it should be verified whether it is expected behavior before treating it as the root cause.


Example of context growth

Some chronological parent model calls:

16:04:14   20,539 input
16:04:21   24,077
16:04:26   29,045
16:04:30   37,425
16:04:39   43,484

16:06:01   49,804
16:06:19   53,083
16:06:39   65,954
16:06:58   69,015
16:07:06   80,235
16:07:17   90,927
16:07:23   91,749
16:07:27   96,721
16:07:46  100,241
16:08:18  106,301
16:08:40  116,529
16:09:14  124,685
16:09:51  130,225
16:10:30  144,471
16:10:59  148,538
16:11:46  164,573

16:21:30  167,029
16:23:19  168,319
16:23:49  168,995
16:24:18  175,709
16:28:40  178,081
16:28:50  180,804
16:29:09  181,729
16:30:29  182,402
16:31:08  194,426
16:31:56  206,348
16:32:32  218,035
16:32:49  218,546
16:33:26  230,244
16:33:30  231,471
16:33:38  231,602
16:33:48  232,938
16:33:54  233,326
16:35:40  233,877
16:41:09  235,354

Most of the later calls are almost entirely cached input.

This repeated processing of a ~170k–235k context appears to be where a large fraction of the parent's 11.74M input total comes from.


Relevant chronology

Approximate sequence:

16:03   /review parent starts

16:04-16:07
        large parts of gstack review/SKILL.md loaded

16:07-16:09
        diff/repository inspection
        specialist/checklist instructions loaded

16:09:27
        testing_review spawned

16:09:36
        maintainability_review spawned

16:09:42
        security_api_review spawned

16:10+
        builds/tests/repository inspection continue

16:23:19
        design_review spawned

16:23:28
        adversarial_review spawned

16:24+
        additional review/repository commands

16:29:09
        nested `codex exec` started

16:30:58
        nested `codex exec resume` used

16:32:40
        another nested `codex review` started

16:33+
        repeated attempts to interrupt nested Codex
        process list inspected
        nested Codex process terminated

16:33:58
        parent has reached 10.49M accumulated input

16:41+
        parent model calls are still ~235k input each

final parent count:
        11.74M input

Reproducing the parent counter

FILE="$HOME/.codex/sessions/2026/08/09/rollout-2026-08-09T17-03-43-019fe744-086c-7882-bf60-7a2cbad58146.jsonl"

jq -c '
  select(
    .type == "event_msg"
    and .payload.type == "token_count"
    and .payload.info != null
  )
  | .payload.info.total_token_usage
' "$FILE" | tail -1

Finding spawned child threads

PARENT="019fe744-086c-7882-bf60-7a2cbad58146"

sqlite3 ~/.codex/state_5.sqlite "
SELECT parent_thread_id, child_thread_id, status
FROM thread_spawn_edges
WHERE parent_thread_id = '$PARENT';
"

At the time of inspection all five edges were still reported as open.


Questions worth investigating

Please don't assume these are the causes; they're the areas that appear worth checking from the evidence above.

  1. Why does the /review parent reach ~170k-235k context and continue making enough model calls to accumulate 11.74M input tokens?

  2. Is loading overlapping portions of review/SKILL.md multiple times expected, or is instruction content unnecessarily entering the parent context more than once?

  3. When gstack /review is already hosted by Codex, is it intentional to invoke additional codex exec / codex review processes?

  4. Is the nested Codex behavior contributing materially to subscription usage beyond the parent and spawn_agent reviewers?

  5. Could /review reduce the number of parent orchestration turns after the context becomes very large, move more work into isolated agents, compact/drop tool output, or otherwise avoid replaying ~200k+ context dozens of times?

  6. Is there any duplication in Codex's persisted token counters for parent/child/forked sessions that means some of the numbers above should not be summed?

The clearest issue regardless of the exact accounting semantics is the rate observed in the parent itself: approximately 4.3M additional input tokens in 5m30s, including a ~2m50s interval at roughly 1M input tokens/minute.

Activity

  1. xg-gh-25 commented on Aug 11, 2026

    @xg-gh-25

    This detailed breakdown reveals a critical architecture question: when /review runs inside Codex, its orchestration loop appears to replay a ~170k–235k context dozens of times while spawning agents and nested Codex reviews.

    Three specific acceleration paths worth validating:

    1. Orchestration compaction: The parent makes 75 exec calls + 19 function calls while carrying forward a context that grows to 235k tokens. Could the orchestration consolidate tool outputs into a running summary rather than appending them? The repeated loading of overlapping portions of review/SKILL.md (lines 1-760, then 1-500 again, then 501-1000, etc.) suggests the skill instructions may be entering context multiple times unnecessarily.

    2. Nested Codex boundary: When gstack is already hosted by Codex, invoking codex exec / codex review from within the session creates a nested execution that the parent eventually labels "runaway nested Codex review process that is consuming tokens" and terminates. This nesting boundary deserves explicit design: should /review detect it's running under Codex and skip nested invocations, or should the nested sessions be intentional isolation boundaries?

    3. Agent delegation vs. parent replays: The five spawned agents consume only ~2.8M total tokens across all five, while the parent consumes 11.74M. This 4:1 ratio suggests the orchestration overhead dominates. Could more of the review work move into isolated agents that don't carry the parent's accumulated context?

    The rate is the immediate signal: 1M input tokens/minute sustained over multiple intervals. Even with near-total cache hits, the parent's persisted counter increments on each call. If that counter maps to subscription quota consumption, this pattern makes /review prohibitively expensive under Codex hosting.

    Measurement request: Can the team confirm whether the parent's 11.74M input_tokens counter (dominated by cached_input_tokens) translates 1:1 to subscription usage, or is there a separate accounting model for cached replay that reduces the effective cost?


    Context-window optimization for agentic workflows from SwarmAI. Discussion: T-CBB

  2. tylerchen0123-sudo commented on Aug 12, 2026

    @tylerchen0123-sudo

    One parsing detail that may help interpret the numbers here: in Codex rollout last_token_usage.input_tokens includes cached input, so for per-call monitoring I keep cached_input_tokens separate and derive fresh input as input_tokens - cached_input_tokens (clamped non-negative). I also avoid summing total_token_usage across token events because it is cumulative; I only use the cumulative total as a delta/fallback signal when per-turn input/output fields are missing.

    So the parent's ~11.74M input is useful evidence of repeated processing across calls, but it should not be read as current context size or automatically treated as 1:1 subscription billing units.

    I have a small zero-dependency local Codex rollout monitor that tails ~/.codex/sessions incrementally and exposes fresh/cache/output/session activity here:
    https://github.com/tylerchen0123-sudo/CODEX-Inspection-Guidelines-for-Dosage

    If it helps this investigation, I can adapt the parser/fixture around the /review pattern so the parent vs child vs nested-session accounting is easier to reproduce without sharing private rollout content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions