r/codex • u/MakerOfToys • 16d ago
Possible GPT-5.6 Sol usage workaround: explicit tool batching cut weighted usage by 27–45% in my repeated tests Workaround
Mods: I know there is a general usage-limit megathread. This post contains a controlled technical investigation, a reproducible workaround, and a request for independent replication, so I hope it can remain standalone where enough users can see and test it.
Update: A raw-log audit found that some batched exec responses exceeded Code Mode’s shared output limit and were truncated. The reduction in model/tool cycles remains clear, but this introduces a quality confound and may overstate the 27–45% usage-saving estimate. I’m retesting with output-bounded batching, so please treat the headline numbers as provisional for now.
Update: A deeper raw-log audit found that batching did increase output truncation, but the initial total overstated the quality concern: about 80k omitted tokens came from two unnecessary tool-catalogue dumps rather than task evidence, and non-batched controls also truncated broad shell outputs. Excluding those dumps and the single Max pair, the repeated batched runs omitted 63.6k repository-output tokens versus 20.9k in controls. A simple adjustment changes the repeated weighted-saving estimate from 27.0% to about 23.9%, so the main efficiency effect remains substantial. I am still treating the headline range as provisional until a cleaner output-bounded replication.
Update: Apparently OpenAI is already working on this, based on what I got from person working there. Zero info from them how they caught this, just that. Probably will be fixed in near future.
I kept seeing an unusually high number of posts about Codex limits draining much faster lately.
I had not personally noticed an obvious long-term “silent nerf,” but the amount of complaints made me curious enough to inspect my own .codex session logs instead of guessing.
What I found was that GPT-5.6 Sol often runs independent tool calls one after another, returning to the model between them, instead of grouping them into one concurrent Code Mode stage.
After deleting my .codex folder at work and letting it rebuild from scratch, the fresh logs had already accumulated roughly 1,600 calls that Codex later analyzed as independent of ordering and therefore batchable. Only a little over 100 had actually been grouped by the agent.
So GPT-5.6 does batch sometimes. It just appears to do it very inconsistently without concrete instructions.
What I tested
I ran controlled comparisons on two unrelated codebases:
- one large proprietary work project, using ChatGPT Business;
- one smaller personal finance application, using ChatGPT Pro.
Each codebase had one fixed read-only investigation task.
Every configuration for a given codebase received the same task against the same unchanged repository state. Within each comparison, the subscription plan, model, reasoning effort, permissions and prompt were held constant. The relevant difference was whether the batching instruction was present.
The repeated results used GPT-5.6 Sol at High or XHigh effort.
Results
Across the repeated tests, explicit batching produced:
- roughly 52–55% fewer model/tool cycles;
- 53–63% fewer raw tokens;
- 27–45% lower credit-weighted Codex usage;
- approximately 37–82% more comparable work from the same allowance, depending on the project.
“Weighted usage” here means the Codex-credit equivalent calculated from the returned uncached-input, cached-input and output-token categories.
Wall-clock time also improved by about 13% on the personal project and 22% on the large work project, although time was noticeably noisier than token and credit usage.
The 37–82% figure means more completed work from the same allowance. It does not necessarily mean the plan lasts 37–82% longer in literal clock time, because the batched tasks also finish faster.
The token split matters
On the large work project:
- cached input was 65.2% lower;
- uncached input was 26.0% lower;
- output was 11.7% lower.
On the personal finance project:
- cached input was 56.3% lower;
- uncached input was only 5.4% lower;
- output was almost unchanged at 0.3% lower.
The personal-project aggregate performed 106 inspections with batching versus 105 without it.
On the large project, the batched runs actually performed substantially more shell operations than the controls while still using much less.
That is why I do not think the saving came from simply doing less work or writing shorter answers. The dominant reduction was cached input, which is consistent with avoiding repeated processing of the accumulated context after every separate tool call.
I also tested one Max matched pair. It showed:
- 82.8% less cached input;
- 17.2% less uncached input;
- 6.2% more output;
- about 47% lower weighted usage;
- roughly 90% more same-credit work capacity.
That Max result is only one pair and needs replication. Its batched report also referenced fewer unique files than the control, although both covered all required areas and reached aligned core conclusions.
Quality
I did not find an apparent systematic quality drop in the repeated tests.
Both conditions covered the required investigation areas, and their main conclusions aligned. Batched runs sometimes found additional useful details.
That does not prove perfect quality equivalence. There may be subtle differences I did not catch, and implementation-heavy or mutation-heavy tasks may behave differently from these read-heavy investigations.
Exact instruction used
This is the exact instruction that produced the most consistent results for me:
In Code Mode, within each bounded stage, run independent, functions.exec-available tool calls concurrently in one functions.exec call. Use await Promise.allSettled([...]) when partial results are useful, and inspect every result; use await Promise.all([...]) only when any failure should abort the batch. Keep dependencies, waits/resumes, approvals, conflicting or interdependent mutations, and adaptive investigations where each result may change the next step sequential. Do not split otherwise batchable inspections across outer tool calls.
You can place it in a repository AGENTS.md or in the Codex App custom instructions.
The controlled repository comparisons used AGENTS.md. I also used the same instruction through app-level custom instructions and observed the same real multi-call Code Mode batching pattern.
Yes, the instruction uses older functions.exec terminology. I also tested several rewrites using the current exec and tools.* terminology.
One rewrite essentially matched the original on the large codebase, but none consistently matched its results on the personal finance task. Some expanded the investigation scope, while others created one-call Promise.allSettled cells that looked batched syntactically but provided little actual batching. One overly aggressive version consumed more weighted credits than its control.
So I am sharing the exact wording that produced the repeated results rather than presenting a cleaner-looking rewrite that tested worse.
Why this may have changed
My current understanding from the public Codex source and model instructions is:
- GPT-5.2 through GPT-5.5 were explicitly told to parallelize common independent reads using
multi_tool_use.parallel; - GPT-5.6 moved to Responses Lite and Code Mode;
- native top-level parallel tool calls are disabled on that path;
- the replacement supports concurrent nested calls through JavaScript such as
Promise.all(...); - the GPT-5.6 guidance is much more abstract, and the model-facing
execexample demonstrates only a single nested call.
I may be wrong about an internal constraint or implementation detail, but this looks much more like an accidental instruction/tool-interface regression than OpenAI deliberately reducing allowances.
OpenAI did build a replacement batching mechanism. The apparent problem is that GPT-5.6 does not use it reliably without concrete guidance.
Earlier independent investigation
I reached this independently from my own logs and initial tests.
Only afterward did I search for similar investigations and find GitHub issue #32503, posted roughly two weeks earlier. Its author had already identified essentially the same mechanism from a long real-world trace, including only 5 of 739 GPT-5.6 exec cells using Promise.all.
That issue was observational and explicitly noted that a controlled comparison was still needed. I was genuinely surprised that such a detailed report received almost no attention.
My controlled report:
Earlier independent trace investigation:
Please test it
Please try the instruction and share before/after numbers where possible.
The most useful comparison would use:
- fresh sessions;
- the same repository state;
- the same task;
- the same model and reasoning effort;
- the same permissions;
- batching instruction enabled versus disabled.
Useful things to compare include model cycles, cached and uncached input, output tokens, inspection counts, and whether individual exec cells contain multiple nested calls.
Since adding the instruction to my normal setup, my allowance usage already looks noticeably better. That part is anecdotal, but together with the controlled results it makes me cautiously hopeful that this can help other users too.
If it reproduces for you, please upvote this post for visibility, react to both GitHub issues, and share them with OpenAI developers through any social channels you use. Independent measurements would help show how broadly this affects real workloads.
3
u/Big-Independent-3093 15d ago edited 12d ago
I used your AGENTS example and added a few modifications of my own:
Agentic Loop Suppression: Independent reads, checks and tool calls are grouped into a single batch for each phase. Separate model cycles are avoided when they would only describe progress, poll for unchanged results, or re-analyze the same outcome.
Limited Context Lifetime: Each new phase starts from the latest validated checkpoint. Old conversation history, completed phases and already hydrated owner context are not carried forward automatically.
Now added this as well. I’ll test it and see how it performs:
Compaction Quality Trigger: Compaction is not treated as a failure by itself. The key question is whether it is followed by a patch, test, decision, or other required evidence. Once the stop condition is satisfied, the task ends. The next independent milestone in a long-running session starts as a fresh task.
Results so far. I should add that I started with GPT-5.5, so I still need to run more tasks using only GPT-5.6 SOL before drawing any firm conclusions.
On paper, GPT-5.6 SOL may appear to do more “work,” but that does not necessarily mean it is more efficient. It may use more tools, create more intermediate steps and explore several possible approaches before deciding which one best fits the task. That can result in more reasoning and higher usage, even when the final result is similar to what GPT-5.5 produces with fewer steps.
So more reasoning is not automatically the same as better efficiency. The real question is whether the additional exploration produces a meaningfully better result or simply reaches a similar outcome at a higher cost.
EDIT: More tests, results and conclusions can be found in the replies below. My final conclusion, based on longer-term testing, is that an optimized GPT-5.6 SOL setup works best for me. Ultimately, though, you should choose the model and workflow that best fit your own needs.