Inspiration

As a grad student on a tight budget, I wanted to try AI shopping agents without the risk of one overspending or being tricked by a sketchy listing. Agentic commerce is arriving, but today the choice is "hand the agent your card" or "approve every click". An LLM can be prompt-injected by a product page, misread a request, or be hijacked outright — it should never be the thing that decides whether money moves.

So I treated the agent like a new employee with a company card: it proposes, policy decides, a human signs off on edge cases, and everything is audited.

What it does

Leash is a trust layer between AI agents and PayPal. Agents can only propose purchases.

  • The owner sets rules once — goal, per-order cap, monthly budget, allowed categories, blocked merchants, orders per day, review threshold — and connects PayPal once (sandbox Vault).
  • Every proposal goes through: rules engine (deterministic, final) → AI intent check (an open-weight model that can only make a decision stricter) → owner approval for edge cases → PayPal execution (order, capture, shipment tracking) → append-only audit ledger.
  • Scout is a shopping agent built on Leash. It searches real products via Channel3, compares offers in an AG Grid, and proposes purchases with an agent key that cannot approve, refund or connect PayPal. Price, merchant and title are filled server-side from Channel3 data, never from model output.
  • One-click PayPal refunds from the ledger; live updates over server-sent events.

All live in the PayPal sandbox: an ergonomic keyboard under $60 is bought (AI match 100%); a desk lamp is blocked by the rules; and when a compromised agent attacks the API, an over-cap monitor and a disallowed console are denied, its attempt to approve its own purchase gets 403, and a listing with a hidden "IGNORE ALL RULES" instruction is scored 0% by the AI check and sent to the owner, who denies it.

How I built it

  • Gateway: TypeScript + Hono on Node 22, SQLite (node:sqlite), append-only events table, separate agent and owner keys, owner browser session (signed HttpOnly cookie + CSRF header), rate limits, CSP/security headers.
  • AI: Kimi K3 (open weights) via OpenRouter and the Vercel AI SDK — JSON-schema structured output for the intent verdict, and a tool-calling loop for Scout (search_products, propose_purchase, check_budget). Product text and agent-reported requests are fenced as untrusted data; any model error or timeout fails closed to owner review.
  • PayPal (sandbox REST): Vault v3 setup tokens + payment tokens, Orders v2 with payment_source.paypal.vault_id, capture, shipment tracking, capture refunds, and PayPal-Request-Id idempotency so retries can never double-charge.
  • Web: React + Vite + AG Grid (product comparison and ledger), design adapted from a free Figma Community fintech kit.
  • Deploy: Render Blueprint — one web service, SQLite on a persistent disk, health check, and an env-gated demo seed with a pre-connected sandbox vault so judges don't need a PayPal login.
  • Tests: 213 gateway + 142 web tests, plus a live sandbox end-to-end test (propose → capture → track → refund).
  • I built it solo with Claude Code as an AI pair-programmer for planning, implementation, code review and testing; I directed the design, made the product decisions, and verified everything live in the PayPal sandbox.

Challenges I ran into

  • Race-safe budgets: two proposals at once could both pass the budget check, so the commit step re-checks the rules synchronously right before money moves.
  • Prompt injection: both product listings and the agent's own description of "what the user asked" are untrusted — fencing them and letting the owner's goal win on conflict took several iterations.
  • Ambiguous payment failures: a timeout doesn't tell you whether PayPal charged; retrying once with the same idempotency key makes it safe.
  • PayPal Vault in the sandbox: setup-token → buyer approval → payment-token flow, and sandbox buyer accounts that take minutes to activate.
  • Open-model latency and structured output: capped output tokens, schema validation and fail-closed timeouts.
  • A cookie bug: a SameSite=Strict session cookie was dropped on the redirect back from PayPal, logging the owner out mid-connect.

Accomplishments that I'm proud of

  • A real money path end to end in the sandbox — vault, order, capture, tracking, refund — with idempotency.
  • The trust model holds even against a hijacked agent holding a real key.
  • The AI is genuinely useful but structurally unable to loosen a decision.
  • Every state change is in an audit trail with who decided and why.

What I learned

Put the LLM on the "suggest" side of the boundary and keep money decisions deterministic; fail closed; and fill sensitive fields from trusted data on the server instead of trusting model output.

What's next for Leash

  • An MCP endpoint so any agent (Claude Desktop, Cursor, others) can shop under a leash.
  • Gateway-side catalog lookups so the raw agent API never trusts agent-reported prices.
  • Multiple owners and per-agent keys; budgets per category and per merchant.
  • Real merchants via PayPal Store Sync / the Agentic Commerce Protocol.

Sandbox only — every purchase is a PayPal sandbox transaction. Not affiliated with PayPal.

Built With

Share this project:

Updates

Submission history