Originally published on dyordo.com.
Last month I gave a research agent an API key with a shared limit and pointed it at a competitor-monitoring job. The job was small: at most 50 calls a day, each costing a fraction of a cent.
On the third night the bill said $37 for one day.
A subtask had fallen into an error loop. Call fails, agent tweaks a parameter, retries, fails again. My 50-call cap didn't stop it, because each endpoint had its own quota and my limit didn't cover all of them.
$37 is not a disaster. But it showed me I had never designed how my agents spend money. I had given each one a card that works, not an account with a budget.
Here is what I do now. None of it needs new infrastructure.
Split the budget by purpose
One monthly number per agent is too blunt. I use three buckets:
- Exploration: $5 to $20 a week for trying APIs. When it's gone, the agent waits until next week.
- Project: a fixed amount loaded for one task, like $10 to scrape pricing for a list of competitors. Unspent money comes back when the task ends.
- Escalation: anything above the threshold needs my approval. The agent asks. It doesn't just spend.
Set the limit before the agent starts. Trimming after it overspends teaches it nothing.
Allow-list, don't block-list
I used to allow everything and block bad services as they showed up. Every new service was a new risk, and I was always behind.
Now nothing is allowed by default:
- Start with services you already trust, like OpenAI, Anthropic and your existing data sources.
- Add new ones one at a time, after checking them.
- If an agent wants a new service, it requests it.
The allow-list also carries numbers. I cap spend per call and per day. A rule like "max $5 a day, 200 calls a day" would have killed my retry loop in round three.
Cap single transactions and watch for anomalies
A healthy total says nothing about one transaction. Every agent account I run has a hard rule: any single charge over $2 goes to a human.
On top of that, an unusual call rate, failure rate or spend speed freezes the account. The cheapest version is one condition: the agent can spend only if budget > 0 and no anomaly flag is set.
Give the agent a visible owner
When an agent calls third-party services, it should say who it works for, for example a handle like yourname.cloudflare.pay, instead of showing up as an anonymous account.
Merchants are more likely to hand out trial credits to an agent with a known owner, and more likely to email you than ban you when something looks off. Same reason people trust yourname.com and not a bare IP and port.
Three things to do this week
- List every paid service your agents call and what each costs per month. The total is usually higher than you think.
- Give each main agent one budget number, then enforce it in code, not in a note.
- One agent, one API key. Separate bills, separate limits, and you can shut one down without touching the others.
This takes under an hour.
Hard limits buy you freedom
With a $10 cap, I can let an agent try 50 services without watching any of them. With a $1,000 account and no cap, I check the bill at 2 a.m.
That's why I like Cloudflare's two-tier wallet design: it turns "do I trust this agent?" into "what's the cap?"
On a normal day, a well-limited agent system shows the occasional "budget exhausted, paused" notice. You top it up or adjust it and move on. You don't wake up and open the bill first.
Prices and policies change. Check official docs before you buy anything.
Top comments (1)
Your anomaly rule is the one that would have caught this, and it is the one rule in the post with no threshold attached. A daily cap, in dollars or in calls, only stops the loop once it has spent whatever you set. The failure rate you already mention is the shape of the thing. Worth pinning a trip condition to it: 3 consecutive failures on the same endpoint, counted per endpoint rather than per call signature, because your own account says the agent tweaked a parameter between attempts. Key the counter on the parameters and every retry is a new key, so it never reaches 3.
Worth checking the billing side too, because it decides whether the breaker counts failures or responses. If any of those calls reach a model API rather than a per-endpoint data quota, a call that fails for the agent can still bill: a 200 carrying an error in the body is charged for the prompt tokens, and a client timeout after the server has already generated output is charged in full with nothing delivered. So a retry loop can burn real money while the success counter sits at zero, which is how 50 expected calls a day arrives as a $37 bill.
One gap in the escalation rule as written. "The agent asks" puts the approval inside the thing that malfunctioned. The loop that broke your 50-call cap was agent-side, so it would have been equally happy to stop asking. Holding the threshold at the key or proxy layer keeps that decision outside the loop.
On "one agent, one API key", does the env isolation match it? If the agent shells out to tools or skills that inherit the parent environment, every key in that shell is reachable from the subprocess, and the per-agent boundary is a naming convention rather than a limit.