How we cut KYC verification from days to hours with a document agent
Confidence thresholds, exception routing, and what still needs a human. What we learned building document verification for a partner network of thousands.
July 14, 2026 · 4 min read · Solution Architect
When we started on the partner onboarding program for a large-scale energy enterprise, verification was the slowest stage in the pipeline by a wide margin. A partner would register, attach a stack of documents, and wait. Somewhere in a regional office, a person would open each file, compare it with a checklist, look up a registration number on a government portal, and forward the whole thing to an approver. Days, routinely. Longer when that person was on leave.
We timed it before we touched it. That turned out to be the most important decision in the program, because the instrumented baseline showed the delay was not in the checking. It was in the queueing. Documents waited for a person far longer than a person spent on them.
What a document agent actually does
The phrase suggests something more magical than the thing we built. A document agent is a pipeline. A document comes in. We classify it: is this a trade license, a tax registration, a bank letter, an identity document? Classification matters because every document type has its own extraction schema and its own reference checks.
Then extraction. For each type we define the fields that matter: registration number, legal name, issue date, expiry date, issuing authority. The model reads the document and returns those fields with a confidence score per field, not per document. That distinction saved us. A tax certificate where the name is read cleanly but the expiry date is smudged should not pass or fail as a whole.
Then cross-checking. Extracted fields are compared against what the partner typed into the registration form, against reference lists where they exist, and against each other. The legal name on the bank letter should match the one on the license. The expiry date should be in the future. A mismatch is not a failure. It is a flag with a reason.
Thresholds and the exception queue
Every field score is compared to a threshold, and the thresholds are per field type, not global. We set them conservatively at first, high enough that early on most documents went to a reviewer, and lowered them field by field as the review data showed where the model was reliable.
Anything with a field below threshold, or any cross-check that fails, goes to the exception queue. The reviewer sees the document image, the extracted fields, the score on each and the flag that sent it there. They confirm, correct or reject. Their correction is logged against the original extraction, which is how we know where the model is weak.
The queue is prioritized, not first-in first-out. A document blocking a high-value partner sorts above one for a renewal three months out. Reviewers work the top of the list. This is the part that most directly attacks the waiting-time problem, and it has nothing to do with the model.
What still needs a human
More than we expected, and for reasons that were not about model accuracy.
Some documents are genuinely ambiguous. A scanned license with a handwritten amendment. A bank letter in a format nobody has seen before. The model’s low confidence is correct, and a person needs to look.
Some decisions are policy, not fact. A partner whose documents all pass but whose registered address is in a jurisdiction the compliance team has questions about. No threshold handles that. We built an explicit rule to route it, and the rule is owned by compliance, not by us.
And some steps must be signed by a person because the regulator says so. We did not try to argue with that. The signature is one click on a screen that shows what the system found, and the click is logged with the person, the time and the version of the rules in force.
Trade-offs we made
We chose per-field confidence over per-document confidence, which made the pipeline more complex and the review screen busier. Worth it, because the alternative sent whole documents back for one bad field.
We chose to keep humans on all document types for the first weeks even where the model scored well, so we could build the correction dataset that let us lower thresholds with evidence. This was slower to show results and harder to defend in a steering meeting than “automate everything on day one”. It also meant the thresholds we ended up with were ones the compliance team had watched being earned.
We did not build automatic re-training. Corrections are collected and reviewed by us; threshold changes are deliberate and logged. Continuous learning sounded attractive and would have made the audit trail unexplainable.
Failure modes
Document quality. Photographs of documents taken on a phone at an angle, in poor light, remain the single largest source of exceptions. The fix is partly model, mostly product: the upload screen now rejects blurred images before they enter the pipeline.
Reference sources going down. Some government portals are unreliable. We cache reference lookups with a validity window and treat a missing lookup as “route to reviewer”, never as “pass”.
Threshold drift. When a new document format appears in a region, scores drop and the exception queue swells. We now watch queue depth per document type per region, which tells us about a new format before anyone reports it.
What we would do differently
Instrument the reviewer’s screen from day one. We instrumented the pipeline and learned late that reviewers spent longer on the screen than on the decision, because the flag reasons were too terse. Rewriting them in plain language was a small change with a large effect.
And we would push harder, earlier, to get the upload experience right. Half the exceptions we were proud of resolving should never have been created.