All articlesAI Engineering

What an AI agent actually costs — and how to cap it

Token spend is the line item nobody scopes until the bill arrives. How we meter every agent server-side, budget it per agent, and stop runaway spend with a daily kill-switch.

Aug 15, 202610 min read

What an AI agent actually costs — and how to cap it

Every agent conversation spends tokens, and tokens are money. Yet cost is the line item almost nobody scopes until the first real bill lands — and it's a surprisingly common reason an otherwise working agent gets quietly switched off. A single well-meaning "do deep research on this" can fan out into dozens of model calls; multiply by a team of users and a month, and the agent that dazzled in the demo is suddenly the most expensive employee you have.

The fix isn't to make the agent timid. It's to treat spend as a first-class, measured, budgeted resource — the same way you'd meter any other utility. Three moves get you there: meter every call server-side, budget per agent, and cap the day with a kill-switch.

Why you meter server-side, not in the client

The temptation is to read the token counts the client already has and log them. Don't. Anything the browser reports is advisory — it can be stale, dropped, or simply wrong when a turn fans out into sub-agent calls the client never sees. The only number you can bill against is the one your own backend records at the moment it calls the model. So the metering lives where the model call lives: server-side, on every turn, including the ones users never directly trigger.

1 · pre-flightbudget left?2 · model calltokens spent3 · recordappend to ledger4 · aggregatevs ceilingceiling reached → pre-flight starts refusing
Spend is a loop, not a report: every call checks before, records after, and the running total feeds the next check.

The ledger: an append-only record of spend

We don't keep a running "balance" field and decrement it — that's a race waiting to double-spend under concurrency. Instead, spend is an event-sourced ledger: every debit is an immutable row, and the balance is their sum. Two turns finishing at once can't corrupt a counter, because there's no counter to corrupt. The same pattern we trust for credits and commissions, we trust for tokens.

goagent/quota.go
 // Pre-flight: refuse before spending if this principal is out of budget or the // daily ceiling is hit. The debit and the check happen in ONE transaction, so // two concurrent turns can't both slip past the last unit of budget. func (q *Quota) Reserve(ctx context.Context, agent, user string, estimate int64) error { return q.db.ReadWriteTransaction(ctx, func(ctx context.Context, tx *Tx) error { day := dailySpend(ctx, tx) // sum of today's debit rows if q.policy.CeilingReached(day) { // kill-switch: whole-fleet stop return status.Error(codes.ResourceExhausted, "daily generation ceiling reached") } if q.policy.OverBudget(ctx, tx, agent, user, estimate) { return status.Error(codes.ResourceExhausted, "agent budget exhausted") } return tx.Append(ctx, DebitRow{Agent: agent, User: user, Est: estimate, T: now(ctx)}) }) } // Post-flight: reconcile the estimate to the real usage the model reported. func (q *Quota) Record(ctx context.Context, agent, user string, actual Usage) { q.db.Append(ctx, UsageRow{Agent: agent, User: user, In: actual.InTok, Out: actual.OutTok, T: now(ctx)}) } 

Reserve first, run, then record the real usage — so a job that dies mid-flight still can't spend past the ceiling, and the numbers you bill against are the model's actual counts, not a guess.

Budget per agent, so you can see where the money goes

A single org-wide number tells you that you're overspending, not who is. Because every row carries the agent and the user, the same ledger rolls up per agent, per person, per day — the research agent cost this, the ops-sync agent cost that. That's the view that turns "the AI bill is too high" into "the research agent's deep-dives are the driver, let's cap those" — a decision you can actually make.

The kill-switch: a ceiling the model can't argue with

Budgets shape spend; the ceiling stops catastrophe. A single console-set daily limit sits in front of generation for the whole fleet: once the day's spend crosses it, the pre-flight check starts refusing new work with a clear, catchable error, and resumes tomorrow. It's the seatbelt for the failure modes you didn't predict — a prompt-injected loop, a runaway retry, a viral spike — none of which get a blank cheque. Crucially it's enforced in the architecture, not asked of the model, so it holds no matter which model is in the seat — the same reason we can stay model-agnostic on price as well as capability.

Cost is a production control, not an afterthought

Metering, budgets, and a ceiling aren't finance hygiene bolted on at the end — they're part of what makes an agent shippable at all. An agent you can't cost is an agent you can't sign off on, which is one more way pilots quietly die. Measure every call, budget per agent, cap the day — and the question "what will this cost to run?" has a number, a dashboard, and a limit, instead of a nervous shrug. That's the difference between a demo and something you can actually put into production. And the number that settles it is never the token bill alone — it's that bill set against the hours of work the agent takes off your team.

Thinking about an agent like this for your team?

Describe the job you want automated and our Automation Architect blueprints it in seconds — or talk it through with the engineers who ship them.