Run Headless AI Agents Overnight: One Task, One Context

The same twelve tasks cost 389,400 tokens in one agent's memory - or 105,600 with none.

Run Headless AI Agents Overnight: One Task, One Context

You hand the agent a reviewed, frozen PRD: bulk CSV import for a project tracker. A schema migration, a CSV parser, three validation rules, a dedup pass, an import endpoint, three UI states (uploading, validating, done), a rollback script, and one end-to-end smoke test - twelve tasks in all, each with its own test suite, already decomposed, each one small enough to verify on its own. You tell it to build the thing and go to bed. By morning it has auto-compacted, drifted on a schema decision it made in task one, and quit with a cheerful summary of work it half remembers finishing.

Run the identical twelve tasks through twelve separate, disposable invocations instead - same model, same spec, same tasks, nobody watching either way - and the whole build moves 105,600 tokens by the time task twelve lands. Run them through one continuous agent that keeps every decision in its head, and the same twelve tasks move 389,400 tokens, 3.69 times as much, and the session has been forced to compact - trade its own transcript for a summary so the rest fits the window - by task nine of twelve. That isn’t a worse model having a bad night. It’s the same twelve tasks, priced two different ways, and only one of the ways compounds.

Check that your tasks are actually independent

Section titled “Check that your tasks are actually independent”

Before any of the arithmetic below matters, run this on your own spec. Pick any two tasks in it and ask: can the second one’s acceptance check run and pass without anything the first one produced - no shared variable name, no “the schema task one wrote,” no “the endpoint task seven built”?

If the answer is yes for every pair, keep reading: the numbers below get big fast.

If the answer is no - if a later task genuinely needs to know what an earlier one decided - read the spec again before you go anywhere. If the spec forgot to say it, fix the spec and re-freeze; that’s a doc gap, and doc gaps are cheap. But if the two tasks are actually coupled, you don’t have this piece’s problem. You have sequentially dependent work, and a disposable agent per task throws away the one thing you need. The Loop That Re-Reads Its Diary already solved that version: the git commit log stands in as a decision diary a later pass can read. Go there instead. Nothing below will save you anything.

The whole design lives or dies on that one yes-or-no answer, and nothing later in this piece can supply it for you.

Two ways to run twelve independent tasks against a frozen spec.

The first keeps one agent alive for the whole build. It reads the spec once, then works the tasks in order inside a single, continuous session. The appeal is real: it remembers every decision it made, because it made all of them in the same conversation. Task nine’s turn knows exactly what task one decided about the schema, because it’s the same agent that decided it.

The second spawns a fresh, disposable agent per task. Each one reads the frozen spec cold, reads its own one-paragraph brief, does the work, and exits. Task nine’s agent has never heard of task three. It never will.

That’s the whole tension: continuity against amnesia. One design remembers and eventually drowns in what it remembers. The other never drowns, because it never remembers anything at all - and the entire bet is that there was never anything worth remembering in the first place, because the spec already said it.

Both designs run the same model on the same tasks. Nothing about the model changed between them. What changed is what gets resent as input on every turn, and that’s a question of architecture, not intelligence.

Pick continuity and you pay to carry every earlier task’s leftovers into every later one. Pick amnesia and you’re betting the spec already told each task everything it needs.

Shrink it to four tasks and add it up by hand

Section titled “Shrink it to four tasks and add it up by hand”

Four numbers carry the whole argument, and they’re invented for traceability, not measured off a real repo: a reviewed 1,000-line spec runs about 8,000 tokens; the rules file every invocation reads (stack choices, naming conventions) is 500; one task’s own brief and acceptance check is 300; and the reasoning, tool output, and diff it takes to actually finish one task is 4,000.

Every invocation, continuous or disposable, pays the spec and the rules and its own brief before it does anything else: 8,000 + 500 + 300 = 8,800 tokens, every single time. Call that the flat rate. Nothing beats it, because nothing skips reading the spec.

The difference is what a continuous session’s transcript is still holding by the time a later task starts. Task one finishes having produced 4,000 tokens of work, and that work stays in the transcript. Task two’s turn now resends task one’s brief plus its work - 4,300 tokens of pure leftovers - on top of task two’s own flat rate.

Trace four tasks the obvious way, turn by turn, before touching a formula:

TaskContinuous inputDecomposed input
18,8008,800
213,1008,800
317,4008,800
421,7008,800
Total61,00035,200

