All projects

Mailroom Reloaded

Agentic document pipeline · deployable rebuild

At a glance

2 LLM calls for a clean text-layer document (sort, then extract)

1,597 tests passed, 3 skipped, in the main-branch verification run (the suite has 1,134 test functions in 83 files by grep)

The problem

My Digital Mailroom design routes incoming documents: decide what each one is, pull out the fields that matter, and file it with a record of what happened. Agent frameworks make that easy to prototype and hard to run. If the model decides what happens next, you cannot say in advance how many calls a document will cost, where a crash will leave it, or why it ended up in a given folder.

Mailroom Reloaded is a rebuild of that design as a single deployable service, built around one rule: code owns the control flow, and models are called at fixed points.

Approach

The pipeline is a CrewAI Flow, but a deterministic driver walks it, not CrewAI’s event engine. A clean text document goes through local ingest, the ModernBERT fast path from Mailroom-ML, one sorter call, a gate, one specialist extraction call, a second gate, and then report, catalog and archive. The gates are plain threshold code with zero LLM calls. That is why the cost of a clean document is exactly two calls.

When a gate is not satisfied, fixed rules pick the next step, and the two gates have different branches:

The ModernBERT fast path runs first and fails open. If the package or model is missing, the input is oversized, or anything errors, the pipeline falls back to a full LLM sort instead of stopping.

What I built

Results

I have no accuracy or cost numbers to publish for this service yet. The harness exists and is tested, but I have not committed evaluation results, so I am not quoting any. What I can show is that the machinery runs end to end: the main-branch verification ran four seeded documents through the stack with a mock provider and all four archived, and eleven browser checks of the replay viewer passed.

A dark terminal-style page with a large cyan MAILROOM banner and the status bar showing theme dark/cyan. The command replay run:7e57d0c0ffee --at 90 is running, paused at 01:30.0 of 02:15.0. Station rows are grouped under intake_sort, extraction, review, reporting and terminal, each with a dotted progress bar and a count. Sorter, specialist, judge and review are cyan, gate and archive are green, boss and failed are red, intake is grey, and a red marker sits on specialist. A scrub bar and a line reading docs 4 of 6, done 3, failed 1, tok 680, $0.0060, calls 4, first-pass 25% sit below, followed by a row of key hints.

The /tui replay viewer in the cyan theme, paused partway through a recorded demo run, with per-station document counts, a scrub bar and a metrics line.

The same cyan terminal page at the end of the run, 02:15.0 of 02:15.0, with an inspector panel open under the station grid and metrics line. It shows the document's station archive, status archived and attempt 1, then an event table with two rows: 00:30.4 gate_decision gate and 00:30.7 retry gate, with cyan event names.

The replay inspector in the cyan theme, on a document that went through a gate decision and then a retry.

A cyan terminal page with a table with columns seq, kind, run, doc, ts and hash, with cyan column headings. Rows are one pinned entry, one run_opened entry and four doc_closed entries. Below the table, the text 6 entries, then the command ledger verify, then a green line reading chain ok, 6 entries, head #6, and a grey line reading merkle: run not closed.

The ledger command in the cyan theme, listing six hash-chained entries, followed by a successful chain verification.

Heads up. The screenshots come from a demo run on a mock LLM provider with seeded documents, so the counts and costs in them describe the demo, not model quality.

What I learned

Stack

Python CrewAI Flows FastAPI SQLite ModernBERT OpenTelemetry Phoenix Prometheus Grafana Docker Compose vLLM pytest