AI AGENT & ACCOUNTS PAYABLE2026

Invoice-to-PO Matcher

An agent that reads vendor invoices, checks every line against the purchase order, and holds anything that doesn't match until a person approves it.

Client
Agent Lab · sample data for Meridian Facilities Co.
Role
Design & Engineering
Timeline
Agent Lab · 2026
01 · Overview

Overview

Accounts payable teams still key invoices in by hand and catch overbilling by luck. This agent reads each vendor invoice PDF, extracts it into a strict schema, looks up the purchase order in the accounting system, and runs deterministic checks on vendor, quantities, unit prices, arithmetic, sales tax and duplicates. Clean invoices wait for one-click approval; problem invoices are held with a plain-English explanation and a suggested action. Nothing reaches accounting without a person's decision, and every decision is logged.

02 · The Problem

The Problem

Three-way matching is slow, repetitive and easy to get wrong. Vendors bill a few percent above the agreed price, charge for more units than were ordered, apply the wrong tax rate, or send the same invoice twice. Letting a language model decide what gets paid is not acceptable either: approvals over money need to be explainable and reproducible.

  • ▸Every vendor formats invoices differently: "PO Number", "Customer PO", "Your order ref".
  • ▸Small overcharges add up and rarely get caught during manual entry.
  • ▸Finance needs to know exactly why something was paid or held, every time.
03 · The Solution

The Solution

The model does what models are good at, reading messy documents, and code does what code is good at, deciding. Extraction is validated against a zod schema and repaired automatically when it fails. The match decision is a pure function with unit tests, so the same invoice always gets the same answer.

  • ✓Model extracts vendor, PO reference, dates, line items, subtotal, tax and total into a validated schema.
  • ✓Code checks the PO exists, the vendor matches, quantities don't exceed the order, prices are within 2%, tax is recomputed from the PO's rate, and the invoice isn't a duplicate.
  • ✓Only held invoices go back to the model, for a two-sentence explanation and a suggested action.
  • ✓A person approves or rejects each invoice; posting the same invoice twice is refused.
04 · Architecture

Architecture

A pipeline on a shared agent runtime: provider fallback, validated structured output, traced tool calls, and a streaming UI that shows every step.

Extraction

PDF text via unpdf, then structured output against a zod schema. Invalid JSON is sent back with the validation errors for up to two repairs.

Accounting adapter

Purchase-order lookup, duplicate search and bill posting behind one interface. A mock stands in for QuickBooks or Xero; a real adapter implements the same three methods.

Deterministic matcher

A pure function that returns each check with a pass/fail and a reason, plus the dollar amount billed above what the PO allows.

Runtime & UI

OpenRouter, OpenAI and Gemini behind one fallback chain with backoff. Every model call and lookup is streamed to a Next.js page over Server-Sent Events.

05 · Key Features

Key Features

Checks you can audit

Each invoice shows the checks run in code, which passed, which failed, and why, next to the original document.

Plain-English holds

Held invoices come with a short explanation and a suggested action, such as asking the vendor for a $60 credit note.

Human approval and audit log

Approve and post, post anyway, or reject. Every decision is recorded, and duplicate posting is blocked.

Live run trace

Every model call, lookup, token count and retry appears as it happens, so reviewers can see exactly what the agent did.

06 · Technology Stack

Technology Stack

AI
GeminiOpenRouterStructured outputsSchema repair
Backend
TypeScriptZodunpdfAdapter pattern
Frontend
Next.js 16React 19Tailwind CSSServer-Sent Events
Quality
VitestScripted fake modelDeterministic rules
07 · My Role

Design & Engineering

Designed and built the agent, the shared runtime it runs on, the sample data and the demo interface.

Key Responsibilities
  • ▪Built the provider fallback chain, tool loop and validated structured output in the shared core.
  • ▪Wrote the matching rules as a tested pure function and kept the model out of the approval decision.
  • ▪Generated seven realistic vendor invoices covering the mismatches AP teams see every week.
  • ▪Designed the review screen and the live trace so the business outcome is clear in seconds.
08 · Screenshots & Product UI

Product UI

Batch results
Seven invoices processed: two ready to post, five held, $208 of overbilling caught.
Price creep held for review
LED tubes billed 6.3% above the PO price, with the dollar impact and a suggested credit note.
Wrong sales tax
Tax is recomputed from the purchase order's rate, not trusted from the invoice.
Approved and posted
A clean invoice approved by a person and posted to accounting, with the decision logged.
09 · Technical Challenges

Technical Challenges

Keeping the model out of the money decision

Challenge: An LLM that decides what gets paid can't be audited and may answer differently on a second run.

Solution: The model only extracts and explains. Approve or hold is a pure function over the extracted data and the PO, covered by unit tests for every scenario.

Reliable extraction from varied layouts

Challenge: Each vendor labels fields differently and models occasionally return numbers as strings or skip fields.

Solution: A strict schema with field descriptions, provider JSON-schema mode where supported, and automatic repair that feeds validation errors back to the model.

Model outages during a batch

Challenge: Providers return 503s and time out under load, which would stall a batch halfway through.

Solution: Per-request timeouts, exponential backoff with jitter, and fallback to the next model in the chain, all visible in the trace.

10 · Outcome

Outcomes & Highlights

On the sample batch the agent posts nothing on its own, clears the two clean invoices for approval, and holds the other five for exactly the right reason each time.

Engineering Outcomes
  • ✓Catches price creep, over-billed quantities, wrong tax, an unknown PO and a duplicate invoice.
  • ✓$208 of overbilling flagged across seven invoices, with a suggested action for each.
  • ✓End-to-end test runs the full batch offline against a scripted model.
  • ✓About 15 seconds for the whole batch on Gemini Flash-Lite.
7/7
Invoices decided correctly

2 cleared, 5 held for the right reason

$208
Overbilling caught

On the sample batch

0
Payments without a person

Every post needs approval