01 Problem
Document-heavy processes are still handled by people reading a PDF and typing its contents into a business system. The work is slow, hard to audit, and error-prone in ways that only surface downstream. Automating the reading is the easy part; the difficulty is producing data a business is willing to act on.
02 Context
Input arrives as scans, exported PDFs, photographs, and — in some cases — structured files that happen to be delivered as documents. Quality varies per source and per sender. The output has to land in systems of record, where a wrong value is more expensive than a missing one.
03 Requirements
04 Constraints
OCR and model calls are external, variable in latency, and occasionally fail. Model output is probabilistic and cannot be assumed correct. Documents may contain sensitive data, so storage and access have to be deliberate rather than incidental.
05 Architecture
The platform is a pipeline of explicit stages over a persisted job. Each stage reads the job state, does one thing, and writes the next state — so any stage can fail and be resumed without repeating the ones before it.
Document
│
Ingestion idempotent key
│
OCR / Structured source
│
Extraction deterministic → AI
│
Validation rules + confidence
│
Human review approval boundary
│
Approved data
│
Business system / Salesforce06 Key decisions
Asynchronous processing with persisted jobs
Processing outlives any single request, and state survives restarts.Deterministic path before the probabilistic one
When a structured source is available, parsing it is cheaper and exactly repeatable. Models handle what is left.Model completion is not approval
A finished extraction is a proposal. Approval is a separate, recorded act.Idempotent ingestion on a client key
Callers can retry safely; duplicates collapse onto the same job.Signed webhooks with recoverable failures
Consumers verify origin, and undelivered events remain replayable.07 Trade-offs
The asynchronous design adds state and operational surface: more to observe, more to reason about, and a client integration that cannot be a single blocking call. Keeping a human in the path bounds throughput deliberately. Both costs were accepted because the alternative is silently wrong data in a system of record.
08 Reliability
09 Human-in-the-loop
Review is a state in the pipeline, not a screen bolted onto it. Fields arrive with their source location and a confidence signal, so a reviewer can go straight to what is uncertain instead of re-reading the document. Corrections are stored alongside the original extraction, which makes them useful later as evaluation data.
10 Evaluation / benchmarks
OCR engines and extraction configurations are compared on a fixed set of documents with known correct values, per field rather than per document, so a change that improves totals but breaks dates is visible. Reviewer corrections feed the same set. The purpose is to make configuration changes decidable by measurement instead of impression.
11 Integration
Consuming systems integrate over an authenticated API and signed webhooks. On the Salesforce side, approved data maps onto records through an integration boundary that owns the translation, so the document platform stays independent of any one target model.
POST /documents → 202 { job_id } idempotency key
GET /documents/{id} → { state, fields, confidence }
webhook document.approved signed · retried · replayable12 Lessons learned
Making the processing state explicit mattered more than the choice of queue or model. Once every document had a durable state, reliability became a question of moving between states correctly.
Confidence is only useful when it is attached to a field and a location in the document. Aggregate scores tell a reviewer nothing actionable.
The AI part of an AI system was not where most of the design effort went. Ingestion, state, validation, review, and delivery were.