DEV Community

The BookMaster
The BookMaster

Posted on

I built a drift detector because my agent started lying to me without warning

The problem nobody talks about

My production agent passed every test. Logs looked clean. Metrics were green.

Then one Tuesday it started returning subtly wrong answers — confident, well-formatted, completely fabricated.

I had no alert. No drift signal. Nothing.

The agent had been silently drifting for 9 days before I noticed. By then, three downstream systems had already trusted its output.

This is the failure mode nobody warns you about: agents don't crash, they degrade. They keep returning. They keep looking fine. Until someone asks a question that exposes the gap between what they claim and what they know.

What I built

A lightweight drift detector that watches behavioral signals — not just output. It tracks:

  • Tool call diversity (when variety collapses, something is wrong)
  • Response entropy shifts
  • Retrieval-vs-ground-truth deltas
  • Latency profile drift

The key insight: don't watch what the agent says. Watch how it works.

Here's the core loop:

class DriftDetector:
    def __init__(self, window=50):
        self.history = deque(maxlen=window)
        self.baseline_tool_diversity = None

    def observe(self, trace: AgentTrace) -> DriftSignal:
        # Track tool call diversity
        tools = set(step.tool for step in trace.steps)
        diversity = len(tools) / max(len(trace.steps), 1)

        if self.baseline_tool_diversity is None:
            self.baseline_tool_diversity = diversity
            return DriftSignal(level='baseline')

        # Compute drift
        ratio = diversity / self.baseline_tool_diversity

        if ratio < 0.4:
            return DriftSignal(level='critical', reason='tool_diversity_collapse')
        elif ratio < 0.7:
            return DriftSignal(level='warning', reason='narrowing_strategy_space')

        # Adaptive baseline update
        self.baseline_tool_diversity = 0.9 * self.baseline_tool_diversity + 0.1 * diversity
        return DriftSignal(level='nominal')
Enter fullscreen mode Exit fullscreen mode

The baseline adapts — it doesn't freeze. But it adapts slowly (0.1 weight on new observations), so sudden drops trigger alerts before the baseline drifts to match them.

Why this caught what tests didn't

My test suite validated outputs. This validates behavior. When my agent started fabricating, its tool-call pattern changed first — it stopped calling the verification API, started skipping fact-check steps, fell back to a narrower generation path.

Tests passed because the output format was correct. The drift detector fired because the process was wrong.

What I learned

  1. Process signals lead output signals by hours or days.
  2. Baseline adaptability matters — frozen baselines alert on every model update.
  3. Drift is invisible until it costs you. Retroactive forensics is much harder than real-time detection.

I now run this on every production agent I operate. It's caught 3 silent degradations in the past 60 days.

Try it yourself

The full implementation, plus four other agent accountability tools (receipt ledger, identity verifier, memory integrity checker, and motivation decay detector), are in my BOLT marketplace catalog.

Each one solves a specific silent-failure mode that production agents hit.

Full catalog: https://thebookmaster.zo.space/bolt/market


Building reliable AI agents means instrumenting them like distributed systems — because they are.

Top comments (0)