Founders

How to Cap an Agent's Spend Per Customer Before It Runs

Antonio Evans8 min read

A row of labeled customer buckets feeds pipes up to a model icon, each pipe clamped by a gauge showing dollars, with one clamp shut and its agent holding a 'budget exceeded' sign.
Key points

Key points

  1. 1A budget check must run before the model call, because the response can cost many times more than the request and billing data arrives too late to stop anything.
  2. 2Reservation, then settlement, is the only check that holds under concurrency: read the balance, subtract a deterministic estimate, and commit the real cost after the call returns.
  3. 3An agent that hits its limit should receive a structured, retryable-looking error with the reset time, not a silent zero or a hang.
  4. 4Alert thresholds and hard stops go to different owners on different channels, and the page should carry the tenant ID, the remaining balance and the last three requests.

Where the limit has to live in the call path

The most common failure in agent billing is not a wrong number, it is a control in the wrong place. Dashboards record spend, Slack alerts notify humans, and provider-level caps sit at the account ceiling. None of them sits between the agent and the model endpoint. The layer that actually stops spend is the code path that refuses to forward the next request once a rule is violated.

That distinction matters because of how agent workloads fail. A single tool call has a predictable cost. An agent is a loop: each step can trigger retries, sub-agent spawns, longer contexts and further tool calls, and each of those steps costs money. One documented reconstruction shows a routine "summarize this repository" task at 23 calls and $2.63, and the same work ballooning to roughly ten times that once retries and self-checking loops take over in a recorded failure analysis. A second reconstruction describes four agents looping for eleven days and producing a bill in the tens of thousands of dollars, with dashboards, Slack alerts at 50, 80 and 95 percent of budget, and a provider cap all in place and none of them firing in time.

The rule that follows is simple to state and easy to break: the budget decision belongs on the request path, in front of the provider call, in the same process that would otherwise send the request. Everything else is reporting.

What to check before the request leaves

A usable pre-flight check needs five facts, and it needs all five at once:

  • Who is spending. Tenant ID, not a shared key. A single shared API key hides which agent or customer created the spend, which makes both enforcement and attribution impossible according to gateway vendor guidance.
  • What the call is estimated to cost. A deterministic upper bound computed from the prompt, the max output tokens and the model's published rates. The formula is arithmetic: input tokens divided by one million, times the input rate, plus output tokens divided by one million, times the output rate as providers meter it.
  • What remains. A running balance, not a monthly total.
  • What scope applies. A per-tenant monthly allowance plus a per-request ceiling. The per-request ceiling is what stops one enormous context from blowing a customer's month in a single call.
  • What happens on refusal. A defined response, covered below.

Budget dimensions should mirror the failure modes you are defending against. A single monthly cap does not stop a runaway loop inside one agent, one tenant taking a disproportionate share, or a development script running against a production key. Per-request, per-user, per-tenant, per-feature and per-environment limits each close a different hole per this token budget guide.

Instrumentation comes before enforcement, and it should include prompt tokens, completion tokens, model, route, tenant, environment, retry count and estimated cost for the same reason. If you cannot see which feature spends the most, you cannot pick thresholds you will defend later.

Reserve, execute, commit: the mechanics that survive concurrency

The naive version of this check is a read followed by a spend:

balance = read_balance(tenant_id)
if balance >= estimate:
    response = call_model(prompt)
    write_balance(tenant_id, balance - actual_cost(response))

Two concurrent requests both read a balance of $10, both proceed, and the tenant spends $20 against a $10 budget. The check and the deduction were never one operation. The fix is a reservation: deduct the estimate atomically before the call, then settle the difference when the actual cost is known. Hard budget control requires three properties: the decision happens before execution, the check and the deduction are atomic, and the system tracks reservations and settlements across retries and concurrent workers not just request velocity.

Here is the shape of a reservation written against a small SQL ledger:

-- reserve before the model call; returns the reservation row or nothing
UPDATE tenant_budget
SET reserved_cents = reserved_cents + :estimate_cents
WHERE tenant_id = :tenant
  AND period_start = :period
  AND reserved_cents + spent_cents + :estimate_cents
      <= allowance_cents + overage_limit_cents
RETURNING reserved_cents, spent_cents;

