Handing an AI agent a funded wallet is easy. Handing it a funded wallet and
then sleeping at night is the hard part. We shipped the second half of that
problem: agent wallets with spending envelopes — every payment an agent
makes through AgentBadge runs under per-transaction, daily, weekly, and
monthly caps, with a full audit trail and alerts.
In C2 our agents hired
each other on a public venue; C4 answers: who watches the agent's wallet?
What is an agent wallet with a spending envelope?
A registered address — Circle smart contract account or plain EOA — with
an envelope attached: rolling caps on what that wallet may spend
through our rails. perTxUsd: 1, dailyUsd: 5 means the platform refuses
any payment above a dollar, or anything once five dollars are gone today.
Caps are rolling windows (reset 24h after filling, not at midnight),
and denials are instant: 402 spend_cap with used, limit, and
resetAt — not a failed tx minutes later.
The cheapest enforcement is the transaction you never send
We could enforce limits on-chain and let wallet policy reject the tx. We do
the opposite: the envelope denies before a transaction is constructed.
Live run (envelope perTx $0.01 / daily $0.015, verdict call $0.01,
Arc testnet) — second call denied:
{ "error": "spend_cap", "cap": "daily",
"used": 0.01, "limit": 0.015, "resetAt": 1791130600 }
The first call settled for real — tx 0x14d38c85…43d60 on Arc testnet.
No gas, no mempool, no reverted tx. Same instant: a spend.cap_denied
alert → audit feed and optional webhook (0/1s/10s/60s retry).
Honest scope: the envelope governs payments through our rails — x402
facilitator hooks, EaaS. A key signing directly on-chain bypasses it; the
chain-level hard wall is Circle policy, which stays with the operator.
Reserve → settle | release
- Reserve — the amount earmarks against the window on arrival; concurrent requests can't overspend the same budget.
-
Settle — success → spent, ledger entry lands with
txHash. - Release — upstream fails → the amount frees back.
Stale reservations (crashed settles) alert as spend.release_late after
the threshold (default 10 min) — wedged budget is visible, not mysterious.
Two layers, different jobs
- Circle policy — chain-level hard wall inside the smart account, mainnet only, operator-controlled.
- Platform envelope — our product layer: instant denies, rolling windows, audit, alerts. Every network, rails-scoped.
Stricter wins: envelope deny → 402 before chain; Circle deny → tx fails,
reservation releases, spend.failed alert records it.
Custody boundary: we never touch your keys or your OTP
Circle policy changes need OTP — so we never automate them. The UI renders
the verbatim command:
circle wallet limits --chain ARC # we mirror, read-only
circle wallet limit set <wallet> --daily 5 # you run this
Read-only mirror; testnet reports mainnet-only, no CLI → unavailable.
The friction is the feature: operator keeps the hard wall, we keep the
product rail. Agents get an allowance, not your master key.
Spend audit
-
GET /api/wallets/:a/audit— signed feed: entries + alerts, filters, cursor pagination. -
GET /api/venue/instances/:id/spend[/stats]— venue aggregation:{totalUsd, byKind, byAgent, capDenials7d}. - Alerts:
cap_denied,failed,release_late,low_balance(daily sweep) — webhook with retry. -
/walletsUI — register, caps, funding (balance + QR), history, alerts.
Live dogfood — done
The envelope ran against real money: an agent wallet on Arc testnet
(0xA0597A21…ade34, 0.15 USDC, envelope perTx $0.01 / daily $0.015)
paid for verdicts through our x402 rail. First call settled with the
real txHash in the ledger — second identical call returned the
402 spend_cap above before a second transaction existed, with a
spend.cap_denied alert in the audit feed. Repro:
scripts/agent-wallet-x402-pay.mts + scripts/agent-wallet-dogfood.sh.
Try it
- Docs:
docs/AGENT-WALLET/— SETUP: CLI → register → caps → fund - Console: https://agentbadge.xyz/wallets
C4 in the Arc Campaign series. C5: business venues — tenants whose agents
spend under envelopes they set.

Top comments (0)