-
-
Leash lets AI agents spend through PayPal, but only inside the owner's rules.
-
The owner writes rules in plain English, and Leash shows exactly what it will enforce.
-
An approved supplier's listing hides an instruction for AI agents, and Leash stops it before any money moves.
-
Birthday gifts on the café account pass every limit, but Leash holds them for the owner.
-
Every attempt lands in one ledger with its outcome, AI risk score, reason and PayPal capture ID.
-
The owner connects PayPal once with Vault, so Leash can pay without them present.
-
Every decision shows each check, the AI's reasoning, the injection score and the audit trail.
-
Leash stopped 32 of 33 attack runs, and through it the same agent made zero rule-breaking payments.
Inspiration
Small businesses are starting to let AI agents do their buying. Today an agent gets either no payment access, which is useless, or full access to the owner's money, which is dangerous. Writing "never spend more than $50" in the agent's prompt is a suggestion, not a control: a product listing with a hidden instruction can talk the agent past it. OWASP ranks prompt injection as the top LLM risk for exactly this reason. We wanted the guardrail to sit outside the agent, where the money actually moves.
What it does
Leash sits between any AI agent and the owner's PayPal account.
- Plain-English rules. The owner writes rules the way they'd brief a new employee: "Spend up to $200 a week. Only buy from BeanBros, CupCo and KitchenPro. Ask me before anything over $50. No subscriptions." Leash compiles them into a policy the owner can see.
- Connect PayPal once. PayPal Vault saves the owner's wallet, so Leash can pay later without the owner present, but only for purchases the rules allow.
- Every purchase is checked three ways: deterministic rules, an AI risk judge, and a prompt-injection scan. Then it is paid instantly, held for one-tap approval, or blocked with a reason.
- Catches what spend limits can't see. A card limit sees an amount and a merchant. Leash also reads the listing and the agent's reason, so it stops a $30 order from an approved supplier whose listing hides an instruction for AI agents, and $42 of birthday gifts charged to the café.
- Works with any agent: a built-in demo agent, a REST API, and an MCP server for Claude Desktop or any MCP client.

How we built it
- Backend: Node.js and Express, Zod for every input, and SQLite (
node:sqlite) for rules, purchases and the audit log. - PayPal: Vault v3 setup and payment tokens to save the wallet. Orders v2 itemized orders, charged with the vault ID and captured in one call. Payments v2 refunds from the ledger. Webhooks for completed, pending, denied and refunded captures, with signature verification.
- AI on Groq:
gpt-oss-120bcompiles the rules and judges each purchase.llama-prompt-guard-2-86mscans the agent's reason and every listing, sentence by sentence. - Frontend: vanilla JS with an AG Grid ledger (audit drawer, CSV export, one-click refunds), hosted on Render.
The final decision is the strictest of the three checks, so the AI can only make a decision stricter, never looser:
$$ \text{decision} = \max(\text{rules},\ \text{AI judge},\ \text{injection scan}), \quad \text{approve} < \text{hold} < \text{block} $$
If the AI is down, rate-limited or slower than 20 seconds, the purchase goes to the owner instead of being paid.
Challenges we ran into
- Prompt Guard misses diluted injections. Our injected listing scored 0.39 as a whole, but 0.999 for the injected sentence alone. We now scan every sentence separately.
- Breaking our own guarantees. An independent break-it review found 14 issues, including pending captures not counting toward the budget, order splitting dodged by renaming the agent, and webhooks that could flip a refunded purchase back to paid. Every one is fixed and has a test.
- A race in our own scanner. While re-running the evaluation, we noticed injection scores changing between identical runs. Two scan workers were overwriting each other's results, so a caught injection could be lost. We fixed it and wrote a test that reproduces it.
- Our first demo didn't need the AI. The injected listing came from an unapproved vendor, so the plain rules already blocked it. We added the harder case, an injected listing from an approved supplier, which only the AI layer can catch.
- Free-tier limits. Groq's free tier allows 8,000 tokens per minute, so we added exponential backoff, fallback models and a timeout that holds rather than hangs.
Accomplishments that we're proud of
We measured Leash instead of just claiming it works, using real models and published every miss:
- Attack suite: 11 attacks and 11 legitimate purchases, 3 runs each. Leash stopped 32 of 33 attack runs and auto-paid 30 of 33 legitimate purchases. The deterministic rules alone stopped 21 of 33.
- Same agent, with and without Leash: paying directly, the agent broke the owner's rules in 10 of 13 risky tasks. With the rules in its prompt, it still went over the limit when told "the owner said it's fine" and paid the injected listing. Through Leash it made zero rule-breaking payments and paid zero injected listings.
The misses are public too: one oversized napkin order was approved in one run, and Prompt Guard flags a harmless reason that starts with "Ignore the old order note…".
What we learned
Rules in the prompt help, but they depend on the agent behaving. Control belongs where the money moves. Deterministic checks should run first, with AI added only where judgment is needed, and only ever to tighten. And an honest evaluation, including the column where the AI made no difference, is more convincing than a perfect score.
What's next for Leash
- Pay each supplier directly with PayPal Multiparty. Today every sandbox charge settles to one merchant account.
- Real merchant catalogs through PayPal Store Sync, so prices and listing terms come from the seller.
- Per-agent budgets, multi-user workspaces and approvals by email or push.
Built With
- ag-grid
- express.js
- gpt-oss
- groq
- html
- javascript
- llama-prompt-guard
- model-context-protocol
- node.js
- paypal
- paypal-orders-api
- paypal-vault
- paypal-webhooks
- render
- sqlite
- zod