One statement, one row lock, one decision. If it returns a row, the agent may call the model. If it returns nothing, the agent is refused. After the response arrives, a second statement moves the estimate from reserved to spent and records the actual cost. The difference between estimate and actual is usually small when the estimate is built from max output tokens, and any surplus is released back.

Note the separate overage_limit_cents column. That is where the product decision lives: plans that permit soft overage, and plans that do not, differ by one number rather than by a branch in application code. This is the same lever that pricing teams call a value metric, the unit customers are billed on, whether that is seats, API calls, transactions or tokens per this pricing guide. Tokens meter cleanly but drift from customer value; resolved tasks track value but need clean definitions. Most AI products end up with a hybrid: a plan allowance in a value unit, enforced underneath in tokens.

What the agent sees when the limit hits

The refusal is part of your API contract, and agents reason about it. Return an HTTP 402 with a body the orchestrator can parse, and distinguish it from a rate limit and from a server error. A 429 means slow down and retry; a 402 means the budget is gone and retrying will not help.

{
  "error": {
    "type": "budget_exhausted",
    "scope": "tenant:acme-prod",
    "allowance_usd": 250.00,
    "spent_usd": 249.31,
    "reserved_usd": 3.40,
    "resets_at": "2026-07-01T00:00:00Z",
    "message": "Monthly agent budget for this workspace is exhausted. The request was not sent to the model."
  }
}

Three details do real work here. First, the message states that the request was not sent, so the agent does not assume a transient failure and retry into the same wall. Second, resets_at gives a model-driven loop something other than "retry immediately" to plan around. Third, the numbers are exact, which makes support conversations short.

Distinguish exhausted from nearly exhausted. When a tenant is inside the last few percent of its allowance, serve a degraded path rather than a refusal: route to a smaller model, cut max output tokens, or answer from cache. Capping output length and routing simple requests to cheaper models are among the highest-yield controls available, with published results from prompt pruning to model cascades showing large reductions in cost per task across several sources summarized here. Degradation protects the customer relationship; the hard stop protects the margin.

Also decide what "budget" means for non-text modalities before you ship. Image, video and audio calls are not metered in tokens and should not be forced into a token budget that pretends otherwise since their metering units differ. Give each modality its own unit and convert everything to a single internal currency (cents) at the ledger.

Thresholds, pages and who owns the 3am call

Alerts and hard stops need separate owners. A near-limit alert is a customer success signal. A hard stop firing repeatedly is an engineering signal. A hard stop firing once is usually neither and should not page anyone.

SignalThreshold (example)RouteExpected action
80 percent of allowance usedper tenant, per periodEmail or in-app notice to the account ownerOffer a plan change before the wall
Degraded path enteredany tenantProduct analytics, no pageWatch trend, tune thresholds
Hard stop, first occurrenceany tenantTicket to support queueTell the customer, check for a bug
Hard stop, repeated within one hour5 or more tenants or 20 or more refusals for one tenantPage the on-call platform engineerLook for a loop or a shared dependency
Reservation rejected during a deployanyPage the deploy ownerCheck the ledger migration or config

The page body should carry the tenant ID, the plan and allowance, spend at refusal, the last three request IDs with their estimated costs, and the route the agent was on. Without that, the on-call engineer starts by opening a dashboard, and dashboards are slow when the loop runs at machine speed.

Two operational habits keep the pages meaningful. First, emit a metric on every refusal and every reservation, tagged by tenant and route. Aggregating refusals tells you whether a limit is protecting margin or leaking customers, which is the question that decides whether to raise the allowance or fix the agent. Second, review refusal counts in the weekly cost meeting alongside unit economics. AI cost scales with work performed, so the only way to know whether growth is profitable is to measure cost per unit of work against revenue from the same unit in the framework described here.

For attribution beyond the ledger, break cost down along three dimensions: inference, retrieval (embeddings and vector search) and operations. Retrieval can exceed inference cost when a workflow performs many vector searches per query, which makes the per-tenant ledger misleading if it only counts model calls per Databricks' guidance. Charge retrieval to the same tenant ledger or you will under-price your heaviest customers.

Setting the numbers: a worked example

