Repository navigation
Image-heavy multi-agent task replays inherited image context, causing 1.48B tokens, 70.73GB traffic, and heavy swap/disk growth #33235
Description
Environment
- Codex Desktop:
26.707.72221(build5307) - Bundled Codex CLI:
0.144.2 - OS: macOS
26.5.2(25F84) - Hardware: Intel MacBook Pro (
MacBookPro16,1), 32 GiB RAM - Workload: one long-running root task that produced 279 images through child tasks
- Task tree: 1 root thread + 25 descendants (26 threads total)
All figures below are sanitized aggregates. I am not attaching raw rollout JSONL because it contains private prompts, image bytes, local paths, and tool outputs.
Summary
An image-heavy multi-agent task appears to repeatedly inherit and replay large inline image context across child threads and subsequent model turns. In this case, the same task family accumulated:
- 1,480,645,018 total tokens in Codex local state
- 70.73 GB of visible upstream traffic during the two-day task window
- 2.916 GB of allocated rollout files for the 26-thread family
- 0.968 GB of generated-image cache
- 0.752 GB in a deleted root rollout still held open by the Codex process
- 16.106 GB of new swap files created during the high-load period
This is related to existing image-heavy rollout and memory issues, but the additional signal here is the multiplicative effect across a multi-agent task tree, including token accounting and measured upstream network traffic while the task was running.
Token evidence scoped to this single task family
I did not sum global/account-wide usage. I recursively selected only the root thread and descendants through the local thread_spawn_edges relationship.
Local state reported:
threads: 26
total_tokens: 1,480,645,018
last_update: 2026-07-15 09:26:37 local time
The parseable rollout token records accounted for 1,476,473,221 tokens:
input_tokens: 1,471,956,553
cached_input_tokens: 1,399,287,552
uncached_input_tokens: 72,669,001
output_tokens: 4,516,668
cached share of input: 95.06%
cached_input_tokens is treated as a subset of input tokens, not added again.
Five high-traffic image child tasks alone recorded:
model turns: 4,244
total tokens: 719,129,229
share of family: 48.57%
cached share: 94.85%
average input/turn: 128,807–135,832 tokens
This suggests that prompt caching reduced uncached processing, but did not prevent the already-large context from being counted and repeatedly processed across thousands of turns.
Image-context evidence
The rollout records contain inline PNG data URLs/Base64 image payloads.
Observed child-task inheritance:
- Three child tasks each started with 26 older images already present, approximately 72.1 MB of image payload per child.
- They then generated 77, 92, and 100 new images respectively.
- Two later retry tasks each started with 103 older images, approximately 269.1 MB before producing their small retry batch.
- A local cumulative-payload estimate for five key image tasks exceeded 53 GB before protocol overhead, text context, root-thread activity, and retries.
The 53 GB figure is a local uncompressed-payload estimate, not a claim that it equals billed network bytes.
Network evidence
A third-party upstream traffic meter showed 70.73 GB of visible records during the two-day task window:
day 1 visible records: 45.00 GB
day 2 visible records: 25.73 GB
total visible: 70.73 GB
Records below 10 MB were omitted by that meter.
On day 2, image-task windows could be aligned precisely:
- Three image children started at 00:50, 00:51, and 00:52.
- Upstream usage from 00:52 to 03:45: 22.50 GB.
- Two retry children started at 07:57 and 07:58.
- Upstream usage from 07:59 to 08:27: 2.27 GB.
- Combined time-aligned usage: 24.77 GB, or 96.3% of the visible day-2 total.
- Large traffic records nearly disappeared while the image tasks were paused between approximately 04:00 and 06:00.
The traffic meter cannot attribute bytes to a Codex thread ID, so the network relationship is a time-correlation observation rather than per-thread byte accounting.
Local disk and memory evidence
Task-family Codex storage:
26 rollout files, allocated: 2,915,504,128 bytes
corresponding generated images: 968,327,168 bytes
deleted root rollout still open: 751,684,963 bytes
task-associated log payload: 123,500,431 bytes (8,908 rows)
The root rollout was scrubbed/slimmed from approximately 742 MB to approximately 10 MB after confirming images were saved. However, lsof +L1 showed the Codex process still holding the deleted old inode, so approximately 751.7 MB was not returned to the filesystem until the file descriptor/process closed.
Swap evidence:
APFS VM volume peak: 19,328,688,128 bytes
new swap files in window: 15 × 1 GiB
new swap allocation: 16,106,127,360 bytes
later VM volume usage: 12,567,490,560 bytes
free-space recovery: 6,821,634,048 bytes (about 6.82 GB)
The VM volume is system-wide, so I cannot assign every swap byte to one Codex thread. The creation times were concentrated in the image-task high-load window.
No local Time Machine snapshots or extra APFS Data snapshots were present.
Reproduction shape
- Start a long-running root task that needs hundreds of generated images.
- Let the root task spawn multiple image-producing child tasks.
- Allow child tasks to inherit the parent transcript containing prior inline image results.
- Continue generating images and making model/tool turns in each child.
- Spawn retry children from the already image-heavy root context.
- Observe:
- cumulative token usage per thread,
- rollout JSONL size,
- repeated inline
image_url/image payloads, - generated-image cache size,
- upstream traffic,
- process RSS and swap,
- deleted-but-open rollout files after slimming.
Expected behavior
- Generated images should be stored once and referenced from rollouts by path/content hash rather than duplicated as full inline Base64 whenever possible.
- Child tasks should not inherit raw historical image bytes unless those images are explicitly needed.
- Multi-agent image workflows should have rollout/context size gates and warnings.
- Codex should expose configurable token, context, disk, or network budgets for long-running tasks.
- Compaction/slimming should not leave large deleted rollout inodes retained indefinitely.
- The app should warn before a thread/task family reaches dangerous rollout, memory, or cumulative-token levels.
Actual behavior
The task continued normally in the UI while token usage, upstream traffic, rollout storage, memory pressure, and swap grew substantially. Most input tokens were cache hits, but the aggregate context-processing count and local/network resource usage still became very large.
Related issues
- Codex Desktop hangs when opening an image-heavy session rollout (~183 MB, huge inline image_url records), and the thread becomes hard to recover from the sidebar #24676 — image-heavy rollout with inline image data hangs Codex Desktop
- # Codex desktop main-process crash:
RangeError: Invalid string lengthwhen loading sessions whose rollout JSONL exceeds V8's max string length #22004 — oversized image-heavy rollout can exceed the desktop/V8 string limit - Desktop threads can be poisoned by inline base64 tool images, leading to
{"detail":"Bad Request"}on resume and likely inflated token usage #18629 — inline Base64 tool images can poison resumed desktop threads and may inflate token usage - Codex memory grows to 75GB+ during basic session #20740 — extreme Codex memory growth on macOS
- Codex session logs grow to 700MB-2GB from repeated compaction history and raw tool output #24948 — rollout/session logs growing to hundreds of MB or GB
- The issue of dramatically increased Codex quota consumption. #26306 — dramatically increased quota/token consumption
- Data loss: resumed-thread errors due missing rollout JSONL files (state still has threads, files gone) #21196 — deleted rollout files remaining open in the Codex process
This report is not primarily about reopening/rendering an existing large thread. The resource amplification was observed while the multi-agent image task was actively running.
Privacy / additional diagnostics
I can provide additional sanitized record counts, timestamps, SQL queries, and file-size summaries if useful. I cannot post the raw rollout or generated images publicly because they contain private user content.
Activity
github-actions commentedon Jul 15, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
dorukardahan commentedon Jul 23, 2026
i have an independent reproduction from another long-running Codex 0.145.0 session.
i counted real server usage updates after one affected compaction, not the provisional local recomputation. The first 53 updates reported:
The matching compacted checkpoint retained 32 high-detail inline images. The current estimator in Codex maps them to about 59,000 model-visible image tokens:
codex/codex-rs/core/src/context_manager/history.rs
Lines 493 to 506 in 808d3c2
For a workspace on the current token-based Codex rate card, the GPT-5.6 Sol input rates are 125 credits per million uncached input tokens and 12.5 credits per million cached input tokens. This 53-update input mix maps to about 206 input credits before output:
https://help.openai.com/en/articles/20001106-codex-rate-card
This is not an account invoice and it does not isolate the image-only share. The usage event has no modality split. It does show that a high cached share does not make the repeated large context free.
i did not inspect or upload prompts, paths, images, tool output, project names, thread IDs, or account-wide totals. A useful regression signal would be sanitized per-request retained image count and estimated image tokens, together with a test that a second compaction request does not replay images covered by the first compaction.
qingye-lab commentedon Jul 24, 2026
Additional sanitized macOS reproduction confirming the same network-amplification pattern, with a much smaller image count.
Environment
26.721.31836(build5828)codex-cli 0.146.0-alpha.3.127.0(build26A5388g), Apple SiliconImage/context evidence
One long-running root thread received 30 PNG attachments in a single user message.
Sanitized structural inspection of the rollout showed:
input_imagedata-URL payload: 44,102,256 bytes across 30 imagesreplacement_historySeveral descendant tasks inherited the compacted image context. Three descendants that did not contain a new direct image message still produced 11–15 compacted records of roughly 42.1 MiB each. Their recorded input-token totals were approximately 488–490 million each, with similarly high cache-hit ratios.
Network evidence
I decoded the per-host/per-second history stored by a local Clash/Mihomo client and aggregated the same 24-hour window:
chatgpt.comaloneA separate per-process traffic display showed approximately 84 GB for Codex over its slightly different window.
The timing aligned closely:
chatgpt.comconnections mapped to the Codex process had each uploaded approximately 33 MBThe 44.1 MB inline image payload repeated roughly 2,100 times is sufficient to explain the measured upstream traffic. Prompt caching clearly reduced uncached model processing, but it did not prevent the client-side payload from being retransmitted.
All
chatgpt.comtraffic in this case used configured proxy nodes rather thanDIRECT, so the amplification also consumed metered proxy traffic.Why this additional repro may matter
This case reached approximately 94 GB upstream in one day with only 30 user-attached images, rather than hundreds of generated images. It suggests the issue can be triggered by a relatively ordinary batch of screenshots when the parent task runs for a long time, performs many tool/model cycles, compacts repeatedly, and spawns descendants.
The observed behavior is consistent with inline image bytes being retained in hot history and replayed across later turns, compactions, and inherited subagent context. A content-addressed attachment reference, explicit retained-image byte/count budget, and excluding historical image bytes from default child inheritance would likely prevent this amplification.
bbingz commentedon Jul 25, 2026
Analysis (community)
Residual analysis for #33235 (image-heavy multi-agent tasks replaying inherited image context → extreme token/traffic cost) under docs/contributing.md — invitation-only. No unsolicited PR.
Root-cause hypothesis (narrowed)
Multi-agent V2 spawn defaults
fork_turnsto"all"→ FullHistory, which re-copies user/system/developerMessageitems includingContentItem::InputImage. That is a real OSS amplification path for attachment-style images. It is not true that every image-bearing wire type is re-injected: tool-output images andImageGenerationCallare explicitly dropped by the fork filter.Verified at HEAD
4c43465133:1. V2 default fork mode = FullHistory.
codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rsSpawnAgentArgs::fork_mode:fork_turns→.unwrap_or("all")"all"→Some(SpawnAgentForkMode::FullHistory)"none"→None(no parent history fork)LastNTurns(n)fork_contextpresent → error (usefork_turns)So the default spawn path forks full parent rollout history unless the model opts out.
2. What FullHistory keeps vs drops (
keep_forked_rollout_item).codex-rs/core/src/agent/control/spawn.rs:Messagerole system/developer/user (any content — includingContentItem::InputImage); assistant only ifFinalAnswer;Compacted/EventMsg/SessionMeta; optional TurnContext/WorldState under full history.FunctionCall/FunctionCallOutput/CustomToolCall*/ImageGenerationCall/ reasoning / compaction triggers / etc.3. Image carriers (protocol) × inheritance.
Message+ContentItem::InputImageMessage+ imagesview_image→ FunctionCallOutput + InputImageImageGenerationCallSo the reporter narrative “multi-agent replays inherited image context” is partially right (message-embedded attachments under default FullHistory, multiplied per child) and partially over-broad if read as “all image types including tool/ig payloads.”
4. V1 contrast.
Legacy multi_agents spawn uses FullHistory only when
fork_context=true(opt-in). V2 inverted the default to full fork — important when attributing regressions.5. Distinct from #33493 / compaction (R-S).
Compaction image-token / re-fire issues are a different axis from spawn-time message inheritance.
Ranked fix outline (all OSS):
fork_turnsfromall→noneor a small N (behavior change — needs product call).keep_forked_rollout_item: strip or stubContentItem::InputImageunless opt-in.fork_turnsdefaults and image inheritance in the spawn tool schema description.Fail-first tests: (1) default spawn without fork_turns → FullHistory; (2) parent user message with InputImage appears in child history; (3) parent ImageGenerationCall / FC-output image does not; (4)
fork_turns=none→ no parent response history.Happy to help sketch the strip-images-on-fork patch if maintainers want the safer default. No unsolicited PR.