Primitive/wallet6 min read

Introducing /wallet: a per-agent crypto wallet with a custody-plane spend cap

Give each agent its own onchain crypto wallet — read its address and balance, and, as an operator, fund it, transfer, set the spend policy, and sweep it. The private key never enters the agent runtime and the spend cap is enforced inside the custody plane.

Read the docs →

/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
/wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet /wallet
Primitive/wallet
TL;DR
  • /wallet the custody half of payments: a per-agent onchain crypto wallet whose private key never enters the agent runtime
  • Agent-safe reads show and balance are the only surfaces an agent touches
  • Operator admin create, fund, transfer, policy, and sweep require a signed-in session or a wallet:admin-scoped key; an agent's key is refused
  • Custody plane signing happens in a Coinbase CDP TEE; Naïve never holds keys or funds, they sit under your own CDP project
  • Fail-closed perTxMax is written into the custody plane as a static policy, so a wallet is never provisioned without its cap
  • Base + USDC per-agent wallets on Base, capped by balance and perTxMax, the same cap that bounds every /payments call

Give an autonomous agent a wallet the naive way — a hot key in the runtime — and you've handed a promptable process the ability to sign anything. Naïve is the autonomous company infrastructure that gives agents real-world capabilities, and /wallet is the primitive that makes an agent's crypto wallet safe to hand over: the agent gets an address and read access to its balance, while the private key and the spend policy live in a custody plane the agent can never reach.

/wallet is the custody half of /payments. The agent reads the wallet; only an operator moves the float.

Two surfaces: what the agent sees, what the operator controls

CommandDescription
naive wallet showShow the agent's wallet (address, network, custody)
naive wallet balanceRead USDC balances
naive wallet createProvision the wallet — operator
naive wallet fundCredit it from the treasury or a testnet faucet — operator
naive wallet transferSend USDC to an address or another agent — operator
naive wallet policySet the spend policy — operator
naive wallet sweepDrain it back to the treasury — operator

create, fund, transfer, policy, and sweep require an operator credential — a signed-in session (naive auth login), or an API key minted with the wallet:admin scope for CI. An agent's key is refused, both server-side and by the CLI. Reads (show, balance) are agent-safe — and they are the only wallet surface in the SDK and MCP.

Show and balance — the agent-safe reads

naive wallet show
naive wallet balance
naive wallet balance --network eip155:8453

show returns the wallet's address, network, custody backend, and spend policy. If the agent has no wallet yet, it returns a no_wallet error — provision one with naive wallet create, or declare has.crypto on the agent in naive.config.ts. balance reads USDC balances on Base; --network takes a CAIP-2 id. The balance is the budget — an agent cannot spend past it.

From code, the SDK client is read-only on purpose:

await naive.forUser(alice.id).wallet.get();               // address, custody, policy
await naive.forUser(alice.id).wallet.balance();           // USDC balances
await naive.forUser(alice.id).wallet.balance("eip155:8453");

fund, transfer, policy, and sweep are deliberately absent from the client — the API refuses them for an agent credential regardless, so the cheapest way to stop an agent moving the float is to give it no way to ask.

Create — provision the wallet

naive wallet create
naive wallet create --per-tx-max 1.00 --daily-budget 10.00
naive wallet create --custody cdp --network eip155:8453 --smart-account
FlagDescription
--custody <custody>cdp, local, or fake (default: the configured provider)
--network <network>Network to provision on (CAIP-2, e.g. eip155:8453)
--per-tx-max <amount>Max value of a single payment, decimal USDC
--daily-budget <amount>Optional rolling daily cap, decimal USDC
--smart-accountProvision as a smart account

Provisioning is idempotent — re-running returns the existing wallet. perTxMax is written into the custody plane as a static account policy, so it holds even if the agent runtime is compromised. Provisioning is fail-closed: if the cap can't be attached, no wallet is written.

Policy — the cap that replaces an approval queue

naive wallet policy --per-tx-max 1.00
naive wallet policy --per-tx-max 1.00 --daily-budget 10.00
FlagDescription
--per-tx-max <amount>Max value of a single payment, decimal USDC (required)
--daily-budget <amount>Optional rolling daily cap, decimal USDC

perTxMax is enforced twice — at runtime, and inside the custody plane at signing time. This is the control that replaces an approval queue for payments. The default policy, if you set none, is perTxMax: "0.50".

Changing perTxMax re-issues the custody-plane policy too, so both layers move together and the new cap holds at signing time. The re-issue happens before the new policy is stored: if the custody plane can't be reached the command fails and nothing changes, rather than storing a cap that isn't being enforced.

Fund — credit the wallet

