The problem: one command line, two kinds of user
When an AI agent and a human operator share the same command line, the system has to know who is typing. Ours guessed from a badge the agent could take off.
We were building crypto vaults into Ravi, a daemon that runs AI agents on WhatsApp and Slack. A customer sends "quero depositar 100", the agent runs ravi crypto deposit 100, and a Pix charge comes back. Approving a trade uses the same tool: the operator types ravi crypto trades approve in a terminal.
The ravi command told the two apart with a badge. Every command an agent runs carries hidden RAVI_* environment variables saying which agent and which customer. A terminal has none, so the rule was simple: no badge means the operator. That rule fails open. Removing information grants power.
The agent types shell commands, and a shell can take the badge off. A guard read each command before it ran, and three tricks got past it:
ravi crypto status > ~/.ravi/crypto.db. The guard saw onlyraviand allowed it. The>then overwrote the ledger with the command's output.env -i ./bin/r'a'vi crypto trades approve ….env -iempties the badge. The guard looked for the wordraviand did not find it inr'a'vi. The shell removes the quotes, runsraviwith no badge, and the agent approves its own trade as the operator.bun script.ts. Every agent is born with an interpreter. A script can open the database directly and skip every rule.
None of these is prompt injection itself. Injection is how a customer talks the agent into trying. These are what let the attempt succeed. Security people call this the confused deputy: a program holding your authority is steered into using it for someone else.
Why it is the market's problem, not ours
Every platform that gives an agent a shell and also lets humans run the same tools has this gap. Coding agents, agent operating systems and "agents with a computer" all share one machine and one user account with the people who run them.
Three trends make it worse:
- Agents are born powerful. Ravi's default profile gives every agent all tools plus
bun,catandxargs, because most agents are trusted helpers for their own operator. That default is right for your assistant and wrong for an agent that talks to strangers. - Text filters cannot keep up with a shell. Quoting, redirection, interpreters and programs that start other programs give a shell many spellings of the same action. We found three bypasses in a short session of poking.
- Money raises the stakes. Simon Willison calls the dangerous mix the lethal trifecta: private data, untrusted input, and a way to act or send data out. A public crypto agent has all three: balances, customer messages, and the power to move funds.
Prompt injection cannot be fully prevented today. Any text the agent reads, a customer message or a token name, may carry instructions. So the question is not "can the agent be tricked?" but "what can a tricked agent reach?"
How the industry overcomes it
The consistent answer: never trust the agent's own process to enforce limits. Put the boundary where the agent cannot reach it, and make the human prove consent on their own device.
1. Sandbox the agent. Claude Code's Bash sandbox is "a boundary that the operating system enforces" around shell commands and every process they start. Command patterns are a convenience; the OS boundary is what holds. Cloud agents go further and run in a throwaway container or micro-VM per session.
2. Keep secrets outside. The agent asks for an action; a service outside the sandbox holds the key and performs it. The agent receives results, never credentials.
3. Prove identity, never assume it. The operator is recognized by something the agent cannot forge: a separate OS user, a signed token, or a login on another device. Missing proof means refuse, not "must be the boss".
4. Approve out of band. High-impact actions are confirmed by the human on a channel the agent has no access to: a passkey prompt, a biometric check, a tap in another app.
5. For payments, scope the credential to the intent. The 2025–2026 agentic payment primitives all follow one pattern: the agent gets a narrow, revocable permission, and the issuer or wallet enforces it.
| Primitive | What the agent holds | What limits it |
|---|---|---|
| Google AP2 (Sept 2025) | Mandates signed as verifiable credentials | Intent Mandate set upfront ("price limits, timing, and other conditions"); Cart Mandate signed for the exact items and price; a non-repudiable audit trail |
| Stripe Shared Payment Tokens (expanded Mar 2026) | A token, never the card | A Visa or Mastercard agentic network token "scoped to the customer's intent" |
| Visa Intelligent Commerce, Mastercard Agent Pay | Tokenized credentials for registered agents | Network-side spending rules and agent verification |
| Coinbase Agentic Wallets (Feb 2026) | A wallet whose key stays in Coinbase's enclave | Spending limits, session caps, transaction controls |
| Turnkey and Privy policy wallets | Signatures, not keys | Policies check recipient, contract, chain and value before signing; Turnkey evaluates them inside a secure enclave |
Turnkey states the principle best: "The agent never touches the private key. It receives signatures, not keys."
6. Pix in Brazil. There is no Central Bank rule yet for agents paying on their own. Today an agent prepares the payment and the person approves it with biometrics in the bank app. Finsiders (Sept 2026) argues agent authority must be "specific, limited, verifiable and revocable", built on Open Finance consent and on existing Pix Agendado and Pix Automático.
What we chose for Ravi
The agent is the front desk, never the cashier. It can ask for money to move; only a service it cannot reach moves it, and only with the customer's proof of consent.
Deposits already follow the industry pattern. The agent creates a Pix charge, and the customer pays it in their own bank app with their own biometrics. The provider's signed webhook goes straight to the money service, so a deposit lands even if the agent is down or confused.
Trades should not need the operator for every order; that does not scale. The customer confirms each trade with one tap, a reaction the service reads directly from their phone, so a tricked agent cannot fake it. Customers who want autonomy sign a mandate once, such as up to R$200 a week in approved assets, and the agent trades inside it. The operator steps in only for exceptions.
The agent sits outside the wall and can only send requests. Confirmations reach the service straight from the customer's phone, payments come from the Pix provider's signed webhook, and only the policy wallet can sign.
| Decision | What it means | Status |
|---|---|---|
| Agent proposes, never executes | The agent can create charges and trade proposals, nothing more | Built |
| Deposits settle without the agent | Signed provider webhook to the money service; the confirmation states the exact amount paid | Built |
| Sandbox and production split by construction | Separate ledger per environment, chosen by a startup flag agents cannot change | Built |
| Customer agents get only what they need | An explicit-only profile plus a stricter shell guard (PR #624) | In review |
| One-tap confirmation and mandates for trades | Customer approves on their phone; mandates cap standing autonomy | Planned |
| Operator only for exceptions | Large amounts, risk flags, frozen vaults | Planned |
| Treasury key in a policy-engine wallet | Signs only allowed swaps up to set values, even if Ravi's host is compromised | Planned |
| Withdrawals only to the depositor's own CPF | Money can only return to its owner | Planned |
| Agents isolated from the money at OS level | Separate OS user or sandbox that cannot read Ravi's data | Planned |
Tradeoffs we accepted
Every choice above trades some convenience or speed for a smaller worst case. These are the ones we made knowingly.
| Choice | What we gain | What we give up |
|---|---|---|
| One-tap confirmation per trade | A tricked agent can only propose; the customer sees every order | One tap per trade; fully hands-off trading needs a mandate |
| Mandates for autonomy | Trading without the customer present | A tricked agent can still misuse the mandate, but only within its cap and assets |
| Custodial vaults (one treasury, ledger per person) | Simple onboarding; no wallet for the customer to manage | Ravi holds other people's money: legal duties, KYC, and one key that matters a lot |
| Buying a policy wallet instead of building one | Enclave-enforced limits, audited by a specialist | A vendor dependency and per-signature cost |
| Shell guards (text checks) | Cheap, immediate, catches the common tricks | Bypassable by design; we found three gaps and three false positives in one session |
| OS-level isolation | Holds even when every rule above has a bug | Real infrastructure work; depends on how production is deployed |
| SQLite ledger for v0, not Postgres or TigerBeetle | Ships now; one file, easy to inspect | Single machine; durability needs synchronous=FULL and off-site replication |
Two things we deliberately did not do yet:
- Self-custody, where each customer holds their own key and signs each trade. It removes the honeypot but adds wallet setup for every user and changes the product.
- Fully autonomous Pix out, where the agent sends money without a human tap. Brazilian rules for agent-initiated Pix are not settled, and withdrawals to the depositor's own CPF already cover the real need.
Where we think this is going
Agents will be treated like untrusted clients, not like employees with the operator's keys. The pieces for that already exist; what changes is that they become the default.
- Isolation becomes table stakes. Agents that talk to the public will run in a sandbox or as their own OS user by default, the way web apps stopped running as root. Shell guards stay, but as a second layer.
- Consent becomes a signed object. Mandates like AP2's turn "the user said yes" into a verifiable record with limits, an expiry and an audit trail. Payment rails and wallets will accept these instead of trusting the agent's word.
- Keys move into policy engines. Money-moving agents will hold permission to request signatures, never keys. The rules live in an enclave run by a specialist, outside the agent's host.
- Agents get verifiable identities. Card networks are already registering agents. Expect "which agent, acting for whom, under which mandate" on every payment, as standard as a card's billing address.
- Pix gets agent rules. Brazil already has the parts: Open Finance consent, scheduled and automatic Pix, biometric approval. A Central Bank framework for agent mandates is a matter of when, not if.
For Ravi this sets the order of work: isolate customer agents, move the treasury key into a policy wallet, replace operator approval with customer taps and mandates, then add withdrawals to the depositor's own CPF. Each step shrinks what a tricked agent can reach.
Sources
- Google Cloud: Announcing the Agent Payments Protocol (AP2)
- Stripe: Supporting additional payment methods for agentic commerce
- The Block: Coinbase rolls out a tool to give any agent a wallet
- Turnkey docs: Agentic wallets
- Privy docs: Agent wallets
- Claude Code docs: Configure the sandboxed Bash tool
- Finsiders Brasil: Agentes de IA podem fazer um Pix. Mas quem os autorizou?
- Ravi PR #624: explicit-only agents and a stricter bash guard