Project Overview
This case study documents a claims document processing system we built for a property and casualty carrier operating in several EU markets. The carrier's motor line receives around 16,000 claim bundles a month, averaging nine documents each, and adjusters were sorting and re-keying them by hand. Compliance had ruled out hosted model APIs, claim bundles carry named individuals, medical records, adjuster notes, and material that may end up in litigation, so the pipeline runs entirely on the carrier's own GPUs with open-weight models. It reached production on the motor line thirteen weeks after kickoff.
The architecture is a classify, extract, route pipeline. Inbound bundles are split into documents, each document is classified, a typed field set is extracted per document type, and the result is pushed into the claims system behind a confidence gate that decides what an adjuster sees. High-confidence extractions on low-risk document types post directly; everything else lands in a review queue segmented by reason. At steady state, 63 percent of documents auto-route with no human touch.
The same stack, pointed at a different schema, now also serves the carrier's underwriting submission intake, which went live six weeks after the claims rollout as a schema and evaluation exercise rather than a new build.
Why the Bundles Defeated Generic Document AI
A first notice of loss rarely arrives as a document. At this carrier it arrives as a bundle: an FNOL form, a stack of phone photos of a bumper, a repair estimate, a police report, a medical bill, and a broker email chain, often flattened into one PDF with arbitrary page order. An adjuster sorted it mentally and re-keyed the fields that mattered, and that re-keying cost scaled linearly with claim volume.
The carrier had trialed a generic document AI tool before engaging us, and it failed structurally rather than marginally. It treated the bundle as one document and asked a model questions about it, but a bundle is a container, page order carries no meaning, and the same logical field appears in several places with legitimately different values: the estimate says one number, the supplement another, the invoice a third. The trial tool averaged contradictory sources confidently. Extraction has to run per document, per type, with provenance, which is what we built.
The second constraint was regulatory, and by the time we were engaged it had collapsed into one requirement: the documents do not leave the network. A processing addendum with an external inference vendor was not going to soften that, and we did not try.
What We Built: Classify, Extract, Route
Ingestion normalizes everything the carrier receives: mailbox drops, portal uploads, SFTP batches, and scanned mail. We take native text where the PDF carries it and fall back to Tesseract OCR only on pages that are genuinely images, since OCR is the most expensive and lossiest step and should be paid for per page, not per bundle. Photos are split out early and travel as attachments with metadata.
Classification runs at page level, then segments the bundle into documents. Particula-Classify does this work, because a per-page label with calibrated confidence is a better primitive than one bundle-level guess. Extraction then runs per document type against a fixed schema, with Particula-JSON constraining decoding so the model cannot emit malformed output or invent a field. Amounts and estimate line items pass through Particula-Finance before reaching the router.
Routing is deliberately dull. A rules layer maps typed fields to operations on the claims system, and every routed record carries its confidence, its source page, and the model version behind it. High-confidence extractions on low-risk document types post directly. Everything else lands in a review queue segmented by reason, so a reviewer sees the field in doubt beside the page it came from, not a whole bundle.
We deliberately left things out. There is no vector database in this pipeline, because extraction is a schema problem, not a retrieval one. We did not start with fine-tuning, because constrained decoding, a tight schema, and a real gold set cleared the accuracy gates, and a fine-tuned model becomes a maintenance liability the moment document formats shift. And there is no agent framework: this is a pipeline, and the code looks like one.
The Stack We Deployed
We kept the stack small and boring on purpose. Every component below is one we were willing to debug at two in the morning inside the carrier's network, with no internet access and nobody to escalate to. The selection favors open weights, inspectable interfaces, and pieces the carrier's platform team could operate after handover, which they now do.
| Layer | What We Deployed | Why This Choice |
|---|---|---|
| Model serving | vLLM on 2x NVIDIA L40S | The 32B at 4-bit fits one 48 GB card with headroom; the second carries throughput peaks and failover |
| Extraction model | Qwen 2.5 32B Instruct, 4-bit quantized | Open weights, strong structured output, sized to the card rather than the other way around |
| Page intake | Native PDF text extraction, Tesseract OCR fallback | OCR runs only on genuinely scanned pages, so cost tracks image volume |
| Classification | Particula-Classify | Per-page type labels and bundle segmentation with calibrated confidence |
| Field extraction | Particula-JSON | Grammar-constrained decoding to a per-type schema; output is valid by construction |
| Domain normalization | Particula-Finance | Currency, amount, and line-item handling for estimates and invoices |
| Services and packaging | FastAPI, Docker, PyTorch | Inspectable, deployed onto the carrier's existing container platform |
| State and audit | PostgreSQL | One queryable store for labels, fields, confidences, and reviewer actions |
Security and Compliance Controls
The inference tier has no outbound route. Weights were delivered offline, serving runs with telemetry disabled, and the GPU nodes sit on a segment where egress is denied by policy, not by convention. This is the control the carrier's compliance team actually tested: they read the firewall policy and confirmed it. The line holds even for pages that look harmless, because nobody knows what a page holds until it is classified.
Inside the boundary, fields are tagged as personal or medical at schema definition time, so retention and access policy attach to the field instead of the document. Bodily injury and medical documents route into a separately access-controlled queue. Derived artifacts, the OCR text, page images, and extraction payloads, inherit the retention clock of the source claim, and the deletion path shipped in the first release rather than being promised for later.
Auditability was a design constraint, not a log level. PostgreSQL holds every page, label, field, confidence score, threshold in force, and reviewer action, keyed so any posted value can be reconstructed months later, and model versions are pinned behind a re-evaluation gate. The EU AI Act places risk assessment and pricing for life and health insurance in its high-risk tier, and GDPR Article 22 constrains solely automated decisions, so coverage and liability calls are informed by the pipeline, never executed by it. That boundary is written into the routing rules, not left to practice.
How the Rollout Ran
The rollout took thirteen weeks to production on the motor line, sequenced so the riskiest unknown resolved first. That unknown was never the model; it was the claims system. Week one was integration discovery: which interfaces existed, who owned them, and what change control governed them. The system exposed no usable API, only a batch staging interface on someone else's release calendar, so we targeted that, the dullest reliable interface available, and proved it end to end with dummy records inside the first fortnight. Model work ran in parallel.
Triage design was a workshop, not a config file. We agreed explicitly with claims leadership what auto-routes and what always reaches a human. Auto-routing covers structured FNOL fields, policy and claimant matching, document type labels, and estimate line items under an agreed threshold. Human review stays mandatory regardless of confidence on total loss, bodily injury, fraud indicators, litigation, and any bundle where two documents disagree on a material field.
Cutover was gated, not scheduled. The pipeline ran in shadow against live volume while adjusters worked exactly as before, and we compared its output with what humans actually keyed. Go-live was gated on field-level parity per document type against an adjudicated gold set built from the carrier's own bundles, and on a review queue small enough for the staffed team to clear daily. Both gates were met in week twelve, and the motor line cut over in week thirteen. Underwriting submission intake followed six weeks later on the same platform: an application, loss runs, a schedule of values, and broker correspondence arrive as the same kind of bundle, so the work was a new schema and rule set, not a new build.
Results
At steady state, 63 percent of incoming documents auto-route into the claims system with no human touch, at field-level precision above 97 percent on the key fields of each document type, measured against the adjudicated gold set and the ongoing shadow comparison. Accuracy is reported per field and per document type, never as one blended number, because a pipeline that reads policy numbers perfectly and estimate line items badly has an average that tells nobody anything. Precision and recall are tracked separately, since a missed field and a wrong field cost differently.
For adjusters, the sorting work is gone: bundles arrive pre-segmented with typed fields attached, and average intake handling time per bundle fell from roughly twenty minutes to under seven. The review queue is doing its job as a filter rather than a bottleneck, sized by reason so the staffed team clears it daily, with reviewers confirming or correcting single fields beside their source pages instead of re-reading bundles.
Calibration is what keeps the auto-routing honest. Confidence thresholds were tuned against reliability curves per field family and an error budget the carrier's claims leadership agreed to, and human override rate is the primary drift signal. It has already earned its keep: when a large repair chain changed its estimate format, the override rate on estimate line items climbed within days, the affected type was pulled back to review, and the extractor was updated and re-cleared through the same eval gate. Mandatory-review categories, total loss, bodily injury, fraud indicators, and litigation, never auto-post regardless of confidence, and that rule has not moved since the triage workshop.
- Insurance
- On-Premises AI
- Document Processing
- Claims Automation
- Underwriting Intake
- Compliance


