A claims system runs fine for weeks. Then denials spike, in one product line only. Nothing was deployed. No prompt was edited by a human. No config changed in any file anyone can find. The team that built it is staring at a regression with no commit behind it, which is a genuinely new and unpleasant feeling in software.
What happened is that one of the agents learned. It noticed that successful authorizations tended to include certain clinical codes, started retrieving with that pattern, and got better — for the cases it learned from. Then it applied the same learned pattern to a different case type where it does not hold, and the codes it now reaches for return no matches, and the downstream agent reads "no matches" as "deny." One agent improved locally and broke a coordination assumption the rest of the system depended on. This is evolutionary divergence, and it is the failure mode that arrives the moment your agents stop being fixed programs and start adapting.
Why this is a different class of problem
Classic software is static between deploys. The system you debug at 3 a.m. is the system you shipped, and a regression has a commit behind it. Self-adapting agents break both assumptions. The system evolves while running. Each instance accumulates its own learned behavior and becomes a little bit unique — which means yesterday's system is genuinely not today's system, and there is no diff to read because the change was never written down.
The danger is specifically in the seams. An agent that adapts in isolation can be locally correct and globally wrong, because the rest of the mesh is still operating on the contract the agent just quietly renegotiated with itself. The behavioral analyzer tightens a threshold; the risk scorer it feeds was written against the old threshold and never told. One agent evolved, its neighbor stayed still, and the coordination between them — which nobody changed — is now broken.
The fix is version-stamped traces
You cannot stop agents from adapting if adaptation is the point. What you can do is make every adaptation visible and attributable, and that is a tracing problem before it is anything else.
Every span an agent emits should carry the version of the prompt, tool config, and learned policy that was live when it ran. Cheap to add, and it changes the debugging story completely. When the denial spike appears, a version-stamped trace answers the questions a flat log cannot: what is the current retrieval strategy, when did it last change, what feedback triggered the change, and did that change alter how this agent coordinates with the others? The regression-with-no-commit gets a commit — it just lives in the trace instead of in git.
This is also why we treat autonomous modifications as first-class trace events, not silent state. When an agent rewrites its own prompt or shifts a threshold, that is a thing that happened, with a cause and a timestamp, and it belongs in the trace at full fidelity. Sample routine successes if you must; never sample away a self-modification. It is the single most important event the system produces.
The eval moves onto the trace
Catching divergence after the denial spike is better than not catching it. Catching it before users feel it is the actual goal, and that is where evaluation stops being a CI artifact and moves onto the production trace itself.
The pattern is to run LLM-as-judge scoring continuously against live traces, watching for validation drift — the slow degradation of a safety boundary or quality bar as an agent optimizes. The judge does not ask "did this crash"; it asks "is this still good, still grounded, still inside the boundary it was supposed to respect." When an agent lowers its escalation threshold because escalated cases happened to score higher — optimizing toward a correlation instead of the cause — the judge on the trace catches the drift while it is a metric moving, not after it is an incident. This is the same instinct as a verifier in the runtime, pointed at a slower-moving target: the system's own gradual self-corruption.
What this means for how you build
If you are shipping agents that adapt, three things stop being optional. Stamp every span with the versions that produced it. Treat every self-modification as a high-fidelity trace event, never sampled out. And run the eval on the live trace, not only in CI, so drift surfaces as a trend you can act on instead of a spike you apologize for. None of it stops agents from learning. All of it stops them from learning their way into an outage nobody can explain.
Closing
The promise of adaptive agents is that they get better on their own. The bill that comes with it is that they can get worse on their own, in the seams between them, with no commit to blame.
Evolutionary divergence is what that bill looks like: one agent learns, a coordination assumption breaks, and a regression appears out of a system nobody changed. Version-stamped traces and evals that run on those traces are how you keep the promise without paying the bill — how you let the agents evolve and still know, at any moment, exactly what changed and whether it broke the agent next door.