Skip to content
Case study · Accounts payable automation

An AP agent that knows when not to pay.

Invoices arrive by email. AI reads them, code checks them against the purchase order, the goods receipt and the vendor master, and each one is either booked in QuickBooks or sent to a person with the reason attached.

Composite Materials Corp
INV CMC-2026-1885 · PO-71463
TAX INVOICE
Industrial solvent, 20L drum436.44
Epoxy resin kit, 5 gal281.96
Corrosion inhibitor concentrate, 55 gal101.24
Protective coating, 1 gal128.82
+ 4 more lines
Total USD$1,832.86
  • Known vendor
  • Valid PO
  • Amount within tolerance
  • Quantity received
  • Not a duplicate
PAID
0invoices paid that the written policy said a person should review, across 392 blind invoices
65.2%paid with no human touch in blind test 2, vs 32.6% industry average
80.4%of blind test 2 decisions matching the written AP policy
~1¢AI cost per invoice processed
01 · The problem

Reading invoices is solved. Deciding which ones to trust is not.

OCR has been around for decades, yet most AP teams still touch two out of three invoices by hand. The work sits in the exceptions: a price that drifted, a short shipment, a vendor name that doesn't match, a bill that arrives twice.

Touchless rate

Average
32.6%
Best
49.2%

Exception rate

Average
14%
Best
9%

Cost per invoice

Average
$9.40
Best
$2.78

Cycle time

Average
9.2 days
Best
3.1 days

Source: Ardent Partners, State of ePayables 2025. Average AP team vs best-in-class.

The opportunity: automate the clean majority safely, and give the AP team every exception with the reason already written.

02 · Diagnosis

First, write the policy down.

Before building anything I wrote the AP policy as six testable rules. Every decision the agent makes, and every test score, traces back to this page.

  1. §1
    Known vendor

    The name must match the vendor master or a registered alias, ignoring case and punctuation.

  2. §2
    Valid purchase order

    No PO, or a PO that doesn't exist, goes to a person.

  3. §3
    Amount within tolerance

    Pay only if the difference is at most 1% and at most a dollar limit that scales with the PO.

  4. §4
    Quantity received

    Billed quantity must match what the warehouse received. Partial shipments are billed pro rata.

  5. §5
    No double payment

    Same vendor, amount and PO as an earlier invoice is a duplicate. Only the first one is paid.

  6. §6
    Readable

    If the amount or date can't be read with confidence, a person reads it.

Try §3 · Amount tolerance
Difference
$80.00 (0.64%)
1% of PO
$125.00
Dollar limit: min($500, max($50, 0.1% of PO))
$50.00
Allowed difference
$50.00
Over tolerance. Sent to a person with the variance attached.
03 · Solution design

Code for facts. AI for judgment.

The model reads documents. It never does arithmetic and never decides whether money moves. Click a step to see what it does and why it is built that way.

CODE deterministic ruleAI Claude Haiku 4.5SYSTEM integration
SYSTEM

Gmail inbox

Polls the AP mailbox every 5 minutes. Every attachment is logged, including zips, empty emails and non-PDFs, so nothing is lost.

Why it's built this way

Logging every email before processing is what turned 69 silent drops into 0.

04 · Try it

Pick an invoice. Watch it get decided.

Seven real invoices from the blind tests, run through the same checks the agent uses, step by step, ending with the decision and the reason a reviewer would see.

Composite Materials Corp
INV CMC-2026-1885 · PO-71463
INVOICE
Real test invoice from Composite Materials Corp, number CMC-2026-1885
  1. ✓
    Intake

    PDF attached, logged

    SYSTEM
  2. ✓
    Extract

    15 units, $1,832.86

    AI
  3. ✓
    Vendor

    Exact vendor match, QuickBooks ID 92

    CODE
  4. ✓
    PO match

    PO-71463 on file, 15 received

    CODE
  5. ✓
    Amount

    $0.00 difference

    CODE
  6. ✓
    Quantity

    15 billed, 15 received

    CODE
  7. ✓
    Duplicate

    No earlier twin

    CODE
Paid automaticallyBill created in QuickBooks. No human touched it.

Real invoice from the blind tests (synthetic company data). The steps show what the system computed and decided.

05 · The build

Built like an AP system, tested like a model.

