Docs / Spending limits
How to set a spending limit for an AI agent
Short answer: set a per-transaction cap and a rolling daily cap in the wallet's own policy engine — not in your application code and never in the prompt. Every serious agent-wallet rail has native controls that can express at least part of this: Coinbase MPC account policies, Turnkey's pre-sign CEL engine, Openfort signer control, card-issuer spend limits. If your agents hold wallets on more than one rail, write the limit once as a declarative policy and compile it to each rail's native form.
Where the limit actually binds, per rail
| Rail | Native control | Guide |
|---|---|---|
| Coinbase (CDP / MPC wallets) | Account policy: reject any transaction above the cap, enforced inside Coinbase's MPC — a direct over-cap send is rejected by Coinbase itself | Coinbase guide |
| Turnkey | Pre-sign CEL policy on a delegated (non-root) user, evaluated in the TEE before any signature exists | Turnkey guide |
| Openfort | Backend signer control — the signer that won't sign an out-of-policy transaction, and can be destroyed to freeze | Openfort guide |
| Cards (Lithic Visa) | Per-transaction spend limit on the card; the network declines above it — plus a real-time auth gate | Cards guide |
Each rail speaks a different policy language and none of them can cap a competitor's rail. That's the gap a control plane fills: one policy, compiled to the strongest control each rail can express, with anything a rail can't express enforced fail-closed at the layer and labeled honestly in the enforceability matrix.
One policy for all of them
// amounts are base-unit integer strings (USDC has 6 decimals: "1000000" = 1 USDC)
import { CountersignClient } from "@countersign/sdk";
const cs = new CountersignClient({ baseUrl: "https://app.countersign.network", apiKey });
await cs.applyPolicy({ policy: {
schemaVersion: 1, asset: "USDC",
perTxCap: "1000000", // max per transaction
dailyCap: "5000000", // max per rolling 24 h, per agent
allowlist: ["0x1111…"], // optional: only these counterparties
approvalThreshold: "500000", // optional: above this → human approve/deny
}});
The daily cap is a rolling 24-hour window, not a midnight reset — an agent can't double-spend by straddling a day boundary. Amounts are asset-scoped and rail-denominated (crypto in base units, cards in cents).
What a spending limit alone doesn't cover
- Assets you forgot to cap. A USDC limit says nothing about DOGE. Countersign denies spends in any asset the policy doesn't govern — fail-closed, not fall-through.
- Where the money goes. Caps bound how much; venue and listing rules (policy schema v2) bound where and on what.
- Terms the agent negotiates. An agent inside its cap can still agree to bad terms — bid ceilings, walk-aways, and pre-authorised envelopes (schema v3) govern the negotiation itself.
- The day it all goes wrong. A limit slows a runaway agent; a kill switch stops it. Keep both.
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