# An autonomous agent with a credit card has no ceiling

> Usage billing means the agent decides how much to spend and you find out afterwards. Prepaid credit makes the ceiling a balance instead of a promise.

Canonical HTML version: https://mcpbelt.com/problems/cap-what-an-agent-can-spend

## The problem

You gave the agent a key so it could get on with the work without asking you every time. That key bills by usage, which means the agent now decides how much money leaves the account, and nothing in the arrangement says how much is too much.

A loop that goes wrong and retries three hundred times is not a rare event, it is Tuesday. The retry is usually the correct behaviour: a call timed out, so the agent tries again, and it has no way to know that the first one succeeded and was paid for. Multiply that by a file that gets re-read on every turn because nobody kept the handle, and the bill is not a bug in one place, it is arithmetic.

The failure is not that money was spent. It is that the spending had no upper bound at the moment the agent made the decision, and by the time anyone could see the number, it had already happened.

## Why it fails locally

Provider spend limits do not stop anything. They are computed from usage that is aggregated after the fact, they fire hours later, and what they produce is an email. **An alarm is not a brake.** By the time the threshold is evaluated, the three hundred calls are done and billed.

Wrapping the calls yourself and counting them is better and still not enough, because a counter can only tell you what you already spent. To stop a call before it happens you need the price of that specific call before making it, and the price depends on the size of the input, which the wrapper does not know until it has read the file.

And the whole scheme rests on the agent not holding the key directly. The moment it does, every guard you wrote is a suggestion: the agent can call the provider without going through your wrapper, because that is exactly what having a key means.

## The code

`account` is free and is never charged. Ask it what a job will cost before running it, and read the balance that is the actual ceiling.

```
account()
  -> credits_available_eur, top_up_url

account(estimate_for="read")
  -> estimate_eur per mode, unit: page

read(key="<key>", mode="balanced")
  -> handle, engine, cost_eur

# when the balance does not cover the job, nothing runs:
#   error credits_exhausted, carrying what it costs, what is
#   left, and a top-up link to hand to whoever pays.
#   Top up, call the same tool with the same arguments,
#   and you are not charged twice.
```

## What it costs

Credit is prepaid. There is no subscription and no per-call invoice: the account holds a balance, the balance is the ceiling, and an agent cannot spend past it because there is nothing there to spend. You start with 0.10 EUR of trial credit and no card, and top-ups start at 5 EUR.

Before committing to a job, the amount it could cost is set aside, and **the charge never exceeds what was set aside**. A bill above the estimate is not something you have to watch for, because it cannot be produced. If the work fails, nothing is charged at all, and the same request sent twice is charged once. Checking any of this is free: upload, result, cancel, account are never billed, at any volume.

`read` is 0.007 EUR per page in `balanced` mode and `listen` is 0.005 EUR per minute, and `account` will tell the agent both, per mode, before it decides. Out of credit, the tool refuses and says so in a message written to be repeated to the person paying. It does not quietly buy a cheaper, worse result to stay inside the budget.

## What this does not do

- The ceiling is the balance, and there is nothing finer. No per-tool budget, no daily cap, no spend alerts: you control the exposure by how much credit you put on the account.
- Credit is not refunded on request. It comes back only when a queued job is cancelled before an engine has started on it.
- A job already running cannot be capped mid-flight. It was priced and reserved before it started, and that reservation is the limit.
- Prices are per page and per minute of the real file, counted from the file itself rather than guessed from its size. An estimate given before the upload is an estimate.
