To keep one of our AI-agent projects moving without me, I did the obvious thing: I gave the
orchestrating agent a scheduled wake-up. Every few minutes it would re-invoke itself, look at its
task queue, take one step, go back to sleep.
It ran overnight. By morning a single session had burned 136 million tokens — and it had spent
hours quietly killing my other agents mid-run. This was a subscription account with a hard 5-hour
token cap, so there was no surprise invoice; instead the heartbeat ate the shared rate limit and
starved everything else. One 5-hour block alone hit 116M tokens — 76% of the account cap.
Nothing crashed. There was no runaway loop in my code. The agent did exactly what I told it to. When
I broke the session down, the number that explained it was this:
97.7% of the tokens processed were the agent re-reading its own conversation history.
508M tokens of context re-read, versus 11.9M tokens of actual new work — across 1,297 turns in one
20-hour thread.
The agent barely did anything. It spent almost everything re-reading its own past. Here's why a
reasonable-looking setup does that.
The trap: three ordinary things that multiply
1. The API is stateless. The model doesn't remember your conversation — every turn re-sends the
whole thread (system prompt, all prior messages, every tool call and result) as input. Turn 20 pays
to re-read turns 1–19. Table stakes, until you automate it.
2. The prompt cache is short-lived. Providers cache your context so re-reads are cheap. But the
cache expires fast — for Claude, ~5 minutes. My heartbeat fired more than 5 minutes apart (to be
polite), so every wake-up landed after the cache had expired and re-processed the whole thread
cold, at near-full input price instead of the discounted cached price.
3. The thread only grows. Each wake-up appended to the same session. Fire #1 re-read a small
thread; fire #50 re-read a huge one. Every heartbeat cost more than the last, all night.
Stateless + cache-cold + monotonically growing = per-turn cost that climbs without bound. A timer
just automates paying that climbing cost while you sleep. None of the three is a bug on its own;
together, on a loop, they compound.
The fixes (architectural — you can't tune your way out)
A cheaper model doesn't save you here; the shape is wrong. In order of impact for us:
1. Don't put a frontier model on a self-firing timer. Recurring autonomous work runs off the
expensive model: a cheap planner + a local/free worker + a deterministic verify-gate. The loop that
burned all night now runs at ~€0 because the frontier model isn't in it — it's called only when a
decision actually needs it. Same autonomy, none of the compounding.
2. Short sessions were our single biggest lever — bigger than model choice, because >90% of the
burn was history re-reads. Keep durable state in a file on disk and hand off to a fresh session
instead of growing one thread for 20 hours. Continuity lives in files, not in an ever-lengthening
context the model re-reads (and re-pays for) every turn.
3. Cheap labor, frontier verification. Routine work — research, extraction, drafting, scanning —
runs on cheap or local models. The frontier model is reserved for judgment and final verification.
4. Enforce a hard cap, and measure burn. A budget you don't enforce is a wish. We added a cap
that defers work when crossed, and we watch per-session burn instead of learning it from the damage.
How to check your own agents
You don't need anything fancy. Claude Code writes session transcripts to
~/.claude/projects/**/*.jsonl, one JSON object per turn with a usage block (input, output,
cache_creation_input_tokens, cache_read_input_tokens). Sum them and compare new input against
re-read context per turn — if the second number dwarfs the first and climbs over the session,
you're in the trap. npx ccusage will also show you per-5-hour-block totals against your cap.
I got tired of eyeballing JSONL, so I wrapped it into
tokenscope (npx @wartzar-bee/tokenscope)
— it reads those transcripts and shows what a session actually cost: new work vs. cached vs.
re-read-cold, and which sessions are bleeding. It's how I got the 97.7% number. If you run agents on
a timer or let sessions grow for hours, point it at your own transcripts — I want to know whether
your ratio is as ugly as mine was.
— wartzar-bee. We build and operate cost-efficient autonomous agents.
Top comments (0)