Rightshold™ Sign up

Answers · agent payments

How do I test my AI agent's spending limits before I give it real money?

Last updated

TL;DR: Test every limit from the outside, the way a misbehaving agent would hit it, using fake money on each rail. For cards, Stripe Issuing has a sandbox: issue a virtual card with spending_controls, fund the test Issuing balance, and use the test helpers to create authorizations, increment them and create force captures, so you see what gets declined and what slips through. For x402, point the agent at Base Sepolia (eip155:84532) and fund its wallet with test USDC from Circle's faucet or the CDP faucet. For the policy layer, open a Rightshold sandbox account (sign up with sandbox: true for rs_test_ keys) and run set_spend_policy and authorize_spend against your agent's real purchase shapes. Write the cases down as a test matrix: under the cap, exactly at it, one cent over, a run of small purchases that crosses the daily cap, a merchant or category outside the allowlist, a different currency, a retried purchase, purchases right after a pause or revoke, and purchases across the reset time. Every case needs an expected allow or deny, and one case that should allow, so you know the test can fail.

What should I check, step by step?

1. List every way the agent can spend: card numbers, x402 or other wallet payments, paid API keys, and tools that buy on its behalf. Each rail gets its own test, because each enforces limits in a different place.

  1. Cards: in a Stripe sandbox, issue a virtual card with the same spending_controls you plan for production (for example a per_authorization limit, a daily limit and allowed_categories). Fund the test Issuing balance first; test funds aren't real and only work for simulated purchases.
  2. Create test authorizations with POST /v1/test_helpers/issuing/authorizations, setting amount and merchant_data.category to match each case. Check which are approved and which are declined, and read the decline reason on the authorization.
  3. Test what limits can't stop: increment an approved authorization (POST /v1/test_helpers/issuing/authorizations/{id}/increment) and create a force capture (POST /v1/test_helpers/issuing/transactions/create_force_capture). Stripe's spending-controls docs warn that tips and fees posted later can push spend past a limit, so reconcile captured transactions, not just authorizations.
  4. x402: run the agent with a testnet client (the CDP x402 client's development environment uses Base Sepolia) and fund the wallet with test USDC from faucet.circle.com or the CDP faucet. Have a test server quote prices under, at and over your per-request cap, and an upto price whose ceiling is over the cap.
  5. Policy layer: sign up for a Rightshold sandbox account (POST /v1/accounts/signup with sandbox: true gives rs_test_ keys), issue a test agent credential, set_spend_policy with your real caps, then call authorize_spend for each case and assert the decision and reasons.
  6. Include the edge cases: an amount exactly at the cap (should allow), one minor unit over (should deny), several small purchases that cross daily_max_minor, a subdomain or look-alike merchant, a missing category, and a different currency. Each needs an expected answer written down before you run it.
  7. Test retries and resets: retry a purchase and check you don't approve or pay it twice; pause or revoke mid-run and check the next purchase is refused; run cases just before and after the daily reset (Rightshold's daily total resets at 00:00 UTC; Stripe's date-based intervals also start at midnight UTC).
  8. Keep one case that must allow and one that must deny in CI, so a test that always passes or always fails gets noticed.
  9. Move to live money in steps: small caps first, alerts on, and the same matrix re-run with live keys at amounts you can afford to lose.

Why should I test an AI agent's spending limits with test cards and testnet USDC first?

Spend limits fail quietly. A cap set in the wrong currency unit (dollars instead of cents), an allowlist that is empty and so allows everything, or a retry that pays twice all look fine until real money moves. The only way to know a limit works is to aim purchases at it and watch it refuse them.

What test cases should I run against an AI agent's spending limits?

Write the matrix as data: purchase amount in minor units, currency, merchant domain or merchant category, time, and the expected decision and reason. Run the same rows against every rail the agent can use.

What can get past a virtual card's spending limit when an AI agent pays?

Stripe says spending controls run before real-time authorizations and can decline a purchase before your webhook sees it, and that later tips and fees can push spending past a limit. Test helpers let you simulate both: increment an approved authorization, and create a force capture that never had an authorization.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “In my Rightshold sandbox account, check this test purchase against my agent's spending policy: $25.01 at api.example.com in the data category, where the per-transaction cap is $25. I expect a deny with over_per_transaction_cap.”

One-click setup

{
  "tool": "authorize_spend",
  "arguments": {
    "credential_id": "crd_YOUR_TEST_AGENT_CREDENTIAL",
    "amount_minor": 2501,
    "currency": "USD",
    "merchant_domain": "api.example.com",
    "category": "data",
    "reference": "test-matrix-row-3"
  }
}

Rightshold records spending policies and signed allow or deny decisions. It never holds or moves money and doesn't run your Stripe sandbox, wallet or test suite. Card networks, Stripe and x402 facilitators enforce their own rules, so a passing Rightshold test doesn't prove those rails will decline the same purchase. Test each rail. Not financial advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'