Inspiration

  • AI agents can now spend money, but payment mandates only prove a user approved a scope ("up to $50 of clothing"), not that the cart matches what they meant.
  • Hidden text on a product page can tell an agent to buy a gift card for a stranger. It's under the cap, so it goes through. In our benchmark, spending caps alone let 92.4% of attacks pass.
  • When an agent buys the wrong thing within limits, nobody can show whose fault it was, so the merchant pays by default.

What it does

  • A payment firewall between any AI agent and PayPal, exposed as an MCP server. The agent never holds PayPal credentials and can never sign for the user.
  • Before payment: the user's request becomes a typed, signed Intent Spec. Every cart is checked against that spec, the spending policy, the catalog, the merchant's quote, and a ledger of where every value came from. A hijacked cart is blocked before any PayPal order exists.
  • The proof: a passing cart gets an Ed25519-signed Intent-Satisfaction Proof. Its hash goes into the PayPal order's custom_id. Funds are held, the checkout is re-checked, and only then captured. If the merchant adds an extra after the hold, the hold is voided.
  • After payment: when a dispute arrives, the proof is verified and a fixed procedure decides fault (user, agent, manipulation, merchant or fraud), then contests the claim, accepts it, or flags fraud.
  • Design rule: LLMs propose, deterministic code decides. No model output can approve a payment.

How we built it

  • PayPal: Orders v2 (intent: AUTHORIZE, custom_id), Payments v2 (capture, void), the Disputes API and webhook verification. Tested end to end on the real PayPal sandbox: hold, proof hash, capture and void all worked.
  • Agents: a remote MCP server with seven tools. The agent requests a mandate, the user signs it in the console, then the agent shops. Works with Claude Code, Claude, ChatGPT, Cursor and VS Code.
  • AI: Claude compiles requests into specs, flags suspicious carts (it can only escalate, never approve) and maps complaint text to an order attribute. Every AI step has a deterministic fallback.
  • Stack: Python, FastAPI, the MCP SDK, Ed25519, SQLite and a plain HTML/JS console. Hosted on Render, API tested with Postman, plus a live Channel3 catalog, AG Grid tables and AG Studio analytics.
  • AgentDispute-Bench: our own benchmark of 150 normal tasks, 119 attacks and 200 disputes with known fault.

Challenges we ran into

  • PayPal only allows custom_id before authorization, so we reordered the flow: check → create order → sign proof → attach hash → hold → re-check → capture.
  • A hijacked agent would lie about where its data came from, so the proxy records the source of every value itself instead of trusting the agent.
  • Our India sandbox merchant couldn't receive USD (UNSUPPORTED_PAYEE_CURRENCY), and INR isn't supported, so the demo uses a US sandbox merchant.

Accomplishments that we're proud of

  • Attack success drops from 100% with no defense (92.4% with caps) to 0% when users decline flagged payments.
  • Fault decisions reach 0.926 macro-F1, and wrong-item purchases drop from 38% to 8.7% with under one question per task.
  • The full PayPal sandbox flow works for real, and 99 automated tests pass.
  • These results come from a scripted agent on our own benchmark; the README says exactly what was and wasn't run.

What we learned

  • A spending limit isn't intent. You need proof of what the user actually meant.
  • The most useful record is one that is checked before payment and reused as evidence after it.
  • Keeping AI out of the final yes/no decision made the whole system easier to trust and test.

What's next for IntentProof

  • An independent red team to attack it.
  • Real dispute data to tune the question-asking thresholds.
  • Running a real Claude agent across the full benchmark.
  • Proposing the proof as an extension to agent payment protocols like AP2.

Built With

Share this project:

Updates

Submission history