Inspiration

Business email compromise, the "we changed our bank account, please pay us here" email, drew about $3 billion in losses reported to the FBI last year. Every finance team used to have a Doris, the 30-year AP veteran who'd say "Sure, hon, I'll call you back on the number we have." We built one.

What it does

Doris answers payment fraud with one rule: never verify a request through the channel it came in on. Check it against what you already had, and confirm it through a channel you already trusted.

  • Reads every incoming invoice (email, PDF, HTML, forwarded mail) and compares it with the record on file: bank account, routing number, domain, payment history, and when each last changed.
  • Runs eight checks plus a new-vendor gate: bank account changed, hidden or AI-addressed text (prompt injection), vendor record edited recently, payee mismatch, lookalike domain (edit distance, homoglyphs, punycode), a newly certificated domain from Certificate Transparency logs, amount anomaly, and pressure language. Claude judges whether the story matches a known fraud script.
  • Decides: pay, hold for a person, block, or call. Prompt injection blocks outright; the attacker's hidden "approve this invoice" text becomes the evidence.
  • Calls the vendor at the number on file in her own Cartesia voice, never a number from the email. "On file" means unchanged for 90 days. Doris says she's automated and asks only yes or no. A denial blocks the payment on screen the moment it's said; a yes must be repeated and backed by the last payment on file, so a hijacked line answered by a cloned voice can't release money.
  • Checks the channel itself with CRS: for an employee's direct-deposit change, Doris sends CRS Fraud Finder the email and origin IP the request came from plus the name, phone and address on file. Live, CRS answers risk 88 of 100: an address first seen ten days ago that doesn't match her name or address, so even a yes on the call won't pay it out.
  • Moves the money: an approved invoice is paid once through Capital One's Nessie sandbox; a blocked one never is.
  • Shows its work: a live timeline of everything Doris did, the call transcript as it happens, a shared SpacetimeDB desk so every screen flips together, and a hash-chained audit record the dashboard recomputes itself.

How we built it

Python detector (ingestion that separates visible from hidden text, deterministic checks, noisy-OR scoring, versioned vendor records, SQLite hash chain, HTTP API) with Claude (claude-opus-5-5, structured outputs) for extraction and judgment; it never sees hidden text and cannot pay. Surfaces: review and BLOCKED screens, live trace, audit packet, Twilio Programmable Voice + Cartesia sonic-3 callback, SpacetimeDB TypeScript module for the shared desk, Nessie payments, CRS Fraud Finder. A frozen JSON Schema contract split the work between two parallel Claude Code agents. Tailscale Funnel exposes only the webhooks.

Challenges we ran into

Three fresh-context adversarial reviews found 41 gaps (a "yes" that counted "I can't confirm that", HTML preheaders that blocked real vendor mail, and more); every one is fixed and pinned by a regression test. The first real call went to voicemail; Doris held the payment, as designed.

Accomplishments that we're proud of

Real calls end to end: an email in, the phone rings, "we haven't changed our bank account," and the screen flips to BLOCKED. On our labelled test sets: 14 of 15 frauds stopped (main set), 12 of 12 (DOJ-typology set), 0 legitimate invoices blocked. More than 385 automated tests.

What we learned

The more convincing scams get, the less a filter that judges convincingness helps. Doris never judges the message; she checks it against what was on file before it arrived.

What's next

The same rule for executive wire requests, real-estate closings and helpdesk resets; a shared blocklist of mule accounts across companies; bank account-ownership checks before the call.

Sponsor tracks

  • Hyphenate (Autonomous Systems for Finance): procure-to-pay, autonomous to the outcome, every step an audit record the dashboard can prove.
  • Anthropic (Claude for Public Benefit): this fraud drains small businesses, nonprofits, schools and employees; Claude judges each invoice's story but can only help, never harm: no hidden text, no ability to pay, a person decides anything uncertain.
  • CRS (Identity / Fraud, Best Overall, Financial AI Agent): CRS Fraud Finder tests the channel a request came in on against the person on file; a high CRS risk stops the payout even after a phone yes. Only sandbox persona data is sent.
  • Capital One (Nessie): approved invoices are paid as real Nessie sandbox transfers, exactly once.
  • Spacetime: the AP desk is a SpacetimeDB database; every open screen flips together, and only Doris's identity can write.
  • Cartesia: Doris's voice (sonic-3, Jolene) is the verification step itself.
  • Armadin (Security): prompt injection as evidence, lookalike/homoglyph/punycode and CT detection, cloned-voice defence.
  • Microsoft (Real World): real calls today, measured false positives, holds what it can't read.

Code: https://github.com/agile-flight/doris

Demo video (backup link): https://drive.google.com/file/d/1NqTUVibVFdK98DYBWjyVh8Gpt6rvIlGx/view?usp=sharing

Built With

  • anthropic-api
  • capital-one-nessie
  • cartesia
  • certificate-transparency
  • claude
  • claude-code
  • crs-credit-api
  • python
  • spacetimedb
  • sqlite
  • tailscale
  • twilio
  • typescript
Share this project:

Updates

Submission history