Four tasks, decomposed into disposable agents, cost 35,200 tokens: four flat rates, nothing more. The same four tasks through one continuous session cost 61,000 - 25,800 more, 1.73 times as much - and every one of those extra tokens is task one, two, and three’s leftovers, resent to a task that never asked for them.

An objection worth answering now, because it ends the read if it waits: provider-side prompt caching discounts a prefix you resend, so the continuous session’s bill is smaller than its token count. Two things survive the discount. Cached tokens still sit in the window, so the continuous session still fills it and still compacts by task nine, and the flat spec every loop pass resends gets the same discount. Caching changes the price of the leftovers. It does not change the design.

On just four tasks, the leftovers already cost more than an entire extra task.

That growing leftover column has a name worth using: the pile tax. It’s the cost of every task re-reading every earlier task’s exhaust - the 300-token brief and the 4,000 tokens of work each finished task leaves sitting in the transcript. Give the tax its shape and it stops being mysterious: every finished task leaves 4,300 tokens behind, and every later task carries all of it, so n tasks pay 4,300 x n(n-1)/2 tokens of pure leftovers. The continuous column is n flat rates plus that term; the decomposed column is n flat rates and nothing else. Check the shortcut against the hand-summed toy: 4,300 x (4 x 3 / 2) = 25,800, and 35,200 + 25,800 = 61,000. Exact. The curve that bends upward is the n(n-1)/2; the flat line has no such term, which is why one design compounds and the other never does.

The fix predates this piece, and it already has a name. Geoffrey Huntley described it in July 2025: a bash loop around a coding agent, fresh context every pass, working a backlog one unit at a time until it’s done. He named it the Ralph Wiggum technique, after the Simpsons character, and it’s established enough now that Anthropic ships an official plugin for Claude Code that runs it: ralph-loop. The loop shape is Huntley’s, named and dated. What this piece adds is the arithmetic for exactly when the flat rate holds, and the one condition that decides it: every task has to be genuinely independent, the thing the self-test above just made you check.

Call the flat-line design running through this piece the flat-rate loop. Same shape as Ralph’s loop; the name here just points at the property this piece is actually about, the one the pile tax breaks.

Huntley named the shape in 2025. This piece prices the one condition that decides whether “flat” actually holds.

Back to the real running example: the CSV-import PRD, twelve tasks, frozen and reviewed before the loop ever starts. The orchestration is dumb on purpose - a shell script:

#!/usr/bin/env bash
set -euo pipefail
while read -r task_id; do
prompt="$(cat tasks/$task_id.md) \
Read SPEC.md and AGENTS.md before starting. \
Implement ONLY this task. Run the test command when done."
claude -p "$prompt" --dangerously-skip-permissions || true # a dead run fails verify below
if ./verify.sh "$task_id"; then
git add -A && git commit -m "feat: $task_id"
echo "$task_id" >> done.log
else
echo "$task_id" >> failed.log # human triages in the morning
fi
done < <(comm -23 <(sort -u tasks.txt) <(sort -u done.log)) # comm requires sorted input

Every task gets its own fresh claude -p invocation - task one for the migration, task seven for the endpoint, task eight for the “uploading” UI state - each one reading SPEC.md and AGENTS.md cold and nothing else. It commits atomically on pass, logs on fail, and comm -23 means a re-run only picks up what’s still outstanding. Nothing half-done leaks into the next iteration, because there is no next iteration sharing a context window with this one.

Each task is a transaction: built, verified, committed, or quarantined - never half-visible to the task that comes after it.

The frozen spec is doing the job memory used to do

Section titled “The frozen spec is doing the job memory used to do”

A disposable agent has no memory of task three by the time task nine starts. What it has instead is the same two files every invocation reads cold: the frozen spec and the project’s rules file. The schema from task one, the “Zod not Yup” decision, the naming convention for the three UI states - none of it lives in any agent’s head. It lives on disk, and every task re-reads it fresh.

This is the mechanism the whole design turns on, stated plainly: the frozen spec is the loop’s only substitute for the continuity it deliberately gave up. Skip the review pass that froze it, and every disposable agent inherits the same gap a continuous one would have papered over with memory.

AGENTS.md
- Persistence: Postgres via Drizzle. Migration in task 1 is the schema - do not redefine it.
- Validation: Zod schemas in src/schema/, imported - never inline.
- Every task ends green on `pnpm test` or it does not commit.
- Touch only files named in the current task. No drive-by refactors.

This is why the self-test at the top of this piece does real work. The frozen spec only replaces the narrow kind of memory an independent task needs: what the spec already says. It cannot replace memory of another task’s actual run - the code it wrote, the edge case it hit, the thing it learned the hard way. If a later task needed one of those, freezing the spec harder doesn’t help. That’s exactly the case the self-test rules out before task one’s claude -p ever fires.

