Inspiration

AI agents are starting to shop for people. That creates a new kind of PayPal dispute: "my agent bought this, I never agreed." Today the seller has nothing to show PayPal about what the buyer actually asked for, so small sellers usually refund and eat the fee. We wanted a receipt for the buyer's intent that PayPal's own record vouches for, and an agent that uses it when a dispute lands.

What it does

At checkout. A shopping agent (our /shop assistant or any agent over MCP) can find products and quote, but it cannot pay. The buyer reviews their own request, the spending cap and the cart on a hosted page, then approves in PayPal. Every step becomes an event in a hash-chained, Ed25519-signed intent receipt. The receipt's seal hash is written into the PayPal order's custom_id before payment, so the commitment lives inside PayPal's record and can't be fabricated later. Anyone can check a receipt at /verify/{id}: chain intact, seal matches the approval, signature valid, and the live PayPal order carries the same seal.

When a dispute arrives. A LangChain Deep Agent pulls the case (webhook or poller), checks the receipt against PayPal, gathers order, capture and tracking evidence, and runs deterministic economics: expected loss if you fight, offer or accept, using PayPal's fee ($15, or $30 once the 90-day dispute rate crosses 1.5%) and a win-probability prior. It drafts a reason-specific response citing evidence IDs. A fact-checker subagent and a deterministic checker reject any amount, date or ID that isn't in the evidence.

The seller stays in charge. The merchant console (AG Grid queue) shows every case with its deadline, fee, receipt strength and recommendation. Nothing goes to PayPal until the seller clicks Approve. The submit tool is gated twice: Deep Agents' interrupt_on pauses before it runs, and the tool itself requires an approval row whose hash matches the exact saved draft and evidence PDF. The response then goes out through the dispute's own HATEOAS link: provide evidence, make an offer, or accept.

In the demo video, a sandbox buyer disputes a $41.99 throw ("my AI shopping agent bought this, but it isn't the sage green linen throw I asked for"). The receipt verifies STRONG, but with a $30 fee at stake the agent recommends a $16.80 partial refund and drafts it; the seller approves and PayPal receives the offer.

How we built it

  • Backend: FastAPI on Python 3.12, psycopg 3 on Neon Postgres, deployed on Render.
  • Agent: LangChain Deep Agents (LangGraph) with a Postgres checkpointer, a fact-checker subagent and human-in-the-loop interrupts; sarvam-105b through Sarvam's OpenAI-compatible API.
  • PayPal (sandbox): Orders v2 (create with custom_id, capture, get, trackers), Payments v2 captures, Customer Disputes v1 (list, get, provide-evidence, make-offer, accept-claim, escalate), webhook signature verification.
  • Receipts: canonical JSON, SHA-256 hash chain, Ed25519 signatures, public keys at /.well-known/countersign-keys.json, AP2-shaped export, evidence PDF with a QR code to the live verifier.
  • Agent interface: an MCP server (/mcp) with search, mandate, receipt and pre-dispute report_issue tools.
  • Frontend: Next.js 16 + Tailwind 4 + AG Grid 36 on Vercel; Channel3 for real product search and Kernel for optional read-only inspection of a source listing.
  • Tests: 181 backend tests on embedded Postgres; live LLM evals for 11 golden cases (G1 recorded passing on sarvam-105b); all 12 golden economics decisions checked deterministically.

Challenges we ran into

  • Recording the demo found real bugs. PayPal rejected a "refund with return" offer with MISSING_RETURN_SHIPPING_ADDRESS, so offers are now partial refunds. Our own draft checker flagged the agent's computed offer amount as "not in the evidence". And the model once returned an empty reply mid-case. Each fix came with a regression test.
  • Sandbox dispute lifecycle. Creating disputes via API isn't permitted for this app, so a sandbox buyer files them in the Resolution Center. Inquiry-stage disputes have no provide-evidence action until escalated, and sandbox won't let a seller force a ruling.
  • Keeping the LLM away from facts. Every number (fees, deadlines, expected value, receipt checks) is deterministic code exposed as a tool; the model plans and writes, and PII is redacted before it ever sees the case.

Accomplishments that we're proud of

A full live loop on PayPal sandbox: real search, real sandbox payment, a STRONG receipt verified against PayPal's order, a real buyer dispute, an agent-drafted response, seller approval, and the response accepted by PayPal's Disputes API.

What we learned

PayPal's custom_id is a small field with a big job: it lets a third party commit to evidence inside the payment record itself. And dispute economics matter as much as evidence; sometimes the right move with a strong receipt is still an offer.

What's next

Return addresses for refund-with-return offers, the Verifiable Intent SD-JWT format, more dispute reasons in the playbook, and an outcome feedback loop that replaces the win-probability priors with measured results.

Tools

Tool How we used it
sarvam-105b (Sarvam AI) Model for the dispute Deep Agent, its fact-checker subagent and the shopping assistant
LangChain Deep Agents Planning, tool calls, subagent, human-in-the-loop approval gate, Postgres checkpoints
PayPal Orders, Payments and Disputes APIs (sandbox) Checkout with the receipt commitment, capture, verification, dispute intake and responses
Channel3 Real product search for the shopping assistant
Kernel Optional live, read-only browser inspection of a product's source listing
AG Grid Merchant dispute queue with custom cell renderers
Render, Neon, Vercel Hosting for the API, database and frontend
MCP Agent-facing checkout and pre-dispute tools

Built With

Share this project:

Updates

Submission history