Docs / Stop overspending
How to stop an AI agent from overspending
Short answer: don't rely on the agent's judgment — put four controls outside the model. (1) A hard spend cap enforced by the wallet itself, so even a compromised or looping agent can't exceed it. (2) A pre-flight guard the agent calls before every spend. (3) An approval threshold that routes big spends to a human. (4) A kill switch that stops the whole fleet in one action. An agent retrying a $0.06 API call 1,000 times a minute burns ~$86,000 in a day — the controls have to work even when the agent is the problem.
1. Put the cap where the money moves, not in the prompt
A budget in the system prompt is a suggestion; a loop, a jailbreak, or a plain bug walks straight past it. The cap has to bind at the wallet: Coinbase MPC account policies, Turnkey pre-sign CEL policy, Openfort signer control, or a card's spend limits. Countersign compiles one declarative policy into each rail's native controls, so the per-transaction and daily caps hold even for a spend that never touches Countersign:
await cs.applyPolicy({ policy: {
schemaVersion: 1, asset: "USDC",
perTxCap: "1000000", // 1 USDC per transaction (base units)
dailyCap: "5000000", // 5 USDC per rolling 24 h
}});
2. Gate every spend pre-flight
Before any payment — an on-chain send, an x402 machine-payment, an AP2 mandate — the agent calls one guard. Anything the policy can't affirmatively allow is denied: unknown asset, unlisted venue, frozen fleet, no response. Fail-closed, so "the guard was down" never means "the money moved."
const d = await cs.evaluate({ agentId, amount: "400000", asset: "USDC", venue: "base-sepolia" });
if (d.outcome !== "allow") throw new Error(d.reason);
3. Route big spends to a human
Set an approvalThreshold and anything above it returns needs_approval with a hold — the spend waits for an explicit human approve/deny. A freeze overrides a pending approval, so the escalation path can never leak a payment out.
4. Keep a kill switch armed — across every wallet
The failure mode that hurts is fleet-wide: several agents, several backends. No single vendor can stop a competitor's rail, so "stop everything" needs a layer above the wallets. One POST /freeze stops Coinbase + Turnkey + Openfort + a Lithic Visa card together, each stop confirmed, in 432–697 ms — watch it run.
5. Audit what actually happened
Every attempt — allowed, denied, frozen — lands in an append-only, hash-chained, Ed25519-signed ledger that anyone can verify offline. Velocity and blocked-burst breakers watch it and auto-freeze on runaway patterns, which is exactly the retry-loop scenario above.
Try it in 60 seconds — no account, no human
Self-serve key, an isolated sandbox tenant with a three-backend demo fleet, testnet only.
Get a free key → Watch the freeze GitHub