A frozen spec on disk is what twelve blind agents share instead of a memory none of them has.

Sweep the same two formulas - one flat rate per task, decomposed; a flat rate plus the pile tax, continuous - across a wider range of task counts than just four or twelve:

TasksDecomposedContinuousSavedRatio
18,8008,80001.00x
217,60021,9004,3001.24x
435,20061,00025,8001.73x
870,400190,800120,4002.71x
12105,600389,400283,8003.69x
16140,800656,800516,0004.66x
24211,2001,398,0001,186,8006.62x

Derive row 12 before trusting it: twelve flat rates comes to 12 x 8,800 = 105,600, and the pile tax is 4,300 x (12 x 11 / 2) = 4,300 x 66 = 283,800, so the continuous total is 105,600 + 283,800 = 389,400. That is the intro’s number, reproduced from four constants and a shortcut, no estimation anywhere.

Row 12 is the CSV-import PRD from the top: 389,400 tokens continuous against 105,600 decomposed, a saving of 283,800. Row 1 is why the decomposed design has no downside case: a single task costs exactly the same either way, because there’s no earlier exhaust yet to carry. Pause on that, because it’s rarer than it sounds - the disposable map is a straight loss at row 1 and only earns itself back from the second run on. This design starts at parity. The ratio never drops below 1.00x, and it only grows from there.

Look at row 8 against the row the table skips: through task eight, the continuous session has been billed 190,800 input tokens cumulatively - still inside one 200,000-token window’s worth. One task later it crosses 234,000, past a whole window, and that crossing is where the harness forces a compaction: task nine of twelve, three tasks before the build is done. That’s the arithmetic behind the cold open’s overnight run compacting before it finished: by task nine the session was resending more of its own history than the window holds, and the harness cut the transcript down to keep going.

The worse an idea “hand the whole PRD to one agent” already was, the more tasks are in it.

The convenience that makes it run is exactly what makes it dangerous

Section titled “The convenience that makes it run is exactly what makes it dangerous”

Unattended doesn’t mean cheap. One agent called the same tool 47 times in a loop overnight and ran an $80 bill up to $400 before its owner opened the billing dashboard at 2 a.m. Two agents left talking to each other in a loop for eleven days burned roughly $47,000 before anyone noticed. One company reportedly ran up about $500 million in a single month on Claude after never setting usage limits on employee licenses. What these runs share is simpler than the pile tax: nobody was watching the meter, and a loop that runs overnight is a design for nobody watching.

You saw --dangerously-skip-permissions in the loop above. That flag is what lets the loop run at all - without it, every tool call stalls on an approval prompt nobody’s awake to answer. It’s also a loaded gun pointed at your filesystem: an agent that drifts, or a task whose dependency got quietly poisoned, now has unsupervised write and execute access while you sleep.

So the loop runs in a sandbox, never on your real environment. A throwaway container, an ephemeral VM, a checkout with no production credentials in reach - the permission gate you’d normally have a human sitting at gets replaced by an automated verify.sh, a fine trade for correctness and no trade at all for safety.

# the loop's home, conceptually: disposable, credential-free, network-locked-down
container = "build-loop-ephemeral"
mounts = ["./repo:rw"] # the work
secrets = [] # nothing real
network = "none" # no exfil path

The sandbox is the only thing standing between a drifting task and the $500 million story, and nothing in this piece’s arithmetic replaces it.

Six things, roughly in the order they’ll bite.

Zero cross-task memory is the whole trade. If task seven discovers a constraint task eight actually needs, and the frozen spec didn’t already say it, the flat-rate loop has no way to carry that forward. That’s the sequentially dependent problem The Loop That Re-Reads Its Diary already owns; this piece doesn’t re-derive it.

Retries pay the flat rate again. The arithmetic assumes every task passes verify.sh on the first try. Every entry in failed.log that gets re-run pays its 8,800 a second time, and the more your “independent” tasks turn out to be underspecified, the more the 3.69x erodes.

Decomposing the spec isn’t free, and none of the tokens above counted it. Writing twelve tasks with genuinely independent, script-checkable pass criteria is real, unglamorous work, done before the loop ever starts. A spec good enough for this design costs more up front than “here’s the PRD, go” - a cost outside a tokens-only argument.

The sandbox isn’t the only defense anymore. Claude Enterprise rolled out org-level spend caps with admin alerts at 75% and 90% of the cap in July 2026 - a platform-layer control aimed directly at the $500 million story above, worth having on top of the sandbox rather than instead of it.