Every change had to pass a regression gate before it went live. Nothing was tuned on the blind tests.

Stack

n8nPostgreSQLClaude Haiku 4.5QuickBooks Online APIGmailSlackDockerPython eval harness

The eval gate

197 labelled invoices. A change ships only if:

  • zero invoices are paid that policy says should go to a person
  • no more than one invoice gets worse than before
  • all 15 vendor-name probes resolve correctly
  1. v1.0Core agent

    Intake, extraction, three-way match, vendor master with 265 aliases, QuickBooks bills, Slack escalations, resolution form.

  2. GateRegression set reaches 197/197

    Up from 95.4% on the first clean run, with zero false payments throughout.

  3. Blind test 1300 unseen invoices, 51.0% policy match

    No payment the policy said to review, but 69 invoices silently ignored and one double bill. Scored once, then frozen.

  4. v1.1Five fixes, each through the gate

    Never drop silently, code sums line items, longer outputs, check QuickBooks before billing, ignore logo text.

  5. Blind test 2100 new invoices (92 scored), new layouts, 80.4% policy match

    No payment the policy said to review, zero ignored. Answer key hashed before the run and scored once.

06 · Results

Twice as many invoices paid untouched. Still none paid that the policy said to review.

Both tests used invoices the system had never seen, built by a separate process from a written scenario list, with the answer key locked before any invoice was sent.

Touchless rate · share of invoices paid with no human
0%20%40%60%80%Industry average32.6%Blind test 1 · v1.0.133.7%Best-in-class AP49.2%Blind test 2 · v1.165.2%

Industry figures: Ardent Partners 2025, real AP teams. Agent figures: synthetic blind test sets. Directional, not like for like.

MeasureBlind test 1
v1.0.1
Blind test 2
v1.1
Invoices scored30092
Paid when policy said review00
Silently ignored690
Paid with no human33.7%65.2%
Matches written policy51.0%80.4%
Unnecessary escalations8118
Cost per invoice$0.010$0.010
07 · What broke

What broke, and what I did about it.

The first blind test found real failures. None of them paid an invoice the written policy said to review, and each one changed the design.

69

Invoices silently ignored

Cause
Documents titled "Statement / invoice" (35), "Field receipt" (16) and "Credit memo" (15) were classed as not invoices, and 3 emails had no usable PDF. Nobody was told.
Fix
Anything the agent can't process now becomes a review item with a Slack alert.
FIXED IN v1.1 · 69 → 0
1

Invoice billed twice

Cause
QuickBooks timed out after creating the bill. The retry created a second one.
Fix
Before billing, the agent checks QuickBooks for an existing bill with the same vendor and invoice number.
FIXED IN v1.1
90

Quantity totals misread

Cause
The model added up line quantities itself and got it wrong. A cross-check caught every one, but each became a needless escalation.
Fix
The model only reads the lines. Code does the sum. Replaying blind test 1 on v1.1, quantity accuracy went from 56% to 99% (a development set by then, not blind).
FIXED IN v1.1
534

Silent mailbox failures

Cause
The Gmail login expired. Polling failed 534 times and no alert fired, because errors in a trigger never reach the error workflow.
Next
A heartbeat check that alerts when no mail has been read for 30 minutes.
OPEN · v2

One more finding, and it is a gap in the policy rather than a failure of it: in blind test 1, 3 invoices with changed bank details were paid, because the written policy has no bank-detail check. The fix is on the v2 list below (remittance change hold).

08 · Limits and v2

What it doesn't do yet.

  • Statement-style invoices go to a person14 of the 18 blind test 2 misses. Cautious, and the cheapest kind of error.
  • Bank detail changes aren't checkedA common fraud vector. Needs a vendor bank master. In blind test 1 three such invoices were paid.
  • Tested on synthetic invoicesRealistic layouts and scans, but not a real company's mail.
  • v2 · Mailbox heartbeat alertCatch a dead connection within 30 minutes.
  • v2 · Remittance change holdAny new bank details pause payment until verified.
  • v2 · Credit notes and multi-currencyOut of scope for v1 by policy.
About

Ebrahim Tahir Awan. A business analyst who puts AI into operations.

MS Business Analytics, Arizona State University. I scope the process, write the rules, build the workflow and prove it works with tests.