Inspiration

A friend of ours lost hundreds of dollars when his personal agent misunderstood a request and kept spending. Agents like Meta's Muse can already book, buy, and check out for you, and they will only get more capable. But an agent that reads the open web can also be misled by a hidden instruction or a fake invoice, or simply get the task wrong.

It matters for credit unions because a payment your own agent makes is an authorized payment, and authorized payments get far less protection than unauthorized ones. We wanted a way for a credit union to stand between an agent and a member's money before anything is spent.

What it does

Escrow gives a shopping agent a one-task virtual card in place of access to a member's account.

  1. The agent proposes a task and budget ("weekly groceries, $80, grocery only").
  2. Agent A checks that the request makes sense for this member. It compares the request to their transaction history. Gambling, crypto, and gift cards are denied outright. Anything unusual, like a new spending category, a budget far above their norm, or a $100,000 boat on a Tuesday morning, goes to the member for approval first.
  3. The card is minted. The agent gets a card number backed by held funds, and never the real account or routing number.
  4. The agent shops, but nothing is bought yet. It builds a cart and submits it.
  5. Agent B reviews the whole cart. If a hidden instruction slipped a TV or a gift card in, the cart is rejected and sent back with what to remove. The agent fixes it and resubmits, and this repeats until the entire list passes.
  6. Escrow buys once and closes the card. Unspent funds go back to the member, and any further charge is hard-blocked.

Normal requests like groceries go through with no friction. The member is only interrupted when something looks unusual.

How we built it

  • Backend: TypeScript with Hono and Zod. The vault runs as a state machine over a task, a card, and a cart, and every step is written to an audit log.
  • Agent A and Agent B: Deterministic rules decide. Agent A checks restricted categories, category familiarity, a per-task cap, and the budget against the member's largest past purchase. Agent B classifies every cart line by what the item actually is, and it never trusts the category label the agent supplies. Unrecognized items are rejected.
  • Jev (TypeSafe System One): A model layer that can only make the rules stricter. It can flag a request that doesn't look like the member's history and reject items that look off-task. It can never override a failed rule, and if it times out the system falls back to rules alone.
  • Card network simulator: A simulated card network with fake money, so we can show real declines for closed, expired, off-task, over-limit, and pre-approval charges.
  • Member-only controls: Overrides, history, and the audit log require a member token that the agent never has, so a compromised agent can't approve its own request.
  • Frontend: React and Vite phone-style app plus a live transaction trace, with an automatic "leak scan" that checks every agent-visible message for real account identifiers.
  • Deployment: Vercel, with per-session state in Upstash Redis so every judge gets their own sandbox.

Challenges we ran into

  • Not trusting the agent. The agent is exactly what might be compromised, so its self-reported categories and justifications couldn't be inputs. Agent B classifies items itself, and anything it can't recognize fails closed.
  • Making the AI layer safe to use. A model can be wrong in either direction. We let it only tighten decisions, which meant designing Agent A and B so deterministic rules always have the final say.
  • We can't verify the user's original words. The shopping agent writes the rules and budget, and nothing on our side can confirm they match what the person actually asked. So our check is narrower: does this purchase make sense for this member?
  • Defining "suspicious" with limited data. Our history signals are simple heuristics (new category, budget versus past spending), and a real credit union would tune them on its own data.
  • Keeping state across serverless calls. The vault needed to survive across invocations without judges sharing state, so we built it to snapshot into Redis.
  • Keeping the frontend and backend aligned. The backend imports its types from the frontend contract so the two can't drift.

Accomplishments that we're proud of

  • A leak-proof boundary we can demonstrate. An end-to-end test runs the real frontend client through the whole flow and scans every agent-visible response for account numbers, routing numbers, and member IDs.
  • Safety properties we test, not just claim. A randomized test runs sequences of operations and checks that money is never overspent, never spent outside checkout, and always conserved.
  • A compromised agent can't help itself. It has no way to approve its own override, wipe the log, or spend from a closed card.
  • Friction only where risk is. Groceries clear silently, while the boat request goes to the member.
  • Honest about the limits. We say up front what Escrow doesn't catch.

What we learned

  • Where the control sits matters more than how smart the detector is. Putting the gate before the money moves changes the whole problem.
  • A model is best used to make decisions stricter, not to make them.
  • For agents, the safest design is to never give them anything worth stealing, rather than trying to catch every bad action.
  • Authorized scams are hard because the transaction looks legitimate, so the right intervention comes from context, not from the payment itself.

What's next for Escrow

  • Learning from history. The default ruleset should update as a member's history grows, using their own percentiles in place of fixed caps.
  • Merchant-level checks. Use real merchant category codes at authorization, on top of cart contents.
  • An MCP server so any agent that supports MCP can request an Escrow card from a member's credit union.
  • Real member authentication for approvals and richer, plain-language approval messages.
  • Extending beyond shopping to bills and subscriptions, and to the scam flows the challenge brief names, such as account takeover.

Built With

  • agentic
  • agents
  • ai
  • api
  • cards
  • commerce
  • credit
  • defense
  • fintech
  • fraud
  • grok
  • guardrails
  • injection
  • llm
  • multi-agent
  • perplexity
  • plex
  • prevention
  • prompt
  • react
  • rest
  • typescript
  • virtual
  • vite
Share this project:

Updates