All builds Book a call
Healthcare · optometry · HIPAA · Wichita Family Vision · Bedrock live 2026-09-16

Invoice filing for a clinic's bookkeeper: HIPAA-compliant on Claude via AWS Bedrock, at 0.9 cents an invoice.

The bookkeeper keyed every vendor bill by hand and filed PDFs into 184 folders. Now a vision model reads each one, proposes the folder, and waits for her click, on a HIPAA-compliant path.

0.9¢ per invoice, 3.4 seconds a file, measured on Claude Sonnet 4.6 in the clinic's account 26,904 input and 2,003 output tokens for 12 files at Bedrock on-demand pricing: $0.11 a run.
12 of 12 synthetic invoices read correctly on 2 models, rotated scans included
The review table: 12 files, proposed names and folders, vendor read, date, amount, and a note per row
The review page on 12 synthetic invoices. Amounts are invented; nothing moves until Go.
What was broken

Before

Every vendor bill arrived as a PDF or a scan. The bookkeeper read each one, typed it into QuickBooks, and filed it by hand into one of 184 vendor folders. The owner's goal was plain: cut her weekly hours in half. The catch: some documents carry patient names, and consumer chat tools carry no HIPAA agreement, so the obvious tool was the wrong tool.

What I built

The build

What changed

Before and after

Before

By hand
Reading a billEyes, then keyboard
FilingHand-filed into 184 folders
The accounting entryTyped into QuickBooks
Patient-named documentsSame pile as everything else
Cost per invoiceBookkeeper minutes

After

The system
Reading a billVision model, 3.4 s a file
FilingProposed, reviewed, one click
The accounting entryQuickBooks capture, no AI
Patient-named documentsFlagged, filed, never sent on
Cost per invoice0.9 cents of model time
Where the numbers come from. Measured on 2026-09-16 in the clinic's AWS account: 12 synthetic invoices, 26,904 input and 2,003 output tokens on Claude Sonnet 4.6 at $3 and $15 per million, $0.11 a run, 0.9 cents an invoice, 3.4 seconds a file. The same 12 files read identically on Haiku 4.5 at about 0.3 cents. The hours saved will be measured on her real volume after the install.
For engineers

How it's built

Architecture
A local Python runner: PDF pages to PNG at 150 DPI (3 pages max), one prompt with two backends (Bedrock for production, OpenRouter for synthetic tests only), a deterministic vendor matcher (exceptions, normalized exact, unique containment), a plan step that names files and resolves collisions, a review page on 127.0.0.1, then move, log, and queue for QuickBooks.
Where it runs
On the bookkeeper's PC against the clinic's network drive. Only the reading step leaves the building, to Bedrock in the clinic's own AWS account (us-east-1), under the AWS BAA. Stephens AI operates it through an access key scoped to one inference profile.
Tests and evals
12 synthetic invoices mirroring her real nine plus the untested cases: 5 rotated image-only scans, a bare-date receipt, a paid invoice, a statement with a period end, an unknown vendor, a same-name collision, 2 patient-data documents. 12 of 12 on Sonnet and on Haiku. Full run, undo, and the browser Go path all proven.
Cost and latency
0.9 cents an invoice on Sonnet 4.6, about 0.3 on Haiku 4.5. At any plausible clinic volume that is $2 to $13 a month of AWS.
Guardrails
HIPAA: a business associate agreement between Stephens AI and the clinic, the AWS BAA on the clinic's own account, retention set to none in Bedrock, logging off, the Anthropic use-case form filed. No patient name is ever written to the log or the proposal. Nothing is deleted or overwritten, ever; the tool never creates a folder; a stop-on-first-failure move with a full undo.
The tradeoff we chose
Why this way and not the other

We moved off Claude Team and Cowork mid-build. They are the easier surface, and the first version ran there, but neither carries a BAA, so the runtime could never read a patient-named file. The Bedrock path costs a compliance program and a Windows installer; it is the only path where the clinic's data stays inside its own boundary. Also chosen: QuickBooks' own capture for the accounting entry, because a model should not touch a ledger when a deterministic feature already does it.

Keep going