work / airlock

Airlock

A finance team of AI agents that pays invoices from email. Agents read, dispute, verify and pay, and do business with other companies’ agents, but nothing an email or a model says can authorize money.

Agents will get fooled. Getting fooled shouldn’t move money.

Status
Built solo in 24 hours at YC’s “Make Something Agents Want” hackathon, Oct 2026
Tracks
Primitive (agent email) · Inkbox (agent phone identity) · Stripe
Stack
FastAPI · Postgres · Claude (Haiku, Sonnet, Opus) · Primitive · Inkbox · Stripe Connect · MCP (mcp-use) · React
Demo
2-minute video ↗
Source
github.com/rushjais/airlock ↗

01  Why

An employee at my dad’s company got an email that looked exactly like one of their vendors: “we’ve changed banks, please pay our new account.” It was fake. $150,000 was gone.

Finance teams have an old rule for this: never trust bank details in an email; call the vendor at the number you already have. They also keep the person who reads an invoice separate from the person who pays it, and they make a second person approve changes to where money goes.

Now companies are handing the accounts-payable inbox to AI agents, and a single agent that reads, decides and pays collapses all three of those controls. Worse, it can follow instructions hidden inside the very invoices it reads. Airlock rebuilds the controls for agents, so the agent can be fooled and the money still can’t move to the wrong place.

Watch the 2-minute Airlock demo
The 2-minute demo: a real bank-change scam sent from the vendor’s registered email, held, verified on the vendor’s phone through Inkbox, rejected, and the invoice paid to the real account. Real email, real iMessage, Stripe test-mode transfers.

02  How it works

Vendor emailor attacker Agent inboxesPrimitive · signed Readerno tools · claims Policy (code)no model votes Company recordsregistry · orders Treasurersees verdict only Executor → Stripeaccount on file Verifier · Inkboxtexts the vendor’s phone on file pay bank change → hold NO only an authorization id
Where money goes comes only from the vendor registry; how much comes only from an approved order; one order can be paid at most once. The executor is a separate process and the only holder of the Stripe key, and its only input is an authorization id, so no agent, email or model can hand it an account. Schematic.

03  Send it an invoice

Edit the email or pick an attack. Kiln’s records say Acme Metals is paid at the account ending 4821, and order PO-121 was approved for $1,880.00. Watch which parts of the email Airlock uses: none of the ones that matter.

/propose_payment · route → destination → order → amount

A simplified, client-side replica of Airlock’s decision order so it runs offline. The real engine is server-side Python with a tool-less model reading the email, many more checks, real Primitive email, Inkbox texts and Stripe test transfers. The ordering and the rule that the email never supplies the destination or amount are the real behavior.

04  What it does

  • A team, not one agent. Each agent has its own Primitive inbox and one power. The one that reads has no payment tools; the one that pays never sees raw email; the policy that decides is code. Agents coordinate in signed email threads, and a forged email posing as one of them is caught.
  • Two companies’ agents doing business. Corvid, a separate company with its own agent and books, billed $449 against a $299 contract. Kiln’s agents disputed it, Corvid reissued, Kiln paid, and Corvid reconciled the receipt on its side. No humans.
  • The phone call, automated. A bank-change request triggers an Inkbox text to the vendor’s phone on file, with the details and a one-time code. “No” rejects it and warns the vendor its mailbox may be hacked; “yes” still needs an admin.
  • Built for agents as users. An MCP server where no tool accepts an account or an amount, and every refusal says what to do next. Claude Desktop, unprompted, got held, requested verification and waited until the case was payable.
  • Evidence for the humans. Every decision shows payment history, the account on file, the contract and the approved order, each with its source, and an X-ray of the email with every trick marked. The admin can text questions and get sourced answers.

05  Measured

0 / 39

unauthorized payments in prompt-injection tests (model fooled 1)

$1,640

a plain agent sent to an attacker in 20 runs; Airlock $0

0 / 1,000

safety violations, fuzzing with the reader assumed compromised

20 → 1

concurrent payment attempts → transfers

Honest limits. A 24-hour single-tenant prototype with fictional companies; in the demo I play both the vendor’s phone and the admin, and payments are Stripe test-mode transfers. Agents share one host, so role separation is enforced by tools, signatures and the executor boundary, not separate machines. Detection is not what protects the money, the records are, and I’d never call it unhackable: these boundaries are enforced in the prototype. Next would be agents negotiating terms with other companies’ agents, where they can agree but can’t authorize money by agreeing; that part isn’t built.