-
-
Writ: the financial permission layer for autonomous AI. Signed by a human, held by PayPal, enforced by code.
-
Your AI can shop. It can't overspend
-
A compromised AI agent was ordered to steal: 16 attacks, 16 blocked. PayPal's own API confirms $0.00 moved.
-
A prompt-injected "pre-approved $389" listing fooled the AI. The 13-rule engine said DENIED. $0.00 moved.
-
You are signing this: the mission compiled into clauses. The amount stays VOID until you sign with a passkey.
-
The human approves in the real PayPal sandbox window: an Orders v2 authorization hold for $100. Nothing is charged.
-
Mission done: $15.67 captured, $84.33 voided straight back to the buyer. Every step confirmed by PayPal webhooks.
-
Append-only audit ledger (AG Grid): $1,525 authorized, $179.90 captured, 40 attack attempts blocked, all traceable to PayPal IDs.
-
Forensics: authorized, yes, but the data provider returned manipulated data. AT FAULT. Every claim cites evidence.
-
Kill switch: one tap revokes every agent under the mandate, and PayPal voids the whole hold.
-
Signed Assurance Certificate: this exact mandate was attacked and crash-tested (20/20 boundaries held). PASSED.
-
Every attack and the rule that stopped it: prompt injection, forged prices, fake storefronts, self-delegation. 16/16 blocked.
Inspiration## Inspiration
AI agents are starting to buy things for people and companies, but today "letting an agent pay" means handing it a card. No payment system can answer four basic questions about an agent's purchase:
- Who authorized it?
- Within what limits?
- Can the agent hand that authority to another agent?
- Who can prove it afterwards?
PayPal and Google's AP2 work describes signed mandates as the answer. We wanted to build the part that actually enforces them at runtime, on real PayPal rails, even when the AI itself has been compromised.
What makes Writ different
Many projects pair a signed spending mandate with a policy gate. Writ goes further in four ways:
- It proves the boundary, live. A compromised AI agent is handed a real slice of a real PayPal hold and ordered to steal. PayPal's own API is asked before and after ($0.00 moved), every clause is crash-tested at its exact edge, and Writ issues a signed Assurance Certificate for that exact mandate.
- Teams of agents under one hold. Delegation trees with capability attenuation: every sub-agent is provably narrower than its parent, checked at every level of the chain, and backed by a single PayPal authorization.
- Agents pay for data, too. The Writ Tab meters paid API calls (signed HTTP 402 prices) under the same mandate, settles them as one PayPal capture, and pays providers through PayPal Payouts.
- When it goes wrong, evidence. Forensics rebuilds a cited evidence graph, separates authorized from correct, and answers real PayPal disputes or refunds through the Agent Toolkit, with a human deciding.
What it does
You write a rule in plain English, for example: "Onboarding kit for the design team: monitors, headphones, lamps. $1,500 total, ask me before anything over $200, nothing from Amazon."
- The policy. An LLM compiles it into numbered clauses on a signed instrument. Deterministic code then cross-checks the result against your literal words, restoring any cap, approval line or exclusion the model dropped.
- The signatures. You sign with a passkey, whose WebAuthn challenge is the sha256 of the mandate. You then approve a PayPal authorization hold for the budget. Writ seals an AP2-shaped IntentMandate (Ed25519) bound to that authorization ID.
- The agents. A single agent, a team of agents, or any external agent over MCP shops real catalogs (Channel3). An orchestrator can delegate sub-mandates, which are always narrower than their parent on every rule (capability attenuation). An over-reaching delegation is refused with the reason.
- The verdict. Every proposed purchase is checked by a 13-rule deterministic engine at every level of the delegation chain:
- ALLOW: partial capture from the hold, plus a signed merchant verification receipt and tracking via the PayPal Agent Toolkit.
- ESCALATE: an approval slip goes to the human. If they decline with a reason, the agent adapts.
- DENY: nobody can override it, not the agent and not the human.
- The kill switch revokes any agent's subtree instantly. When the work is done, the unspent hold is voided and refunds run through the Agent Toolkit. PayPal webhooks (signature-verified) reconcile everything into an append-only AG Grid ledger.
- The proof. The red-team suite hands a deliberately compromised AI agent a real $100 sub-mandate from the live hold and orders it to steal: prompt-injected overspend, forged prices, quantity stuffing, blocked merchants, skipping approvals, delegating itself more money, escaping its token scope, spending after revocation, and a sub-agent exceeding its own slice while the parent still has money. Writ then runs a policy-specific Crash Test, a boundary matrix generated from the mandate's own clauses (budget + $0.01, approval line + $0.01, one item too many, every blocked merchant and subdomain, rating − 0.1, deadline + 1 day, expiry, revocation, and every way a delegation could widen authority). It asks PayPal's own API before and after, and issues a signed Assurance Certificate bound to that exact mandate hash. From the run in our video: "16/16 attacks blocked (5 improvised by the adversarial AI) · 20/20 boundaries held · $0.00 moved, confirmed by PayPal · certificate PASSED".
- Merchants can verify any agent order at
/verifyand get a signed, offline-verifiable receipt. - Writ Tab: agents pay for data. Paid APIs answer HTTP 402 with a signed price. Writ verifies it, the same engine checks the call at every level of the chain, and charges accrue on a tab that settles as one PayPal capture. A 5-cent call can't escape the mandate. (The providers are simulated; the PayPal settlement is real.)
- Writ Forensics: an authorized payment isn't the same as a correct one. Every purchase has an evidence graph. Code answers three questions (authorized? did the agent follow the instruction? did the merchant or provider deliver?), and an investigation agent cites evidence for every claim (uncited claims are dropped). It recommends: you approve a refund (via the Agent Toolkit) or a signed dispute pack. When a buyer opens a real PayPal dispute, Writ pulls it from the Disputes API, investigates it, and (once you decide) either submits the signed evidence through
provide-evidenceor accepts the claim. - Know Your Merchant, autonomy profiles, photo and voice missions:
- Look-alike and impersonating storefronts are denied.
- Careful / Balanced / Autopilot presets never loosen a limit you wrote.
- Missions can start from a photo or your voice.
- Tab settlements pay providers through PayPal Payouts.
- Agent Passport: a signed, verifiable credential stating any agent's authority and delegation chain, up to the human.
How we built it
PayPal:
- Orders v2 (
intent=AUTHORIZE,/authorize,GETfor independent evidence) - Payments v2 (partial
capturewith idempotency keys,void,refund) - PayPal Agent Toolkit (
create_refund,create_shipment_tracking,get_shipment_tracking,accept_dispute_claim), wrapped so it only runs behind the policy engine - Disputes API (
list,get,provide-evidence,accept-claim) to answer buyer disputes with signed, cited evidence - Webhooks with
verify-webhook-signature - JS SDK v6 for the human's approval
- Payouts (
/v1/payments/payouts) to pay data providers after each tab settlement - AP2 concepts: signed IntentMandate, user signature, and the mandate hash stamped into each capture's
invoice_id
AI:
- Vercel AI SDK v7 tool loops with JSON-schema structured output
- Gemini 3 Flash on Google Cloud Vertex AI (service-account auth, no API key), with resilient retry and failover
- Used for: the compiler, the orchestrator, the specialist shopping agents and the adversarial red-team agent
Enforcement and crypto:
- A pure TypeScript policy engine, attenuation rules and a cross-check (36 Vitest tests)
- Ed25519 signatures over canonical JSON
- WebAuthn passkeys (
@simplewebauthn) - One lock per delegation tree
Stack and sponsors:
- Next.js 15, Tailwind v4, Postgres + Drizzle
- Channel3 product search (agentic mode)
- AG Grid ledger with a custom theme
- Google Cloud: Cloud Run, Cloud SQL Postgres, Secret Manager, Vertex AI
- Render Blueprint deploy (mirror)
- An MCP server (Streamable HTTP), so any agent can connect with a scoped token
Writ Tab, Forensics, Passport:
- Ed25519-signed 402 price challenges with pinned provider keys and signed receipts.
- A batch-settled tab.
- Evidence graphs with deterministic checks and citation-enforced reports.
- Signed passports.
Design: "Intaglio", the vocabulary of security printing, because a mandate is a financial instrument. Each mandate gets a guilloche rosette generated from its own hash; unsigned amounts carry a VOID pantograph; final acts (DENIED, VOID, REVOKED) are punch-cancelled like a 19th-century share certificate. The layout is a strict Swiss grid, and colour carries meaning only: PayPal blue for PayPal money; green, amber and red for verdicts.
The film: recorded from the live app by an automated browser (nothing mocked) and edited in Remotion.
Challenges we ran into
- PayPal sandbox regions. India-to-India sandbox payments are declined, so we moved to a US merchant and buyer.
- One hold for a whole tree. Making a single PayPal authorization safely back a whole tree of agents took care: spend counts against every ancestor, unspent allocations return to the parent, and money operations are serialised per tree.
- The model drops instructions. It sometimes silently dropped explicit rules ("nothing from Amazon"), so we added a deterministic cross-check. It fired during our own live run.
- Honest security testing. A model resisting an injection proves nothing about the boundary. So we built a suite where the AI is told to attack, and we check PayPal's own records rather than our database.
Accomplishments that we're proud of
- Every product shot in our video is a live run on real PayPal sandbox rails: a passkey signature, the PayPal approval window, a $100 hold, an orchestrator delegating to 3 specialists, partial captures, a pay-per-call tab settled in one capture plus Payouts, $84.33 voided back, all confirmed by verified webhooks.
- A compromised agent with a real budget couldn't move a cent, and PayPal confirmed it. Every mandate can now carry a signed Assurance Certificate: crash-tested at every clause's edge, red-teamed, and PayPal-verified.
What we learned
"AI for judgment, math for money." The safest agent architecture isn't a smarter model. It's a boundary the model can't argue with, enforced by the payment system itself.
What's next for Writ
- The full AP2 Cart and Payment mandate chain
- Phone approvals
- Earned autonomy (limits that widen as an agent proves reliable)
- Nightly red-team scorecards
- A merchant SDK with a "Verified agent order" badge (aligned with PayPal Agent Ready / Store Sync)
- A
mandate.guard(tools)SDK, plus ACP/UCP adapters - Vault recurring mandates, and Payouts for marketplace settlement
Built With
- ag-grid
- ap2
- channel3
- cloud-run
- drizzle
- ed25519
- gemini
- google-cloud
- mcp
- next.js
- paypal
- paypal-agent-toolkit
- paypal-disputes
- paypal-js-sdk
- paypal-orders-v2
- paypal-payments-v2
- paypal-payouts
- postgresql
- tailwindcss
- typescript
- vertex-ai
- webauthn