Skip to content
Vinesh Goyal Vinesh Goyal

AI Engineering

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.

Fewer tokens, More agents
The Relay Framework
MediDesk build notes · Agentic coding

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 problem

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.

One long threadThe relay: one small task per thread
Context used over time. Same work, same model. The long thread crosses the 80% line during task 4 and hits the limit inside task 5. The relay never goes above about 20%.
  1. Thread grows with every turn
  2. Limit hit mid-task
  3. Feature half written
  4. Next session guesses the plan
  5. Bugs ship
Step 1 · Divide the tasks, cut the tokens

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.

T01Project setup
T02Conventions
T03Auth & MFA
T04Data models
T05Settings
T06Invitations
T07Roles
T08Billing
One spec, many small task files. MediDesk's spec is about 4,800 lines across the overview, the schema and the API, plus 25 BDD feature files. It became 55 task files.
Step 1 · Why small tasks cost fewer tokens

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%.

35%
The dashed box is the next task (about 20%). If it would end past 80%, don't start it here.
Step 2 · Track the progress

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.

IDTaskDepends onStatusAgentNotes
☐ todo · ◐ partial, with the pending items written down · ☑ done, and the acceptance command passed in that session.
Step 3 · Hand off between AI agents

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

Claude Gemini T05 ✕✕ conflict

Same task twice. Each overwrites the other's files and both write a handoff.

With a lock

Claude Gemini 🔒 T05 🔒 T06 T05 taken → next

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
Step 4 · Sort the tasks

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.

tick 0
    One agent alone needs 26 ticks for these 12 tasks. Press Play to see how long three agents take.
    Dashed outline: ready to start. Coloured outline: locked by that agent. Green: done. Each agent's bar is its context for the current task; a new task starts a fresh thread.

    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.

    The whole thing

    Four steps, four files

    SPEC.md + tasks/1 · Divide

    One spec, cut into small task files. Each fits in 15–20% of a context window, so tokens stay low.

    PROGRESS.md2 · Track

    Every task and its status: ☐ todo, ◐ partial, ☑ done. A new thread reads one row, not a chat.

    HANDOFF.md + locks/3 · Hand off

    Who holds which task right now, and what each agent left for the next one in For Txx: lines.

    TASK-MANAGER.md4 · Sort

    Waves from dependencies. Says which task can start now without waiting for anyone.

    One session, start to finish

    1. Picknext-task tells you
    2. Claimcreate the lock
    3. Loadtask file + 2 spec sections
    4. Buildfollow the steps
    5. Checkrun acceptance
    6. RecordPROGRESS row + HANDOFF note
    7. Releasedelete lock, commit
    Then look at the context meter: under 60%, pick the next task here. Otherwise open a fresh thread.

    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.

    What broke along the way

    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 status for leftover work.
    Take it

    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…
    Pick a file, copy it, drop it in your repo.

    Comments

    Sign in to comment

    No comments yet.