Inspiration
Merchants lose money when a customer's card declines or an invoice goes unpaid. Recovery often means blind retries and nagging emails, and handing that job to an AI agent raises a fair question: why would anyone trust it with money? I started Vasooli at another hackathon on a different payments gateway. For this one I asked a sharper question: what would make an agent trustworthy enough to touch real payments? Our answer is "autonomy you can audit": the model can propose, but only deterministic, fingerprinted rules can authorize, and only a signed PayPal webhook can confirm that money came back.
What it does
Vasooli recovers failed payments on PayPal in three acts.
Say the rules. A merchant types policy in plain English, such as "Contact at most twice, wait 48 hours, and ask me before anything over $100." Gemini turns it into structured values. Deterministic code checks them against hard caps and against the merchant's own words, shows a diff and a new rulebook fingerprint, and only an admin can apply the change. Over-cap requests are rejected with a reason, never silently clamped. Attempts to disable the opt-out check are refused. Watch it work. A card on file is declined (a PayPal sandbox simulation). Vasooli reads the real decline code, diagnoses it, passes policy, and retries the vaulted card through the PayPal API. A signed PAYMENT.CAPTURE.COMPLETED webhook marks the money recovered. The ledger separates verified money from merchant-asserted money and never blends them. Try to break it. Outside AI agents reach Vasooli through a public page and an MCP server. Seven scripted attacks (retry a do-not-retry decline, contact an opted-out customer, a fourth contact, a $1,500 spend without approval, calling "apply rules," and more) are evaluated by the real policy layer and blocked. Every attempt is audited.
Who it's for and why it matters
Who: online merchants and subscription businesses that charge cards on file through PayPal and small businesses that invoice through PayPal. The person who feels the problem is the owner or finance lead who wants recovery automated but has to answer, "Why did the agent do that, and can I stop it?"
Why it matters: when a renewal card declines, the money is already owed. Recovery is where an agent can help most and where a mistake costs the most: a wrong retry, a fourth reminder, or a charge nobody approved. Vasooli shows a recovery that is automatic, bounded by rules the merchant wrote, and proven by PayPal's own signed events. In the demo, a declined $49 payment is recovered end to end, and the matching transaction appears in the PayPal sandbox.
How we built it
- PayPal: Orders v2 for card capture and server-side retries on a vaulted
vault_id; payment tokens for cards on file; webhooks verified withverify-webhook-signatureand stored once per event; Invoicing v2 for invoice creation, partial payments, and recorded payments (to tell PayPal-collected from externally recorded money). - AI (Gemini): a plain-English rules compiler with structured output and untrusted-text fencing, a diagnosis fallback for unmapped decline codes, retries with a fallback model, and cached example rules for resilience. [A read-only studio assistant answers only from ledger queries, with a kill switch and rate limits.]
- Agentic commerce: an MCP server and a REST page share one gateway core with exactly eight allowlisted tools. Dry-run tools write nothing,
execute_recoveryneeds a structuralAuthorizedVerdict, and there are no tools to apply rules, reset data, move the clock, or call PayPal directly. - Backend: Python, FastAPI, MongoDB Atlas, Pydantic. An orchestrator with an injectable simulated clock drives the stages, a loop guard stops failed recovery attempts from creating new revenue at risk, and atomic locks and rate limits are proven on a real MongoDB.
- Frontend: React, TypeScript, AG Grid (ledger and audit grids), [AG Studio dashboard], and a Mission Control page that plays a real run step by step with source badges.
- Hosting: Render (API and static site), MongoDB Atlas.
Challenges we ran into
Making "verified" mean something.** PayPal's invoice-paid event also fires for partial and recorded payments, so I classify each payment by its type, use cumulative amounts, and tolerate out-of-order delivery.
- Retries that can loop. A failed recovery attempt produces a new decline webhook. A loop guard attaches it to the original event instead of creating new revenue at risk.
- Production-only bugs. A field my reconciler wrote was missing from the read model, which broke the live audit trail. I added a write/read symmetry test and real-database tests.
- Honest demos. Sandbox webhooks take about a minute, so I label time compression and simulated time everywhere. Gemini sometimes reports "high demand," so the rules page works from cached examples and retries with a fallback model.
Accomplishments that we're proud of
- A real decline, retry, and signed-webhook recovery running end to end on a hosted service.
- Rules that an LLM can propose but never authorize, with caps enforced in code and old rulebooks always re-derivable.
- A gateway that blocks seven scripted attacks, with every attempt in an audit trail.
- Public responses sanitized, production refusing to start without its guard, and hundreds of automated checks (190+ offline contract checks, 41 adversarial checks, real-MongoDB integration checks, and a frontend test suite).
What we learned
Trust comes from structure, not from prompts: the type system, deterministic checks, and signed evidence do the work, and the model only proposes. Testing on a real database finds the bugs that mocks hide.
What's next for Vasooli
A learning loop that tunes recovery odds from verified outcomes inside the same caps, a human approval inbox, partial-payment counteroffers on PayPal invoices, and more currencies.
Built With
- ag-grid
- ag-studio
- apimatic
- contextmatic
- fastapi
- gemini-api
- invoicing)
- model-context-protocol
- mongodb-atlas
- paypal-(orders-v2
- python
- react
- render
- typescript
- vault
- webhooks