Giving an AI agent a card without giving it your wallet: the freeze, approve, refreeze pattern
"Renew my Vercel plan." "Top up the OpenAI API balance before it hits zero." "Buy 200 more Midjourney credits for this task." These are the most boring bills there are, and an AI agent with tools can already open the rig
"Renew my Vercel plan." "Top up the OpenAI API balance before it hits zero." "Buy 200 more Midjourney credits for this task." These are the most boring bills there are, and an AI agent with tools can already open the right page and press the button. What it lacks is a way to pay that you'd actually be comfortable handing over.
Disclosure: we're Guarapay and we built a card for exactly this, so we have an opinion. But the pattern below doesn't depend on our product, and it's worth knowing before you give any agent payment access.
Why "just give it the card" is a bad idea
The naive version is to paste a card number into the agent's context or a config file. That breaks in three ways:
- The secret leaks. Anything in the context can end up in logs, traces, a shared transcript, or a prompt-injected reply to a malicious page. A card number is a long-lived secret, and you can't rotate it as easily as an API key.
- There's no ceiling. The agent can spend whatever your main card allows. One loop, one misread price, one fake checkout and the damage is bounded only by your credit limit.
- There's no moment of consent. You find out about the purchase from your bank statement, not before it happens.
Spending caps on a normal card help with the second point, but not the other two.
The pattern: freeze â approve â refreeze
Here is what works better. Give the agent a separate card with its own balance, and keep that card frozen by default. Then, for every purchase:
- The agent asks. It sends a purchase request: which shop, and the most it may cost (for example, Vercel, up to $20).
- A rule decides. If the amount fits inside the daily and monthly limits you set, it's approved at once. If it doesn't, you get a prompt on your phone ("Allow $120 to AWS?") and the request waits for your tap.
- The card opens briefly. After approval it unfreezes for a short window, 15 minutes in our case, so the agent can complete the checkout.
- The card freezes again. Right after the payment, or when the window ends, whichever comes first.
- You get a push with the real merchant and amount as it happens.
So the card has no standing spending power. Between purchases nothing can be charged to it, even if the number leaked somewhere.
Keep the card number out of the agent's world
The second half of the design matters just as much: the agent should never see the full card number or CVV.
That sounds like it would make paying impossible, but most of what agents pay for is recurring, online, on sites where a card is already saved: hosting, API credits, SaaS seats, domains. So the flow becomes:
- You save the card at the service once, by hand.
- The agent asks for approval and presses "Pay" on a page where the card is already on file.
The agent knows the last 4 digits so it can pick the right saved card, and that's it. If the card has to be added to a new site, the agent can send you a link that opens the details in your own app. It never receives the digits itself.
What this looks like over MCP
We expose this as an MCP server, so any assistant that supports custom connectors (ChatGPT, Claude including Claude Code, Cursor) can use it. The parts that matter are what the tool list doesn't include:
-
get_agent_card: balance, limits, last 4 digits. -
request_purchase: merchant plus maximum amount. Returns approved, or waiting for the owner. -
get_purchase: check whether the owner allowed it. -
cancel_purchase: the agent changed its mind, so the card refreezes right away. -
card_details_link: a link for the human to see the details in their app.
What isn't in the list: no unfreeze, no way to change limits, no way to read the card number or CVV, no way to move money out. Those powers stay with the person, in the app. The agent can read the limits but can't touch them.
Even if a prompt injection fully takes over the agent, the worst it can do is make requests inside a limit you chose, at merchants you'll see in a push, using money you put on that one card.
Things to decide before you turn it on
- Limits that match the job. A daily limit a bit above your largest regular bill and a monthly limit around your normal monthly spend. Anything unusual should need your tap.
- A small balance. Top up the agent card for the month, not for the year. The balance is the final cap.
- Where it's saved. Only save the card at services you actually want the agent to pay. Otherwise "pay only where the card is saved" means nothing.
- A kill switch. You need one tap that freezes the card and makes every new request fail. Test it once.
- Where it doesn't fit. In-store and NFC payments, gambling, crypto exchanges and captcha-heavy checkouts are out of scope for an agent anyway.
Try it, or build your own
If you're building agent tooling yourself, the pattern above is a good baseline: frozen by default, a request with a maximum amount, an owner-side rule plus a human prompt above it, a short unfreeze window, no card data in the model's context, and no tool that lets the agent raise its own permissions.
If you'd rather not build it, here's how ours works: Guarapay card for AI agents. You add one connector, sign in, issue the card, top it up with USDT or a bank card, and set the limits in the app.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes â full credit and traffic to the original publisher.