GVNR

How to stop an AI agent spending too much money

Most advice on this is a list of dashboards to watch. Watching is not stopping. This is about the controls that actually refuse an action, in the order they are worth adding, and what each one misses.

You can do the first four with no tool at all, and most of the value is there. The last two need something sitting in front of the agent.

1. Turn on the provider's own cap first

It is free, it needs no code, and it is the only control that works when everything else you build has a bug in it. Anthropic ships usage limits at organisation, workspace and member level; OpenAI has hard and soft monthly caps in billing. Claude Code takes a per-session ceiling directly:

claude --max-budget-usd 5

Where it fails: a monthly cap is a cliff, not a brake. You find out you were wrong at the end of the month, and by then the money is gone. It also cannot tell a useful $200 from a wasted $200.

2. Give each agent its own budget, in dollars

Token counts are the wrong unit. They are not comparable across models, and a cached session re-reads its whole context every turn, so raw token sums balloon into the billions while costing very little.

Weight by price instead. One effective token is one input-token of cost at that model's price, so output at roughly 5x input, cache writes at about 1.25x, cache reads at about 0.1x. Then a dollar cap converts with a single multiply, and $20 means $20 whether the agent is on a frontier model or a small one.

Where it fails: a per-session cap is still a total. An agent that burns the lot in ninety seconds and an agent that works all afternoon look identical to it.

3. Cap the rate, not just the total

This is the one almost nobody ships, and it is where the money actually goes. A total only notices once it is spent. A rate notices while it is happening.

Three rates are worth watching, and you can compute all of them from a sliding window of request outcomes:

SignalWhat it catchesSane starting point
Dollars per minute, per agentA single agent that has gone wrongOrdinary work sits around $0.10 to $0.25 a minute, so $2 leaves normal sessions alone
Dollars per minute, across the fleetMany agents each looking individually fine$10
New agents per minuteAn orchestrator spawning orchestrators. A team that starts over an hour is a choice; eight inside a minute is a bug8
Errors per minuteA retry storm. A rate-limited call fails cheaply, the retry after it does not6

Gate on the derivative, not the total. In pseudocode, that is the whole idea:

window = requests in the last 60s
spend_per_min  = sum(cost(r) for r in window)
errors_per_min = count(r for r in window if r.failed)
new_agents     = count(distinct new agent ids in window)

if spend_per_min > burn_limit: ask the human
if errors_per_min > retry_limit: ask the human
if new_agents > fanout_limit: ask the human

Make it ask once, not block. An overnight run that dies at 2am has cost you the night. One that pauses and waits has cost you nothing.

4. Catch the loop

Repeated work is cheap per call and expensive in aggregate. Hash the action and its arguments, keep a short streak counter per agent, and treat a streak past three or four as a loop rather than progress. This is behaviour, not cost, so it fires before the budget notices.

5. Gate what it may DO, not only what it may spend

Here is the part a spend cap structurally cannot do. The actions that hurt most are nearly free:

A budget check will wave every one of those through on a full budget. You need a separate check that runs on capability regardless of spend, with three outcomes rather than two: refuse the reckless ones outright, and make the irreversible ones stop and ask.

Where the agent supports it, do this before the tool runs rather than at the API. Claude Code exposes a PreToolUse hook for exactly this, and a refused action there never executes at all.

Be honest about the limit: pattern rules are a guard, not a sandbox. Published research found most open-source agent guards could be defeated by shell obfuscation. If your threat model is an adversary rather than an accident, the answer is process or container isolation with no credentials in reach, and a pattern guard on top of it.

6. Keep a record you can defend

Once an agent acts for a person, "what did it do" becomes a question someone else asks you. A log is not enough, because anyone with write access can revise it. Chain each record to the one before it so an edit visibly breaks the chain, and record the fields an audit actually wants: the human it acted for, the tool, the model that answered, and the rule that decided.

What not to bother with

If you would rather not build it

GVNR is the six controls above in one local process, free and self-hosted. Full disclosure: we make it.

npx --yes enforcer-governor start

Point an agent at it with OPENAI_BASE_URL or ANTHROPIC_BASE_URL, or install the Claude Code hook with npx --yes enforcer-governor install-hook. It runs on your machine and sends nothing to us. The quickstart takes about a minute, and how it compares is honest about the three cases where a gateway or a provider cap is the better answer.

Nothing above requires it. Points 1 to 4 are worth doing this afternoon whatever you use.

Powered by Instruxi. Verified against the GVNR source on 15 September 2026. Free and open, runs on your own machine, nothing is sent to Instruxi. Related: GVNR · Stop an agent overspending · Block dangerous commands · Quickstart · Configure · Receipts · How it compares · Live demo · Enforcer. Enforcer, the identity and authorization service, is at enforcer.instruxi.dev.