Output drift

Find out nightly whether each agent still answers as it did last week: refusals, answer length, tool mix, escalations, confidence, grounding, rejected writes.

After reading this page you will be able to:
  • Read each agent's output drift and its history
  • Measure drift on demand
  • Alert when an agent's behaviour shifts
  • Tell output drift from input drift

The same model, prompt and tools can start behaving differently: a provider updates the model behind an alias, someone edits a prompt, or a knowledge base loses a collection. Output drift shows that shift before it shows up as a complaint.

Two checks run side by side:

CheckAsksCompares
Input driftDo today's tickets and questions still look like what the system was built for?The day's inputs, embedded and matched to the tenant's approved taxonomy, against the shares the categories were learned from
Output driftDo the agents still answer the way they did?Each agent's outputs in the last window against the days before it

Input drift explains a change in what arrives. Output drift catches a change in what agents do, even when the inputs have not moved. Read them together: output drift with no input drift points at the agent, its model or its knowledge.

What output drift measures

Per tenant and per agent, the last TICKETIQ_OUTPUT_DRIFT_WINDOW_HOURS (default 24) are compared with the TICKETIQ_OUTPUT_DRIFT_REFERENCE_DAYS (default 7) before them:

MetricRead fromTest
tool_mixTrace spans, tool calls by tool nameChi-square
answer_lengthTrace spans, output tokens per model callTwo-sample KS
refusal_rateAnswer records not answeredChi-square
escalation_rateAnswer records escalatedChi-square
confidenceAnswer records by confidence bandChi-square
groundednessAnswer records by grounding verdictChi-square
approval_rejectionThe agent's write approvals that were rejectedChi-square

The score is the population stability index (PSI) of the window against the reference; answer lengths are binned at the reference's deciles. One set of bars reads across every metric:

LevelWhen
okBelow the warning bar, or the test says the shift could be chance
warningPSI at least TICKETIQ_OUTPUT_DRIFT_WARNING (default 0.10) and p < 0.01
criticalPSI at least TICKETIQ_OUTPUT_DRIFT_CRITICAL (default 0.25) and p < 0.01
insufficientFewer than TICKETIQ_OUTPUT_DRIFT_MIN_ITEMS (default 30) on either side

A window with too little data is marked insufficient, never ok.

When it runs

The nightly job (TICKETIQ_OUTPUT_DRIFT_NIGHTLY, default true) runs on the scheduler, at most once every 20 hours. A run stops starting new series after TICKETIQ_OUTPUT_DRIFT_BUDGET_S seconds (default 300) and reports the rest as skipped.

Rows hold counts, shares and scores, never an answer's text. They are kept 180 days, per tenant, under row-level security.

Everything is computed from this instance's own tables: no model or embedding call, so nothing of a tenant's data leaves its region. Input drift, by contrast, embeds each input with the instance's embedding service, held to the tenant's residency.

Read it

Open Evaluations › Drift and judges. Output drift is listed under input drift, worst first, with Measure now to run it for the tenants you can read.

QuestionEndpointPermission
Each tenant's newest output drift rows per agent and metric, the bars, the last runGET /api/evals/output-driftgovernance.read
One series' historyGET /api/evals/output-drift?tenant=<id>&agent=<key>&metric=refusal_rate&days=30governance.read
Measure output drift nowPOST /api/evals/output-drift/rungovernance.write
Input drift rows, or one tenant's historyGET /api/evals/drift (?tenant=&source=&days=)governance.read
Measure input drift nowPOST /api/evals/drift/rungovernance.write

Another tenant's rows are never shown. A manual run is audited as eval.output_drift.run.

Alert on it

Create an alert rule on the output_drift metric (Incidents › Rules, or POST /api/alerts/rules). It reads the worst score in the rule's window, scoped to the fleet, a tenant or an agent. Input drift has its own metric, input_drift.

Limits

  • Evaluator scores over time are not part of output drift. Alert rules on eval_score partly cover them.
  • The reference is a rolling window, so a slow drift over several weeks moves the reference with it.

Next steps