Repository navigation
/review consumed 15M+ input tokens in a few minutes on Codex #2519
Description
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_cachedIt 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_cachedThe 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 -1Finding 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.
-
Why does the
/reviewparent reach ~170k-235k context and continue making enough model calls to accumulate 11.74M input tokens? -
Is loading overlapping portions of
review/SKILL.mdmultiple times expected, or is instruction content unnecessarily entering the parent context more than once? -
When gstack
/reviewis already hosted by Codex, is it intentional to invoke additionalcodex exec/codex reviewprocesses? -
Is the nested Codex behavior contributing materially to subscription usage beyond the parent and
spawn_agentreviewers? -
Could
/reviewreduce 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? -
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
dgrcode commentedon Aug 11, 2026
could be related to
xg-gh-25 commentedon Aug 11, 2026
This detailed breakdown reveals a critical architecture question: when
/reviewruns 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
execcalls + 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 ofreview/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 reviewfrom 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/reviewdetect 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
/reviewprohibitively expensive under Codex hosting.Measurement request: Can the team confirm whether the parent's 11.74M
input_tokenscounter (dominated bycached_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
tylerchen0123-sudo commentedon Aug 12, 2026
One parsing detail that may help interpret the numbers here: in Codex rollout
last_token_usage.input_tokensincludes cached input, so for per-call monitoring I keepcached_input_tokensseparate and derive fresh input asinput_tokens - cached_input_tokens(clamped non-negative). I also avoid summingtotal_token_usageacross 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/sessionsincrementally 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
/reviewpattern so the parent vs child vs nested-session accounting is easier to reproduce without sharing private rollout content.