How to Reduce Token Usage with Multiple AI Coding Agents
Cut AI token usage and stop hitting plan limits mid-task. A free spec-driven framework to run Claude, Gemini and ChatGPT coding agents in parallel.
Reduce token usage with multiple AI coding agents.
Four steps that cut token use and keep sessions from dying mid-feature: divide the tasks, track the progress, hand off between AI agents, sort the work. How I built MediDesk on a basic Pro plan with Claude and Gemini working at the same time.
1Divide
One spec, cut into small tasks. Small context, fewer tokens.
2Track
PROGRESS.md: ☐ todo, ◐ partial, ☑ done.
3Hand off
Lock the task, leave a note, the next AI picks it up.
4Sort
Waves by dependency. Nobody waits.
The thread that ran out of road
Every AI model has a different context window, and every person is on a different plan. A bigger window feels like a gift, but it lets one thread keep growing. Everything you said, every file the agent read, every test output, stays in there and gets paid for again on each turn.
Then you hit the limit, usually in the middle of something. The feature is half written. The next session doesn't know what the last one was thinking, so it guesses. That guess is where the bugs come from.
- Thread grows with every turn
- Limit hit mid-task
- Feature half written
- Next session guesses the plan
- Bugs ship
Write the spec once, then cut it into small tasks
If you have to type the requirements into every chat, you are the agent's memory, and you have to sit there the whole time. That isn't using an agent. It's pair programming with extra steps.
So the first thing I wrote for MediDesk was not code. It was a full spec: the data model, every API endpoint, the business rules, the acceptance scenarios. Then I cut that spec into small feature tasks.
Give the agent a coder's job, not an architect's
Each task file carries everything needed to build one feature: which two spec sections to read, which classes already exist, the exact files to create, the traps to avoid, and the command that proves it works. The agent doesn't have to think about the design. It reads the card and writes the code.
# T06: Invitations | Depends on | T03 | Wave | 2 | ## Goal An owner can invite staff by email; invite expires in 7 days. ## Read first (only these) - SPEC.md §3.4 "Invitations" - SPEC.md §5.2 POST /invitations ## Already exists - AuthService.createUserFromInvite() ## Build 1. Table `invitations` (copy §4.6) 2. InvitationService.create(), .accept() 3. Route + screen, 4. Tests ## Acceptance npm test -- invitations ## Out of scope Bulk invites (T21)
- Depends on + WaveThe task manager uses these to decide when the task can start.
- Read firstTwo sections, not the whole spec. This is where most of the token saving comes from.
- Already existsStops the agent rebuilding a helper that lives three folders away.
- AcceptanceA command, not a feeling. Done means it passes.
- Out of scopeNames the later task, so nobody builds it early "to be helpful".
A task sized like this finishes in about 15–20% of the context window. That leaves room for a choice after every task: carry on in the same thread, or open a fresh one and start from zero. The one thing you never do is start a task late enough that it could run past 80%.
A scoreboard every agent can read in one glance
Small threads forget everything when they end, which is the point. So the memory has to live in the repo. PROGRESS.md is one table: every task, what it depends on, its status, who did it, and what is still pending. A new thread reads one row, not a conversation.
| ID | Task | Depends on | Status | Agent | Notes |
|---|
Why pick one AI when all of them can run?
Once every task is self-contained, nothing ties a task to a particular model. Claude can build one, Gemini the next, ChatGPT a third, all at once in the same repo. Stop arguing about which one is best and let each of them run a leg.
The catch is that two agents can pick the same task. So before an agent touches a task it creates a lock: a tiny file saying who has it. If the lock already exists, that task is taken. Pick another.
When an agent finishes, it leaves a note in HANDOFF.md: what it built, what it decided, and a For T07: line for every later task it set something up for. The next agent, whichever AI it is, reads those few lines instead of a whole conversation.
Without a lock
Same task twice. Each overwrites the other's files and both write a handoff.
With a lock
Claude claims T05 first. Gemini's claim fails, so it takes T06.
# claim: fails if someone already holds T05 ( set -o noclobber; echo "agent: gemini-1" > locks/T05.lock ) || echo "taken, pick another" # renew while working; a lock untouched for 90 minutes is stale touch locks/T05.lock # release when done rm locks/T05.lock
Sort the work so nobody waits
Locks stop two agents taking the same task. They don't stop an agent taking a task whose foundations aren't built yet. If billing needs invitations and roles, an agent that grabs billing first is building on air.
The task manager fixes that by sorting tasks into waves. A task with no dependencies is wave 0. Every other task is one wave after its latest dependency. Agents always take the lowest-wave task whose dependencies are done and that nobody has locked. Everything in the same wave can run in parallel.
Press play. Three agents, twelve tasks, and nobody tells them what to do.
The order isn't fixed forever. When a task is added or split, or a decision changes a dependency, the waves are recomputed and the table re-sorted. In MediDesk that's one command: php scripts/task-manager.php --next prints the next unlocked task, its file, and the handoff lines that mention it. The generic framework below ships the same thing as a 50-line Python script.
Four steps, four files
One spec, cut into small task files. Each fits in 15–20% of a context window, so tokens stay low.
Every task and its status: ☐ todo, ◐ partial, ☑ done. A new thread reads one row, not a chat.
Who holds which task right now, and what each agent left for the next one in For Txx: lines.
Waves from dependencies. Says which task can start now without waiting for anyone.
One session, start to finish
- Picknext-task tells you
- Claimcreate the lock
- Loadtask file + 2 spec sections
- Buildfollow the steps
- Checkrun acceptance
- RecordPROGRESS row + HANDOFF note
- Releasedelete lock, commit
That's how two problems went away together. Token use dropped because no thread ever carries more than one task's worth of history. And the risk of hitting the limit mid-task dropped because every task is small and starts with plenty of room. If you want to cut tokens further inside each task, I measured that separately: I measured Ponytail, and the saving was not where I expected.
Three things MediDesk taught me
- A lock doesn't protect shared files.Two agents once rewrote HANDOFF.md at the same time and one wiped the other's notes. Now the rule is: add your own section, never rewrite the file, re-read your edit afterwards.
- The memory files grow, so never read them whole.PROGRESS.md passed 100 KB. Agents now search for their task ID and read only those lines; the task manager prints exactly what's needed.
- Agents crash, so locks expire.A lock that isn't renewed for 90 minutes is stale. The next agent can take it over, after checking
git statusfor leftover work.
The framework, ready to copy
It's plain Markdown and works for any stack and any agent. Drop the files at your repo root, write the spec, split it into tasks, and point every agent at AGENTS.md.
your-project/ ├── AGENTS.md the loop every agent follows ├── SPEC.md what you're building, written once ├── TASK_TEMPLATE.md shape of one task file ├── TASK-MANAGER.md waves + how to pick ├── PROGRESS.md one row per task ├── HANDOFF.md notes for the next agent ├── next-task.py optional: prints the next ready task ├── tasks/T01-*.md one file per task └── locks/ one file per task in progress
Loading…