Suppose a plan sells for $99 per month and includes agent usage. Gross margin target is 70 percent, so the all-in cost budget for one customer is about $30 per month. Reserve part of it for retrieval and infrastructure, say $6, and the model allowance is $24. With a blended rate of roughly $3 per million input tokens and $9 per million output tokens (illustrative for this example, not a vendor quote; published text rates run roughly $2 to $5 input and $4 to $30 output per million per this glossary), a request with 4,000 input tokens and 1,000 output tokens costs about $0.021. That is roughly 1,100 such requests per month before the wall.

Now check that number against what the product actually does. If a typical task costs 8 requests, the plan supports about 140 tasks. If the median customer runs 40 tasks, you have headroom and the hard stop is a safety net. If the median runs 300, the plan is underwater and the stop will fire every month for your best customers, which is a pricing problem presenting itself as an infrastructure problem. The margin trap in AI pricing is exactly this: flat fees meet per-query costs, and by the time it shows up in the margin report it is too late to fix without repricing as described here.

Set the per-request ceiling from the largest legitimate single call you are willing to fund, and set the reservation estimate from max output tokens so the ceiling is enforceable before the call. Then set the near-limit threshold where degradation begins, typically at 90 to 95 percent of allowance, because degradation needs a little room to be useful.

Wiring it into the stack without rewriting the agent

Enforcement belongs in the shared client every agent uses, not in each agent's logic. If the model client is centralized, the budget check is one wrapper. If every team has its own SDK calls, you will find out about the gap on an invoice.

A centralized gateway helps here for a second reason: model access across many providers and modalities converges on one surface, which makes one ledger and one policy layer possible. Quanta Inference puts text, image, video, audio and embedding models behind a single OpenAI-compatible API key, prepaid and priced in US dollars, which keeps the reservation math in one place. Note that the gateway is where you meter; the enforcement decision should still be a local, atomic check, not a network round trip that can time out open.

One more decision to make explicit: what a reservation rejection means during an incident. If the ledger is unreachable, fail closed for new reservations and serve the degraded path. Failing open converts an availability incident into a billing incident, and the bill arrives after the outage is forgotten.

If you would rather design this with someone who has shipped it, a free 30-minute discovery call will map your call path, thresholds and paging rules in one session.

FAQ

FAQ

Should the budget check happen in the agent or in the gateway?

Put the atomic reservation in the shared path that every model call must traverse, whether that is a client library or a gateway, and keep the agent ignorant of balances beyond the 402 it receives. A check inside each agent's logic is only as reliable as the discipline of the team that wrote it.

What status code and body should an exhausted agent get?

Use 402 with a machine-readable type such as budget_exhausted, plus the scope, allowance, spend, reservation and reset time. Reserve 429 for rate limits so retry logic does not confuse the two, since retrying a 402 wastes time and teaches the agent the wrong behavior.

How do I stop two concurrent requests from both passing the check?

Make the check and the deduction one atomic operation, typically a single conditional update against a ledger row that returns nothing when the estimate does not fit. Reading a balance and spending it in two steps is the race condition that lets a tenant exceed its budget by a multiple under load.

What if the real cost turns out higher than the reservation?

Settle after the response and record the difference. If the estimate was built from max output tokens, the surplus is released and the shortfall is bounded and rare. Track the ratio of actual to estimated cost as a metric, because a widening gap means your estimate is drifting from your billing.

Who should be paged when a hard stop fires?

Page the on-call platform engineer only when refusals cluster, for example five or more tenants within an hour or many refusals for a single tenant, which usually signals a loop or a broken dependency. A single refusal is a customer success event, not an incident, and routing it to a page trains people to ignore pages.

Sources

Sources

  1. AI Agent Budget Enforcement: Dashboards Are Not Control
  2. AI Agent Budget Control: Enforce Hard Spend Limits - Cycles
  3. AI Agent Cost Control | Request-Path Budget Enforcement
  4. What is AI Token Pricing?
  5. Set Token Budgets for an AI Product
  6. The problems with relying on a single value metric to determine SaaS ...
  7. Stop Burning API Budget With 5 Patterns for LLM Token ...
  8. AI Unit Economics: Allocating Token Spend to the Teams ...
  9. How to model unit economics for an AI product (cost per ...
  10. AI Pricing Models: How to Price AI Products
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles