-
-
Describe what the agent may buy in plain English. It drafts rules you can edit, and the rules are signed.
-
Approve the budget once in PayPal: one authorization hold. A signed PayPal webhook confirms it in the audit log.
-
Edit the budget without re-signing and every purchase is refused, because the signature no longer matches.
-
An independent AI auditor blocks a plastic lamp because the mandate says no plastic
-
Above the auto-approve limit a human approves. PayPal captures exactly that amount and the budget drops.
-
Limit orders reserve part of the budget and buy only if the price drops. The same checks run before paying.
-
Undo purchase refunds a capture through PayPal and frees the budget again: back to $120.00.
-
Red team: an attacker AI writes poisoned listings against your own rules. 8 of 8 stopped, $0 moved
-
Insights (AG Studio): a custom seal widget shows purchases stopped and money kept safe
-
A custom guardrail agent answers "would this purchase pass?" with the real rules engine. A $249 watch is blocked
-
Under the hood: PayPal holds, partial captures, refunds, signed webhooks; Gemini; Channel3; Neon; Render; AG Studio.
Inspiration
Agentic commerce has a trust problem. Handing an AI your payment method means hoping it behaves. We wanted the opposite: let the user approve a budget once, then make it structurally impossible for the agent to exceed it, edit its own rules, or be talked into a bad purchase by a poisoned product listing.
What it does
Mandate is an AI shopping agent that can only spend inside rules you sign.
- Rules you sign. You describe a mandate in plain English ("home desk setup, $120 total, ask me above $30, no plastic"). An LLM turns it into editable terms, and the terms are HMAC-signed, so nobody (including the agent) can quietly change them.
- One PayPal approval. You approve the budget once in PayPal. The app creates an
AUTHORIZEorder, and that authorization becomes the agent's spending pool. - Two independent checks on every purchase. The agent searches real products (Channel3) and proposes purchases. It cannot pay directly. Every proposal passes a deterministic rules engine (signature, funded, expiry, currency, stock, per-item cap, remaining budget, merchant allow-list, blocked terms, price drift) and an independent auditor agent that judges whether the product really fits the goal and flags prompt-injection text. The strictest verdict wins: allow, ask a human, or block. Anything above your auto-approve limit waits for your click.
- Many purchases, one hold. Approved purchases are partial captures against the same authorization. Closing the mandate voids the unspent remainder.
- Undo purchase. A human-only button refunds a capture through PayPal and frees that budget again. The agent has no refund tool.
- Limit orders. They reserve budget and buy only when the live price drops to a target. A triggered order runs the same checks.
- Signed webhooks. PayPal events (buyer approval, capture, refund, voided hold) are verified with PayPal's signature check and applied to the ledger, so changes made in PayPal show up in the app. Retries change nothing.
- Red team. An attacker AI tries to break your own mandate's guardrails. The attack numbers come from your rules (over your cap, past your budget, a look-alike of your allowed store, wording that dodges your blocked terms, an edit to your budget without re-signing), and the AI writes fresh poisoned listings for your goal. The real rules engine and the real auditor judge each attack. It is a simulation: no PayPal call, nothing saved.
- Insights dashboard (AG Studio). An analytics dashboard over everything the agent tried to buy, what was stopped and why, and where the money went. A custom
guardrailagent answers "would this purchase pass my mandate?" by running the app's real rules engine and auditor (read-only, no money moves), and a custom Mandate seal widget shows purchases stopped and money kept safe.
How we built it
Next.js 16 and TypeScript. PayPal REST: Orders v2 (intent: AUTHORIZE), order authorize, multiple partial captures (final_capture: false, idempotent request IDs), void, refund, and webhook signature verification. Vercel AI SDK v7 with Google Gemini for the shopping agent (tool calling), the mandate parser and the auditor (structured output). Because Gemini's free tier allows about 5 requests a minute per model, we built a 5-model failover pool. Channel3 supplies real products and live prices (product detail by ID is free, which is what the limit-order watcher polls). The rules engine is pure code with 52 unit tests.
State lives in Postgres on Neon when hosted. Every write runs in a transaction that locks one row, re-reads it, applies the change and saves it, so two server instances cannot overwrite each other and a failed write changes nothing. The signing secret is stored there too, so mandates stay valid across restarts. Locally the app uses a JSON file with zero setup. Deployed on Render.
The Insights page is built on AG Studio. We went beyond dropping the component in: the theme reads the app's own design tokens, the store is flattened into related tables with calculated rates, and the assistant runs through a browser-side adapter to a server route on the Gemini failover pool, so the API key stays on the server. On top of AG Studio's built-in agents we added a sixth, guardrail, with a custom tool that calls /api/preflight, and a custom seal widget registered through createWidgets. The Red team page derives each attack from the mandate's own numbers, has an AI write the listings, and judges them with the real guardrails.
Challenges we ran into
- PayPal sandbox accounts created for India fail at checkout with a currency error. We moved to US sandbox accounts.
- Free-tier LLM rate limits: solved with timeouts and a model failover pool.
- Making a guardrail that an LLM cannot talk its way past: the final decision takes the stricter of a deterministic engine and a separate auditor model, and the agent has no tool that moves money.
- Getting AG Studio's agents to delegate to our custom one. Gemini sends the delegate target as a plain string where AG Studio expects
{ id }, so delegation failed and the model invented an answer. The adapter now accepts both, and the lead agent is told never to claim a check it didn't get from a specialist. - PayPal's sandbox checkout sometimes declines an approval in a stale browser session. It happens inside PayPal, before the buyer returns to the app, so we added a Copy approval link button and an honest message instead of pretending we could fix it.
- Render's free tier wipes its disk on every deploy, which erased mandates and changed the signing secret. We moved the state to Postgres on Neon and checked that the secret survives a redeploy.
- PayPal's docs don't say whether money from a refunded capture can be captured again from the same authorization, and we chose not to test it with real captures. The PayPal hold stays the hard cap either way: if PayPal ever refuses, the purchase fails with nothing spent, the audit log says why, and refunds stop freeing budget.
Accomplishments that we're proud of
- One PayPal approval safely backing many agent purchases through multi-capture on a single authorization, with void, refund and signed webhooks around it.
- An attacker AI that tries to break your own mandate (8 of 8 attacks stopped, $0 moved), and a guardrail check inside the analytics dashboard that uses the real rules engine and auditor rather than a model's guess.
- Real PayPal sandbox captures, a limit order that triggers a human approval, a tamper test that refuses to spend, an auditor that blocks a plastic lamp against a "no plastic" rule, a refund that frees the budget, and a void that releases unspent funds, all verified end to end on the hosted app.
What we learned
Agent safety is a payments design problem, not a prompt problem: put the limit in the money rail, then add AI judgment on top.
What's next for Mandate
Multi-user accounts, PayPal vaulting for recurring mandates, and payout-based mandates for contractors. The repo also includes optional Render Workflows tasks that fan out limit-order price checks in parallel. They are off in the hosted demo (Workflows needs a payment method on the Render account) and have not been tested against a live workflow.
Built With
- ag-grid
- ag-studio
- channel3
- google-gemini
- neon
- next.js
- paypal-orders-v2
- paypal-payments-v2
- paypal-rest-api
- paypal-webhooks
- postgresql
- react
- render
- tailwind-css
- typescript
- vercel-ai-sdk