naive wallet fund --amount 5.00 --source faucet
naive wallet fund --amount 25.00 --source treasury
FlagDescription
--amount <amount>Decimal USDC amount (required)
--source <source>treasury or faucet — faucet is testnet only (required)
--asset <asset>Asset to credit (default USDC)

The balance is the agent's real budget — fund only what you can afford to lose.

Transfer — move USDC out

naive wallet transfer --to 0xabc... --amount 1.50 --purpose "settle invoice"
naive wallet transfer --to <agent-uuid> --amount 1.50 --purpose "top up worker"
FlagDescription
--to <to>Destination address, or an agent id to target that agent's wallet (required)
--amount <amount>Decimal USDC amount (required)
--purpose <purpose>Why — recorded on the transfer for audit (required)
--asset <asset>Asset (default USDC)
--network <network>Network (CAIP-2)

Transfers are bounded by the wallet's perTxMax — the same cap that bounds agent payments. Passing an agent id as --to resolves to that agent's wallet, which is how you top up a worker or budget a sub-agent.

Sweep — decommission the wallet

naive wallet sweep
naive wallet sweep --to 0xabc...

Drains the wallet back to the treasury (or --to an address) to decommission it. Sweeping moves the funds out but does not delete the wallet — the agent simply has nothing left to spend.

The custody plane

A wallet is a per-agent onchain keypair whose private key never enters the agent runtime. Signing happens in a custody plane, selected per wallet:

  • cdp — Coinbase CDP Server Wallets. Real cloud custody, signing inside the Coinbase TEE. Naïve never custodies funds — wallets are created under your own CDP project with your own credentials.
  • fake — a deterministic in-memory double. Zero credentials, the default for local dev. Not for real funds, but it enforces perTxMax at sign time exactly like CDP does, so tests exercise the real control path.
  • local — an on-box signer. Planned.

The wallet row the agent can read holds no key material — just the address, network, custody type, an opaque provider reference, the policy, and status (active, treasury, or revoked).

What you can build

Give every Employee an economic identity — The wallet address is the agent's identity onchain. Payments in and out are attributable to a specific agent, not a shared pool.

Control the float without blocking the agent — An operator funds and caps the wallet; the agent spends via /payments up to that cap and never past it. No approval click in the hot path, and no way for the agent to raise its own limit.

Budget sub-agents — Fund a supervisor wallet and transfer small budgets to worker agents by id, each bounded by its own perTxMax.

Keep a treasury-controlled lifecycle — Fund from a central treasury, sweep back to it on retirement. The agent can spend but never withdraw, and decommissioning is one command.

Get started

Drop this starter prompt into any coding agent to wire up Naïve:

Read https://usenaive.ai/skill.md and use it to set up Naïve in my project.

Frequently Asked Questions
What is /wallet?+
/wallet is the Naïve primitive for an agent's crypto wallet — a per-agent onchain keypair (USDC on Base). The agent can read its address and balance; an operator provisions it, funds it, transfers out, sets the spend policy, and sweeps it. The private key never enters the agent runtime — signing happens in a custody plane. It is the custody half of /payments.
Who can move funds?+
Only an operator. create, fund, transfer, policy, and sweep require an operator credential — a signed-in session (naive auth login) or an API key minted with the wallet:admin scope for CI. An agent's key is refused, both server-side and by the CLI. Reads (show, balance) are agent-safe.
Does Naïve custody the funds?+
No. With the cdp provider, wallets sit under your own Coinbase CDP project using your credentials, and signing happens inside the Coinbase TEE — Naïve orchestrates but never holds keys or funds. There is also a fake provider (a credential-free in-memory double for local dev) and a planned local on-box signer.
How are spend limits enforced?+
The balance is the outer bound — an agent cannot spend what isn't there. perTxMax is enforced twice: at runtime, and as a static policy inside the custody plane at signing time, so it holds even if the agent runtime is compromised. An optional dailyBudget adds a rolling runtime counter. This is the control that replaces an approval queue for payments.
What happens if the custody plane can't be reached when I set a policy?+
Setting or changing perTxMax re-issues the custody-plane policy before the new policy is stored. If the custody plane can't be reached, the command fails and nothing changes — the system never stores a cap that isn't actually being enforced. Provisioning a wallet is fail-closed the same way: no wallet is written without its cap attached.
How do I get started with /wallet?+
Enable payments on the Account Kit (the wallet is opt-in), select an agent with naive use <alice> since the wallet is per-agent, then run naive wallet create as an operator, set a cap with naive wallet policy --per-tx-max 1.00, and fund it with naive wallet fund. The full guide is at usenaive.ai/docs/cli/wallet.
A
AshleyEngineering

Engineering at Naïve. Owns the payments and wallet primitives.

Keep reading