An AI document-review system can be fully “up,” passing every health check, answering every request, and still be making worse decisions than it made yesterday. In one incident, a production system ran with degraded judgment for 53 hours before anyone noticed, because nothing that measures uptime measures judgment. That gap is now closed with four layers of monitoring that check judgment directly: config hashing, a prompt-length floor, a verdict-vocabulary gate, and a statistical drift alarm on approval rate, checked every 15 minutes.
Why uptime monitoring missed it
Standard infrastructure monitoring answers one question: is the service responding? Response codes, latency, error rates, queue depth. All of it was green for the full 53 hours. The API was up. Requests completed. Documents got a verdict: approve, reject, or escalate. Every dashboard a typical ops team watches said the system was healthy.
What actually happened was quieter and worse. A prompt template had been edited during a routine cleanup and deployed without anyone flagging it as a judgment-affecting change. The new version was still valid, still produced parseable output, still returned verdicts inside the expected schema. It just reasoned less carefully. An instruction block that told the model to check lien status against the extracted document text before approving had been shortened during the edit, and the model quietly started leaning on defaults instead of verifying. The approval rate crept up. Nobody was watching approval rate in real time, because approval rate is a business metric, not a system metric, and the team responsible for uptime doesn’t own it.
It surfaced when a downstream reviewer, doing a routine spot-check on a batch of already-approved deals, found three in a row with lien discrepancies that should have blocked approval. That’s a human catching a symptom two days after the cause. The postmortem traced it back to the exact deploy timestamp: 53 hours of degraded judgment, invisible to every system that was supposed to be watching.
The core problem: judgment doesn’t fail like software fails
Software either crashes or it doesn’t. A model that’s a little less careful than it should be doesn’t throw an exception. It just makes slightly worse calls, at a rate that looks like noise until you have enough volume to see the trend, and by the time you have enough volume, you’ve already processed the damage.
Key insight
Judgment degrades on a gradient, and a gradient produces no alert unless something is specifically watching for the gradient.
This is the structural reason “the AI is a black box, I can’t trust it” is the wrong complaint, and “I have no way to see when it changes” is the right one. The model itself isn’t inherently unstable. What’s unstable, without deliberate engineering, is everything around it: prompts get edited, config drifts between environments, upstream data pipelines change shape, and none of that shows up on an uptime dashboard. We’ve written before about the audit trail work that makes each individual decision explainable after the fact. Monitoring judgment in production is the other half of that problem: catching the moment the population of decisions starts drifting, not just explaining one decision after someone complains.
What actually catches drift: four layers
1. Hashed config snapshots, diffed like git
Every prompt template, rule set, and model parameter that can affect a verdict gets hashed on every deploy, and that hash is logged against a timestamp the same way a git commit is logged against a SHA. When something looks off in the output, the first question is no longer “did anything change?” (nobody remembers) but “show me every hash change in the last 72 hours,” which is a query, not an investigation. This is the single highest-leverage layer because it turns “what changed” from forensic archaeology into a lookup. It would have cut the 53-hour incident down to whatever it took to notice the approval-rate shift, because the config diff would have been sitting there waiting.
2. A prompt-length floor alarm
This one is deliberately crude and that’s the point. If the assembled prompt sent to the model for a given document type drops below a set character-length floor, something upstream broke: a template edit dropped a clause, a document field failed to populate, a context-injection step silently returned empty. A prompt that’s supposed to carry title text, lien status, and verification instructions and suddenly carries a third of that length is a system that’s about to reason with less information than it needs, and it fires before a single bad verdict goes out the door. It’s not a sophisticated check. It’s cheap, it runs on every single call, and it would have caught the instruction-block truncation that caused the 53-hour incident in the same minute it deployed, not two days later.
3. A verdict-vocabulary gate
Every verdict the system emits has to come from a fixed, small vocabulary: approve, reject, escalate, and a bounded set of reason codes underneath each one. If a verdict comes back with a reason code that isn’t in the approved set, or free text where a code should be, or a confidence phrasing that doesn’t match the expected pattern, it’s rejected and routed to a human before it ever reaches a customer or a deal record. This one exists because a model that starts drifting doesn’t just get the verdict wrong, it often starts explaining itself differently first: hedging language creeping into what used to be a clean “reject: lien mismatch” is an early signal, and the vocabulary gate is what turns that signal into a stop rather than a shrug.
4. Statistical drift alarms on approval rate, every 15 minutes
The approval rate for each document type and deal type is compared against its own trailing baseline on a 15-minute cycle, not daily, not weekly. A move outside the expected statistical band, in either direction, generates an alert with the affected document type and time window attached. This is the layer that closed the actual gap: the same class of incident that took 53 hours to surface manually is now caught inside 15 minutes, because the system is asking the business-metric question (“is this population of decisions behaving like it did yesterday?”) on a clock, instead of waiting for a human to notice during a spot-check.
We covered the mechanics of one specific version of this failure, a race condition rather than a prompt edit, in a full postmortem of a 10-point approval-rate drop: same detection principle, different root cause, which is exactly the point. The alarm doesn’t need to know why approval rate moved. It needs to fire when it moves.
How this differs from evaluating a model before launch
Pre-launch evaluation, benchmark sets, red-teaming, accuracy testing against a labeled holdout, answers a different question than production monitoring does. Eval tells you the model is good enough to ship. It says nothing about whether the thing running six months from now is still the thing you evaluated. Prompts get tweaked for a different edge case and nobody re-runs the full eval suite for a two-line change. A model provider updates a model version behind an API endpoint. A document intake pipeline changes a field name and half the context silently goes missing. None of that shows up in a benchmark score, because the benchmark already ran, once, before any of it happened.
We’ve written separately about the discipline of running two model versions side by side before a migration so the switch itself doesn’t introduce blind drift. That’s the pre-deploy control. The four layers here are the post-deploy control, and a system needs both: shadow runs to catch a bad swap before it goes live, and continuous drift monitoring to catch degradation that happens after everything already looked fine at launch.
What this costs to run
None of these four layers requires a research team or a custom ML monitoring platform. Config hashing is a checksum on deploy. The prompt-length floor is a threshold check on every call. The vocabulary gate is a schema validator. The statistical drift alarm is a rolling-window comparison, the kind of thing a basic anomaly-detection library handles out of the box. The cost is mostly discipline: deciding upfront that judgment gets monitored the same way uptime does, wiring the four checks into the pipeline, and routing their alerts to someone who owns the business metric, not just someone who owns the servers. Compare that cost against the alternative: a 53-hour window where every approved deal is a liability nobody has quantified yet, discovered by luck during a spot-check instead of by design.
FAQ
How do you detect LLM drift without ground truth labels?
You don’t need labeled “correct” answers for every case to catch drift. You need a stable baseline for indirect signals: approval rate by document type, verdict-vocabulary compliance, prompt length, and reason-code distribution. When any of those moves outside its normal statistical band, that’s the drift signal, independent of whether you know the ground-truth answer for any individual case. Ground-truth spot-checks still matter for confirming what caused a detected drift, but they’re not what triggers the alarm.
What metrics catch prompt degradation fastest?
The prompt-length floor is the fastest, because it fires on the very first call after a bad deploy, before any verdict goes out. The verdict-vocabulary gate is close behind, since degraded reasoning often shows up as hedging or off-pattern language before it shows up as a wrong outcome. The statistical drift alarm on approval rate is the slowest of the four by design (it needs enough volume in a 15-minute window to be statistically meaningful) but it’s the one that catches degradation the other three don’t have a rule for yet.
If your review team is still relying on someone noticing a bad batch during a spot-check, that’s the same blind spot this post describes. Deskflow builds these monitoring layers into the document-review workflows it runs, so judgment drift gets caught on a 15-minute clock instead of a lucky one.