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.

Honest scope: everything here is testnet-only — no mainnet, no custody, no PII. The hosted sandbox seeds a mock three-backend fleet so you can exercise policy, guard, freeze, and ledger end-to-end; the vendor enforcement described on this page was proven live on real testnet backends. Mainnet follows a third-party security audit.

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