The starting point
Invoices and other recurring documents arrive as attachments, download links and files. Reading each one, re-typing its fields and checking them — does the total add up, did the amount change since last time — is slow and easy to get wrong by hand.
What we were responsible for
We designed and built the product: the processing pipeline, the model calls and field parsing, the rules, the Gmail integration, the web app and its hosting.
What we built
-
Classify and extract
A background worker works out what kind of document each file is and extracts its fields — line items included, as a table — with Claude. Values the model was unsure about are shown as such.
-
Rules the user defines
Each document type has its own checks: a number against a simple calculation, a field against the previous document of the same type, line items in aggregate. The checks are deterministic code, not another model call.
-
Corrections without losing history
Any value can be corrected. Classifications, extractions, corrections and check runs are append-only, so a re-check creates a new run and older results stay as they were.
-
Gmail as an inbox
A connected mailbox is checked every five minutes. Matching emails become documents; with no attachment, the file is fetched from its download link or the email is saved as a PDF. The verdict comes back as a Gmail label.
-
Export
Every document of a type downloads as a CSV.
Why it was hard
-
Models are uncertain
Extraction is probabilistic, so rules run as plain code on top of it and doubtful values are surfaced rather than trusted.
-
Email is messy
The document can be an attachment, a link or the email itself. Links that sign in, unsubscribe or confirm something are never followed.
-
Restricted access to mail
OAuth tokens are held by a connection service, never by the app, and the app only reads mail and sets labels — it never sends, moves or deletes.
Where it stands
Upload and Gmail intake, classification and extraction, user-defined rules, corrections with full history and CSV export are built, with a separate public site and legal pages.
- Document arrives Uploaded, or picked up from a connected Gmail inbox.
- Classified The document type is worked out from the content.
- Fields extracted Values and line items, with doubtful ones marked.
- Checked against rules Deterministic checks defined for that type.
- Verdict delivered Shown in the app and set as a label on the email.
A value is corrected The document is checked again as a new run; history is kept.