Rolling your own loop isn’t the only option. GitHub’s coding agent, OpenAI’s Codex cloud tasks, and Cognition’s Devin all run this same disposable-task shape as a hosted service instead of a shell script you own and babysit. This piece is specifically about the self-hosted version; handing the loop to a vendor is a real, reasonable choice it doesn’t make for you.

And this piece leans on a lot of ground that other pieces already own, on purpose. Earn the Automation makes the general case that headless mode replaces a human approval with permissions and hooks before it’s safe; this is the specific, quantified recipe underneath that rule - task decomposition plus a frozen spec plus a sandbox. This loop terminates naturally once tasks.txt runs dry, so it skips the two brakes a loop with no natural end needs; verify.sh is only as good as its acceptance check, which is why a green build is the weak version of “done”; the deterministic gate verify.sh runs is one instance of the general case for a hook over a vibe; and the sandbox’s own numbers - a laptop’s reach cut from 399 addressable things to 63 - are worked out in full in Full Autonomy Is a Small Blast Radius, not restated here. This is also a different shape from one long feature relayed across sessions: Destination and Journey, The Relay, Not the Window, and treating the plan file as external memory all cover one build, many sessions, each picking up where the last stopped. Here it’s many independent tasks, each getting one single-shot agent that never gets resumed. You could fan several of those out in parallel instead of running them one after another - the natural next step once you trust the sequential version - but that’s out of scope here: it widens the blast radius and adds a coordination problem this piece’s arithmetic doesn’t model.

Every number above assumes the trade held. Nothing in this piece can tell you it did until a task fails in a way that proves it didn’t.

Row twelve: 389,400 tokens to run the CSV-import PRD through one continuous agent, 105,600 to run the identical twelve tasks disposable, and a compaction forced on the continuous one at task nine that nobody asked for. Row one is why there’s no case where the decomposed design costs you anything - the ratio starts at parity and only grows.

But the flat rate is only flat because the twelve tasks were true tasks before the loop ever ran: independently specified, independently verifiable, checked against each other with the self-test at the top of this piece before task one’s claude -p fired. Getting a spec to that state is a different kind of work than running the loop, and it’s work this piece’s arithmetic doesn’t price at all.

So here’s what the numbers can’t tell you. They can’t tell you whether your own decomposition actually held - whether task eight secretly needed something task three decided and the spec never wrote down - until a task fails in exactly the way that reveals it.

The 3.69x is real for tasks that were actually independent. Whether yours were is the question this piece hands you, unanswered, at 3 a.m.


About the numbers. The four constants (spec 8,000 tokens, rules file 500, one task’s brief 300, one task’s own work 4,000) are invented for traceability, not measured off a real repo - a plausible mid-size feature build, chosen so every later figure in this piece follows from them by arithmetic you can check with a pencil. Every total, ratio, and the task-nine compaction crossover is derived from those four constants and was re-checked with a script before publishing, and the closed form was checked against a naive turn-by-turn simulation of the same session; they match exactly. The 200,000-token window is a common context size as of writing; other models and configurations vary. The cost anecdotes are quoted from named, dated public sources: the $400 overnight run is Hidai Bar-Mor, dev.to, December 8, 2025 (dev.to/hidai25/my-ai-agent-cost-me-400-overnight-so-i-built-pytest-for-agents-and-open-sourced-it-492c); the $47,000 eleven-day loop is TechStartups.com, November 14, 2025 (techstartups.com/2025/11/14/ai-agents-horror-stories-how-a-47000-failure-exposed-the-hype-and-hidden-risks-of-multi-agent-systems); the roughly $500 million month is TechStartups.com, May 28, 2026 (techstartups.com/2026/05/28/company-accidentally-spent-500-million-on-claude-ai-in-one-month-after-forgetting-usage-limits), which attributes the figure to a consultant’s account of an unnamed client. The Ralph Wiggum technique is Geoffrey Huntley’s, written up July 14, 2025 at ghuntley.com/ralph; Anthropic’s official ralph-loop plugin, at claude.com/plugins/ralph-loop, describes itself as “using the Ralph Wiggum technique.” The Claude Enterprise spend alerts, 75% and 90% of an org-level cap, are from July 2026 rollout coverage of Anthropic’s admin spend controls.

For the per-task execution mechanics, see Headless & CI and Subagents; for the shared memory every agent re-reads, Rules; and before you ever pass --dangerously-skip-permissions, Permissions & sandboxing.