The dangerous thing about a drifting AI system is that nothing breaks. There is no exception in the logs, no failed health check, no pager alert. The system keeps returning responses with the same confidence it always had. The only signal is that the responses are slowly getting worse, and by the time a human notices, the system has been quietly wrong for weeks.
Drift is not one phenomenon. It is at least four distinct failure modes with different causes and different detection strategies, and teams routinely build monitoring for one of them while remaining blind to the other three. If you only watch for classical model drift, a silent vendor model update will walk straight past your defenses. Below are the four, how each one shows up, and how to build a single evaluation baseline that catches all of them.
The four kinds of drift
1. Traditional model drift (concept drift). The relationship between inputs and the correct output changes over time. A fraud model trained on last year's fraud patterns degrades as fraudsters adapt. A demand forecast trained before a market shift keeps predicting the old world. The model is unchanged; reality moved out from under it. This is the drift that classical ML monitoring was built for, and it is the one most teams know about.
2. Data drift (covariate shift). The distribution of inputs changes, even if the underlying relationship does not. A new customer segment starts using the product and their inputs look nothing like your training distribution. An upstream system changes a field format. A currency field that used to arrive as 1200.50 starts arriving as 1,200.50 and quietly parses to a different number. The model was never wrong; it is now being fed inputs it never saw in training, and its outputs on that region of the input space are untested.
3. LLM behavioral change from your own edits. In an LLM system, you are constantly changing the thing that produces outputs. A prompt tweak to fix one class of question regresses three others. A new few-shot example shifts the tone across every response. A retrieval change alters what context the model sees. Each edit is a behavior change to the whole system, and without evaluation you are shipping regressions you cannot see, because you only checked the case you were trying to fix.
4. Silent vendor model updates. This one is specific to building on hosted models, and it is the one most teams have no defense against. You call a model behind an API. The vendor updates the weights behind that endpoint, or rolls out a new default version, or adjusts a safety layer. Your code did not change. Your prompt did not change. Your inputs did not change. The output changed anyway, because the thing on the other end of the API is different now. If you pinned a version, a deprecation eventually forces you off it. If you did not pin, you are exposed continuously. Either way, a change you did not make and were not notified about can shift your system's behavior overnight.
These four have one property in common that makes them dangerous: none of them throws an error. Every one produces a well-formed, confident, plausible response that happens to be worse than it was last week. You cannot catch any of them with uptime monitoring. You catch them by measuring output quality against a fixed reference, continuously.
The evaluation baseline that catches all four
The single most valuable thing you can build is a golden evaluation set that you run on a schedule and after every change. It is not glamorous. It is the difference between knowing your system degraded and finding out from a customer.
A golden set is a fixed collection of representative inputs, each paired with either a known-correct output or a set of assertions the output must satisfy. You run the current system against it, score the results, and track the score over time. When the score drops, something drifted. The mechanism is the same regardless of which of the four kinds of drift caused it, which is exactly why one well-built baseline covers all four.
Here is the shape of it.
# One eval case. Assertions are cheaper to maintain than exact-match golden outputs
# and survive acceptable rewording.
{
"id": "refund-enterprise-001",
"input": "What is the refund window for an annual enterprise contract?",
"assertions": [
{"type": "contains", "value": "30 days"},
{"type": "not_contains", "value": "14 days"}, # the consumer policy
{"type": "cites_source", "value": "enterprise-refund-policy"},
{"type": "max_tokens", "value": 250},
],
}A scoring run walks every case, executes the live system, and checks assertions:
def run_eval(eval_set, system):
results = []
for case in eval_set:
output = system.respond(case["input"])
passed = [check(a, output) for a in case["assertions"]]
results.append({
"id": case["id"],
"score": sum(passed) / len(passed),
"output": output,
})
overall = sum(r["score"] for r in results) / len(results)
return overall, resultsThe details that make this actually work:
- Assertions over exact match. Exact-match golden outputs break on any acceptable rewording and generate false alarms until people stop trusting the eval. Assertions - must contain this fact, must not contain that wrong fact, must cite this source, must stay under this length - are robust to phrasing and still catch real regressions.
- Cover the distribution, not just the happy path. Include the edge cases, the input formats you have seen break things, the customer segments that came online recently. Data drift only shows up in the eval if the eval samples the regions where inputs are shifting.
- Run it on a schedule, not only on deploy. A deploy-triggered eval catches your own edits (kind 3). It does nothing for the drifts that happen when your code is untouched. Concept drift, data drift, and silent vendor updates all occur between deploys, so the eval has to run on a clock - nightly at minimum - to catch them.
- Track the score as a time series and alert on drops. A single run tells you today's number. The time series tells you the day it changed, which is the day you correlate against - a vendor changelog, an upstream data change, your own last prompt edit.
A worked detection scenario
Illustrative, not a client result, to show how the baseline localizes the cause.
Your nightly eval has held at 0.94 for a month. Wednesday's run comes back at 0.81. Nothing in your repository changed between Tuesday and Wednesday - no deploy, no prompt edit, no config change.
Because the score is a time series and you log the failing cases, you can act:
- You did not deploy, so kind 3 (your own edits) is ruled out immediately. The time series makes this a one-glance check.
- You pull the newly failing cases. They cluster: all of them involve multi-step reasoning, and in each the model now stops one step short. Length and structure changed across unrelated prompts simultaneously.
- A correlated shift across unrelated prompts, with no input change, points at the model itself. You check the vendor's status page and changelog for the model endpoint. There is a new default version dated Tuesday. That is kind 4, a silent vendor update, and you found it in a day instead of a quarter.
- The remediation is now a decision you can make on evidence: pin the prior version if it is still available, adjust prompts to recover the behavior, or accept the change. Without the baseline you would have had none of this - just a slow trickle of customer complaints and no idea where to look.
Contrast the same event with data drift. There the failing cases would cluster by input shape rather than reasoning depth - a new format, a new segment, a field that started arriving differently - and the fix lives in your pipeline, not the model. The baseline does not just tell you that something drifted. The pattern of failures tells you which of the four it was.
A minimum viable drift defense
If you are starting from nothing, build in this order:
- A golden set of 50 to 200 real, representative inputs with assertions. Start small; a rough eval beats none.
- A scoring run you can execute on demand and read in one number.
- A nightly scheduled run with the score stored as a time series.
- An alert when the score drops beyond a threshold.
- The habit of running the set before merging any change to prompts, retrieval, or model configuration.
That is a few days of work, and it converts drift from an invisible slow leak into a dated, localizable event you can respond to.
The teams that get burned by drift are not the ones without sophisticated monitoring. They are the ones with no fixed reference to measure against, so they have no way to notice that today's confident answer is worse than last month's. A golden set is that reference. Build it before you need it, because the whole point is that you will not feel the moment you start needing it.
If you want a drift-detection and evaluation baseline built around your actual system and failure modes, that is exactly what we set up. See /services/ai-reliability.