Canopy
← All posts
Engineering6 min read·May 4, 2026

How to give your AI agent a wallet safely.

An agent that can't pay is a research project. An agent that can pay anything is a liability. Here's how to land in between.

ATAtif · Founder & CEO
/ share

Most AI agents in production today can't move a dollar. They write drafts, summarize, query, classify — but the moment a real action requires a payment, a human takes over. That gap is where useful work currently leaks back to people.

Closing the gap means giving an agent a wallet. Which sounds simple, until you actually try it. Here are the three patterns we see most teams reach for first, what each one breaks, and the model we ended up at after watching it break.

Pattern 1: Hand the agent a seed phrase

Spin up a fresh wallet, drop the private key into the agent's environment, and let it sign whatever it likes. This works for a hackathon. It does not survive contact with reality.

Three problems, in order of how quickly they show up:

  • The key leaks. It ends up in a log line, a stack trace, a screenshot in a Slack channel, a context window of a model you didn't realize was being trained on it. There is no version of this where the key stays inside the agent.
  • The agent can spend everything in the wallet. A prompt-injection that flips the recipient address, a tool-use loop that misreads its own state, a single bad token in a planning step — any of these can drain the balance before you notice. The wallet has no opinion about what's allowed.
  • You can't revoke without moving funds. Killing the agent means sweeping the wallet to a new one and rotating every downstream reference. Fine for one agent. Painful for ten. Unworkable for a hundred.

The deeper issue is that there's no separation between holding funds and authorizing a payment. The agent is doing both, and only one of them is its job.

Pattern 2: Give the agent a credit card

Issue the agent a virtual card, set a limit, point it at checkout flows. This is the consumer answer, and for some use cases — checkout-flow automation, SaaS signups — it's a reasonable one.

What it doesn't help with:

  • APIs that don't take cards. A growing share of the data and compute an agent will want to call is paywalled over crypto rails (x402, MPP), not Stripe. A card buys you nothing on those.
  • Per-call economics. Cards are batch settlement. You get a statement, eventually. You don't get a receipt-per-call you can attribute to a specific reasoning step.
  • Granular policy. Most virtual-card products give you spend limits and merchant locks. They don't give you human approval on a $200 transaction, while auto-approving a $2 one. That distinction matters once an agent runs at any volume.

Cards have a place. They're a fallback rail for things only the card networks reach. They aren't the primary surface for a software-native agent.

Pattern 3: Build your own signer

Stand up a service that holds keys, exposes a sign() endpoint, and applies whatever policy you write. Now the agent makes an HTTP call instead of holding a key.

This is the right shape, and it's the one we picked. But the cost of doing it well is much higher than it looks at first:

  • Key management at production grade (HSMs, rotation, recovery, multi-region).
  • A policy engine that's fast enough to sit on the hot path of every payment.
  • An approvals queue, an audit log, a dashboard for finance.
  • Smart-wallet contracts on the chains you support, plus a paymaster so agents don't need to hold ETH for gas.
  • A way to attribute every signature back to the specific agent that asked for it.

You can build all of this. It's roughly six months and a team. We know because that's what we built.

The model we landed on

The shape we use, and the shape we recommend, is one shared treasury, per-agent wallets that sign on its behalf.

  • The org has one treasury — a smart wallet on Base, funded once, in USDC. Top-ups happen at the org level. This is where the money actually lives.
  • Each agent gets its own wallet, registered as a co-owner of the treasury. The agent's wallet doesn't hold funds. It only holds the right to sign on the treasury's behalf, within whatever policy you give it.
  • Every signature passes through a policy before it exists. Spend cap per rolling 24 hours, allowlist of which services it can pay, approval threshold for anything over a dollar amount. The policy decides; the wallet signs only what the policy permits.

The reason this shape works is that it cleanly separates the three things the previous patterns were tangling:

  1. Funds live in one place, not N places. Top-ups are a single action, not a fan-out.
  2. Authorization is per-agent. Each agent has its own signer, its own attribution trail, its own policy.
  3. Revocation is removing a co-owner. You don't move funds. You don't rotate keys. The treasury keeps doing its job; the agent simply loses the right to sign.

In code, the agent side looks like this:

import { Canopy } from "@canopy-ai/sdk";

const canopy = new Canopy({
  apiKey: process.env.CANOPY_API_KEY!,
  agentId: process.env.CANOPY_AGENT_ID!,
});

const result = await canopy.pay({
  to: "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97",
  amountUsd: 0.10,
});

canopy.pay() returns one of three results: allowed, pending_approval, or denied. Your agent can branch on each — it doesn't throw, because "denied" is often the correct outcome and the agent should be able to reason about it the same way it reasons about any other tool result.

There is no spendLimit argument. That's deliberate. The policy you set in the dashboard is the ceiling. Adding a code-level cap on top would be belt-and-suspenders that drifts out of sync the first time finance changes the limit.

What this gets you

Three things, in the order you'll notice them:

  • You can let the agent run. Not in a dry-run, not in a sandbox, not behind a babysitter. Real money, real calls, with the safety living one layer down from the agent's own decisions.
  • Finance gets a real audit trail. Every signature carries the agent that asked for it, the recipient, the amount, the policy decision, and the on-chain transaction. "Agent X spent $Y today" stops being a guess.
  • You can scale to ten agents without ten times the operational load. One treasury, one set of top-ups, N policies. Add an agent, attach a policy, hand it an API key. Remove an agent, remove a co-owner.

Once you have this in place, the question shifts from can my agent pay? to what should I let my agent pay for? — which is the more interesting question, and the one that turns out to drive everything else worth building.

We'll write that one next. For now: if you've been bouncing between hackathon-grade key handling and a six-month signer build, there's a third path. It takes about three minutes to set up.

npx create-canopy-agent to get started, or look at the docs for the full SDK surface.

/ share