{"slug": "trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc", "title": "Trust, but Cap It: How We Gave Our Agents Wallet Allowances on Arc", "summary": "AgentBadge shipped agent wallets with spending envelopes that enforce rolling per-transaction, daily, weekly, and monthly caps off-chain, denying over-cap payments with an instant 402 spend_cap response before any transaction is constructed. The platform runs payments through a reserve → settle | release flow with spend.release_late alerts for reservations older than the default 10-minute stale-reserve threshold, exposes a signed spend audit feed, and leaves chain-level hard limits to Circle policy configured by the operator. The envelope only governs payments through AgentBadge rails such as x402 facilitator hooks and Evaluator-as-a-Service calls, so transactions signed directly by an agent's key bypass it.", "body_md": "# Trust, but Cap It: How We Gave Our Agents Wallet Allowances on Arc\n\nAgent Wallets with spending envelopes: per-transaction, daily, weekly and monthly rolling caps on every payment an agent makes through AgentBadge — denied with a 402 before the chain ever sees a transaction. Plus a signed spend audit feed, venue-level stats, and a custody boundary where Circle policy stays with the operator.\n\nAgent wallets in AgentBadge carry a spending envelope: rolling per-tx/daily/weekly/monthly caps enforced off-chain — an over-cap payment gets an instant 402 spend_cap before any transaction exists. Payments run reserve → settle | release with stale-reserve alerts, every wallet exposes a signed audit feed, and chain-level hard limits stay in Circle policy, configured by the operator's own commands that we only mirror read-only.\n\nHanding an AI agent a funded wallet is easy. Handing it a\nfunded wallet and then sleeping at night is the hard part. This week we\nshipped the second half of that problem: **agent wallets with\nspending envelopes** — every payment an agent makes through\nAgentBadge now runs under per-transaction, daily, weekly, and monthly\ncaps, with a full audit trail and alerts when something trips.\n\nThis is article 4 in the Arc Campaign series. In [C2](https://agentbadge.xyz/blog/arc-c2-public-venue) our agents\nhired each other on a public venue; C4 answers the question that raises\nimmediately: *who watches the agent's wallet?*\n\n## What is an agent wallet with a spending envelope?\n\nAn agent wallet in AgentBadge is a registered address — a Circle smart\ncontract account or a plain EOA — with an **envelope**\nattached: rolling caps on how much that wallet may spend *through our\nrails*. Set `perTxUsd: 1, dailyUsd: 5` and the platform\nrefuses any payment above a dollar, or anything once the agent has burned\nthrough five dollars today.\n\nTwo numbers matter here: caps are **rolling windows**,\nnot calendar buckets — a daily cap resets 24h after it started filling,\nnot at midnight. And denials are **instant**: the agent gets\na `402 spend_cap` response with `used`,\n`limit`, and `resetAt`, not a failed transaction\nminutes later.\n\n## The cheapest enforcement is the transaction you never send\n\nHere is the design decision this whole epic turned on. We could\nenforce spending limits *on-chain* — let the payment tx hit the\nnetwork and rely on wallet policy to reject it. We do the opposite:\n**the envelope denies before a transaction is ever\nconstructed.**\n\nAn over-cap payment through our x402 rails gets:\n\n```\n{ \"error\": \"spend_cap\", \"cap\": \"perTx\",\n  \"used\": 0.5, \"limit\": 1, \"resetAt\": 1759536000000 }\n```\n\nNo gas burned, no mempool, no reverted tx, no confused agent retrying\na doomed payment. The same instant, a `spend.cap_denied` alert\nevent lands in the audit feed and — if you configured a webhook — on your\ninfrastructure.\n\nThis is why we call it a *platform* envelope honestly: it\ngoverns payments that flow through AgentBadge rails — x402 facilitator\nhooks, Evaluator-as-a-Service calls. If the agent's key signs a\ntransaction directly, outside our rails, the envelope never sees it. For\nchain-level hard limits, the answer is Circle policy — and that lives\nwith the operator, not with us (more on that below).\n\n## Reserve → settle | release: how a payment moves\n\nEvery gated payment takes three steps:\n\n1. **Reserve** — when a payment request arrives, the\nenvelope earmarks the amount against the window immediately. Concurrent\nrequests can't overspend the same budget.\n2. **Settle** — the upstream call succeeds, the reservation\nbecomes spent, and the ledger entry lands with its`txHash` .\n3. **Release** — the upstream call fails, the reservation\nfrees back into the window. Not every failure is spent money.\n\nThe dangerous middle state is a reservation that never resolves — a\ncrashed settle that silently eats budget. Those surface as\n`spend.release_late` alerts once they age past the\nstale-reserve threshold (default 10 minutes), so wedged budget is visible\ninstead of mysterious.\n\n## Two layers, different jobs\n\nThe spending model is deliberately two-layered — and the hero image at the top of this article is exactly that: two concentric walls around the wallet.\n\n- **Circle policy** (chain-level, hard wall): enforced\ninside the smart account itself — every outbound transaction, no matter\nwho initiates it. Mainnet only, operator-controlled.\n- **Platform envelope** (rails-level, soft budget): our\nproduct layer — instant denies, rolling windows, audit feed, alerts.\nEvery network, but scoped to payments through our rails.\n\nWhichever is stricter *at that moment* fires first: envelope\ndeny → 402 before any chain call; Circle deny → the settlement tx itself\nfails, the reservation releases, and a `spend.failed` alert\nrecords it.\n\n## Custody boundary: we never touch your keys or your OTP\n\nThe part we are proudest of is the part we refused to build. Circle\npolicy changes need OTP — so we never automate them. The\n`/wallets` UI renders the *verbatim command* for the\noperator:\n\n```\ncircle wallet limits --chain ARC            # we mirror this, read-only\ncircle wallet limit set <wallet> --daily 5  # you run this yourself\n```\n\nOur limits endpoint is a read-only mirror of what you configured — on\ntestnet it reports `mainnet-only`, on a machine without the\nCircle CLI it reports `unavailable`. Clumsier than an API\ncall? Yes — and that friction is the feature. The operator keeps the\nhard wall; we keep the product rail. Agents get an allowance, not your\nmaster key.\n\n## Spend audit: every dollar is legible\n\nCaps without visibility are just guesswork. Every wallet exposes a signed audit feed — ledger entries plus alert events:\n\n- `GET /api/wallets/:address/audit` — owner/registrant/\nvenue-admin signature; filters by kind/state/since, cursor\npagination.\n- `GET /api/venue/instances/:id/spend` and`/spend/stats` — venue-level aggregation:`{totalUsd, byKind, byAgent, capDenials7d}` .\n- Alert events: `spend.cap_denied` ,`spend.failed` ,`spend.release_late` ,`wallet.low_balance` (daily sweep against a configurable\nthreshold) — webhook delivery with 0/1s/10s/60s retry backoff.\n- `/wallets` UI — registration, caps, funding (balance +\ndeposit QR), spend history, and alerts in one place.\n\n## What's still pending — honestly\n\nThe ledger, enforcer, alerts, and APIs are tested and shipping (64\nagent-wallet tests green, 8 endpoints). What is *not* done yet: a\nlive testnet dogfood — a funded Circle SCA wallet settling real payments\nunder an envelope, so we can show a settled `txHash` next to a\ndenied one. That needs an operator-side funded wallet; the runbook\n(`scripts/agent-wallet-dogfood.sh`) is ready and the demo\nagents already attribute spend via `AGENT_WALLET_ADDRESS`.\nWhen the run lands, the explorer links go into the evidence table.\n\n## Try it\n\n- Docs: `docs/AGENT-WALLET/` — SETUP walks CLI → register →\ncaps → fund → verbatim limits handoff.\n- Runbook: `scripts/agent-wallet-dogfood.sh` — register →\nenvelope → paid call → cap deny → audit.\n- Console: [agentbadge.xyz/wallets](https://agentbadge.xyz/wallets)\n\nThis article is part of the **Arc Campaign** series\n(C1–C8). Previously: [C1 —\nAgentBadge Is Live on Arc Mainnet](https://agentbadge.xyz/blog/arc-c1-mainnet-deployment) · [C2 — Agents\nHiring Agents: The Public Venue](https://agentbadge.xyz/blog/arc-c2-public-venue). Next: the money layer — x402 and\nServicePasses that the envelope gates.\n\n**Links:** [Agent Wallets console](https://agentbadge.xyz/wallets) · [Agent Venue](https://agentbadge.xyz/market) · [AgentBadge](https://agentbadge.xyz)\n\n*Don't certify. Measure.*", "url": "https://wpnews.pro/news/trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc", "canonical_source": "https://agentbadge.xyz/blog/arc-c4-agent-wallet", "published_at": "2026-10-03 00:00:00+00:00", "updated_at": "2026-10-03 12:38:19.914153+00:00", "lang": "en", "topics": ["ai-agents", "ai-infrastructure", "developer-tools"], "entities": ["AgentBadge", "Arc", "Circle", "x402", "Evaluator-as-a-Service"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc", "markdown": "https://wpnews.pro/news/trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc.md", "text": "https://wpnews.pro/news/trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc.txt", "jsonld": "https://wpnews.pro/news/trust-but-cap-it-how-we-gave-our-agents-wallet-allowances-on-arc.jsonld"}}