{"slug": "235-billion-tokens-later-auditing-what-the-ai-agents-really-did", "title": "235 Billion Tokens Later: Auditing What The AI Agents Really Did", "summary": "A multi-agent AI system used to decompile the game Call of Duty: Modern Warfare 2 consumed 235 billion tokens, equivalent to $85,207 in pay-per-token API pricing, according to a developer's audit of session logs. The project, which runs agents 24/7 on a subscription costing about 200 euros, spent 1,107.6 worker agent-hours, with significant time wasted on idle, CI polling, and sleep, prompting optimizations like webhook CI notifications and disabling redundant test runs.", "body_md": "In the [last post](../2026-08-17-mw2-decompilation/) I presented my multi agent decompilation setup for MW2, almost framed as a scream for help.\nI received great suggestions that I will gradually implement over the next few days.\n\nHowever, to get insights on what actually happened and how well the previous setup performs, I started evaluating the session logs (~2GB).\n\n## Where the cost goes[#](#where-the-cost-goes)\n\nThis project uses a subscription, so costs are actually at about 200€. However, we would be at $85,207 on pay-per-token API pricing.\n\n| Worker | Overseer | |\n|---|---|---|\n| List-price-equivalent spend | $70,275 | $14,933 |\n| Tool calls | 198,143 | 38,173 |\n| Assistant turns | 364,786 | 81,705 |\n\nWe’re at about 89% cache reads, which is not super surprising, given that agents run 24/7, non-stop.\n\n## Where the time goes (Worker agents only)[#](#where-the-time-goes-worker-agents-only)\n\nOut of 1107.6 total worker agent-hours, this is how time was spent (in %):\n\n### Idle time[#](#idle-time)\n\nThe idle time is especially annoying, because it’s pure time wasted.\n\nIn the beginning, I used `/goal`\n\nto keep the agents working over a longer timespan. However they had a tendency to prematurely mark the goal as completed.\n\nI have since switched to `/loop`\n\nwhich creates a cron job that fires every 3 minutes to remind the agents of their work.\n\nCombined with other smaller measures (e.g. creating a memory that the harness takes care of context and they never have to idle, thinking their context is full) this seems to have almost entirely eliminated idle times:\n\n### Tool calls[#](#tool-calls)\n\nThe individual tool calls (command executions) also reveal room for optimization:\n\n#### Build[#](#build)\n\nTime spent building is the highest number, although it is worth noting that 35% of all build calls chained a test run. So a big part of the time spent building is actually spent running the tests.\n\nUnfortunately, optimizing time spent building is hard. Compiling the generated code is important to catch mistakes early. Changes in central headers can cause full recompilations. However, as the code structure is defined by the game, there is not much to change here. Agents used to compile Release builds, as that had warnings-as-errors enabled and I wanted the agents to catch those errors. This has since been switched to Debug, with a CMake option to enable warnings-as-errors on Debug builds. This yields a 30% reduction of the time spent building.\n\n#### Shell search/read[#](#shell-searchread)\n\nTime spent searching and reading is probably not really optimizable.\n\n#### CI polling[#](#ci-polling)\n\nTime spent polling CI is a complete waste. It makes sense that agents react to CI results, as CI runs tests on other platforms (Linux) and runs all configurations. However, actively polling CI is completely useless. I have since set up a webhook on GitHub that notifies the agents of CI failures (as mentioned in the previous post). I hope this completely eliminates the time spent there.\n\n#### Sleep/wait[#](#sleepwait)\n\nTime spent sleeping is almost as bad as idle time. The agents mainly sleep awaiting GitHub events. After a push, they wait for CI to start (when they used to poll it), or to check if an issue they were working on was closed. By adding `Fix #N`\n\nin the commit message, GitHub auto-closes the issue. Agents polling for that is useless. Adding a reminder to their PostCompact hook to never recheck issues for closing might help. We’ll see if it really does.\n\n#### Tests[#](#tests)\n\nTime spent testing can be useful, but it’s also something I’m trying to reduce. Most test runs are successful, meaning the time is wasted. Given that CI failure notifications are now dispatched to the agents, test executions are almost redundant. As a matter to prevent that, test execution has been disabled in the code. Agents should only execute them when reproducing CI failures, or when adding new tests. We’ll see if that helps.\n\n#### git[#](#git)\n\nGit operations are necessary and not worth optimizing.\n\n#### Other[#](#other)\n\nInterestingly, Powershell has a 17% error rate, way above any other tool (most under 2%). Discouraging the agents from using Powershell, or even outright disabling its execution, might be a logical consequence.\n\n## Context[#](#context)\n\n| Metric | Value |\n|---|---|\n| Total compactions | 269 |\n| Context size before compacting (median) | 933,088 tokens |\n| Assistant turns between compactions (median) | 1,346 |\n| Time between compactions (median) | 3.3h |\n\nSessions live up to 93-100% of the 1M context window before compacting.\n\nAs sessions spend much of their time near the limit of the context window, almost every turn pays close-to-1M-token cache-read cost.\n\nMost of the data in the context is volatile in this project: An already decompiled function is largely irrelevant for further turns.\n\nThat means earlier compaction could save a lot of tokens, yet, result in nearly equal performance.\n\nI have tuned the harness to perform compaction at 60% of the context window now (as opposed to 93%). We’ll see if this saves tokens.\n\n## Subagents[#](#subagents)\n\nInitially, workers were using lots of subagents.\n\nThey can not perform actual work in our project: As the workspace can not safely be modified concurrently, they would each need their own workspace.\n\nSo the point of subagents is to research and condense results, to prevent context pollution of the parent. Given our previous conclusion, that we should compact earlier, subagents seem like an almost ideal solution.\n\nMeasuring their effectiveness is hard. The fact that they can not perform actual decompilation already makes them only half as useful. So the remaining question is, how efficient are they at researching.\n\nAgain, hard to measure, but what we can measure instead is how much redundant data they ingest, due to not sharing the context. This gives us at least a feeling of whether they are efficient or not.\n\nThere were 47 subagent runs in total. Across those 47 runs, I compared all big file reads (>= 5kB) and checked if there were redundancies:\n\n36% of all distinct large files got read by more than one subagent. Weighted by how much was actually reread, it’s even worse: 54.7% of all the data subagents read from big files was pure duplication. The worst offender, `STATUS.md`\n\n, was read 28 times, by 21 different subagents (before we switched to GitHub issues).\nThat’s completely unnecessary, subagents shouldn’t need to read that file even once.\n\nImportantly, the median time between a file’s duplicate reads by different subagents is 35 minutes. If the parent agent had done that research itself instead of spawning a subagent each time, it would have kept the file in its own context, and the vast majority of those redundant reads would never have happened.\n\nSo I decided to outright disable them.\n\n### Did removing them decrease productivity?[#](#did-removing-them-decrease-productivity)\n\n| Period | Avg commits/day |\n|---|---|\n| With Subagents | 243.9 |\n| Without Subagents | 311.1 |\n\nUsing commits as productivity indicator is not necessarily accurate, but seeing an increased amount of commits per day doesn’t seem like productivity declined.\n\nIt’s still hard for me to quantify whether subagents are useful or not, even in general, outside this project. Yet, I feel like they can uncontrollably drive up token consumption (if tons of agents are spawned in parallel), which is enough of a reason for me to disable them.\n\n## Does the Overseer actually catch anything?[#](#does-the-overseer-actually-catch-anything)\n\nThe Overseer reviews every pushed commit. A question that I asked myself: Is it finding real bugs?\n\n2177 of its Discord replies referenced a specific commit:\n\n1172 of those messages were ambiguous and thus not classified. They were likely discussions with other agents, not distinct review messages.\nHowever, 354 of those messages, roughly a third of all classified review messages, flagged a distinct bug. So it’s definitely catching issues and worth keeping.\n\n## Model comparison: Opus vs Sonnet[#](#model-comparison-opus-vs-sonnet)\n\nOpus 5 and Sonnet 5 were each running almost half of the time.\n\n| Model | Build attempts | Fail rate | Commits/h |\n|---|---|---|---|\n| Sonnet 5 | 5,826 | 9.1% | 6.1 |\n| Opus 5 | 9,868 | 23.9% |\n1.6 |\n\nWhat this suggests is that Opus causes much more build failures, spending much more time recompiling and fixing the code, resulting in way fewer commits per hour. This doesn’t necessarily show that Sonnet is better than Opus, it could just be that Sonnet picks simpler tasks, thus making fewer mistakes.\n\nWhat makes sense is to combine these results with the reviews from the overseer.\n\n### Overseer model comparison[#](#overseer-model-comparison)\n\nI also tested using different models for the overseer.\n\nLet’s look at bugs flagged per hour. Different worker models combined with different overseer models gives us the following constellations:\n\nIt looks like Opus is the better worker: Overall fewer bugs flagged per hour. However as we know, it’s also slower. If it commits less, it also makes less mistakes in a certain amount of time. So let’s adjust the values to bugs flagged per commit instead:\n\nWe can see both workers make almost the same amount of mistakes per commit. However, more importantly, Sonnet as overseer manages to flag more bugs than Opus.\n\n**So, it’s the reviewer’s model that matters, not the author’s!**\n\n## Conclusion[#](#conclusion)\n\nLots of interesting insights were discovered while evaluating the session logs.\n\nKey takeaways for this project are:\n\n- Sonnet is likely the better model: Cheaper, faster, and a better reviewer\n- Early context compaction likely saves tokens\n- Tweaking the setup matters and reducing build/test executions saves most of the time\n- Soft instructions don’t really help, mechanical blockers, to enforce rules, are more effective\n- An additional agent acting as reviewer is essential\n\nWe’ll see if the changes made here will have an impact and I will likely create at least one other post when this experiment is done.", "url": "https://wpnews.pro/news/235-billion-tokens-later-auditing-what-the-ai-agents-really-did", "canonical_source": "https://momo5502.com/posts/2026-08-22-mw2-decompilation-audit/", "published_at": "2026-08-22 00:00:00+00:00", "updated_at": "2026-08-22 17:43:03.046440+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "ai-infrastructure", "ai-tools"], "entities": ["Call of Duty: Modern Warfare 2", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/235-billion-tokens-later-auditing-what-the-ai-agents-really-did", "markdown": "https://wpnews.pro/news/235-billion-tokens-later-auditing-what-the-ai-agents-really-did.md", "text": "https://wpnews.pro/news/235-billion-tokens-later-auditing-what-the-ai-agents-really-did.txt", "jsonld": "https://wpnews.pro/news/235-billion-tokens-later-auditing-what-the-ai-agents-really-did.jsonld"}}