# LLM monitoring in production: what to watch, and how failures become tests

> Source: <https://www.evalshift.dev/blog/llm-monitoring>
> Published: 2026-11-13 21:57:19.410674+00:00

[← all posts](https://www.evalshift.dev/blog)

# LLM monitoring in production: what to watch, and how failures become tests

LLM monitoring in production: the metrics to watch, online evals and what they cost, alerting on rates, OpenTelemetry's status, and the tools compared.

LLM monitoring is watching an application built on a language model while real users are on it: whether calls succeed, how long they take, what they cost, and whether the answers and actions are still the ones you tested. The first three are ordinary monitoring with new units. The fourth is the hard one, because a wrong answer comes back with the same status code as a right one.

Most guides to LLM monitoring stop at the dashboard. This one covers the signals worth watching and how each is computed, what it costs to score a sample of live traffic, how to alert on a rate without paging someone over noise, where the OpenTelemetry standard stands, and the tools as their docs and pricing pages read in November 2026. It ends with the step most setups skip: turning a production failure into a test case, so the next change is checked against it.

A disclosure: I build EvalShift, which is not a monitoring tool. It covers the testing half of that last step, and it has a short section near the end. The rest works with any tool.

## What LLM monitoring is

Three terms get used for overlapping things, and the tools blur them further.

|  | Question it answers | When it runs | Output | 
|---|---|---|---|
| LLM monitoring | Is something wrong right now? | Continuously, on live traffic | Metrics over time, and alerts | 
| LLM observability | Why did this request go wrong? | On demand, after an alert or a complaint | A trace: every model call, tool call and retrieval in one request | 
| Offline evaluation | Will this change make things worse? | Before release, on a fixed set of cases | A comparison of two versions | 

Monitoring is built on observability data: you cannot chart tool-call errors if tool calls are not recorded as spans. So one product does both, and "LLM observability platform" and "LLM monitoring tool" name the same list of vendors.

Monitoring and offline evaluation feed each other. Monitoring sees real inputs and has no
expected answer for them. [Offline testing](https://www.evalshift.dev/blog/llm-testing) has expected answers and only the
inputs someone thought to collect.

## Why ordinary APM misses LLM failures

An application performance dashboard watches status codes, latency and throughput. An LLM application can fail while all three look healthy.

**A failed response returns 200.** Anthropic's
[stop reason docs ↗](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons)
say a refusal arrives as "a normal HTTP 200 response, not an error", with `stop_reason` set to
`refusal`. Google's
[API reference ↗](https://aistudio.google.com/api-reference/generate-content) lists more than twenty
finish reasons on a successful response, among them `SAFETY`, `MAX_TOKENS`,
`MALFORMED_FUNCTION_CALL` and `TOO_MANY_TOOL_CALLS`. OpenAI's
[chat completion object ↗](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create)
carries a `refusal` field on the message and a `content_filter` finish reason. None of these moves
an error-rate chart.

**A wrong answer has no field at all.** A reply that invents a refund policy, or an agent that
issues the refund without looking up the order, finishes with a normal stop reason. The only way
to count these is to check the content.

**Cost is a property of each request.** A one-line question and a long agent task hit the same
endpoint and cost very different amounts. A loop in an agent shows up on the invoice before it
shows up anywhere else.

**Behavior changes without a deploy.** In September 2025 Anthropic published a
[postmortem ↗](https://www.anthropic.com/engineering/a-postmortem-of-three-recent-issues) of three
infrastructure bugs that degraded Claude's responses. One misrouted 0.8% of Sonnet 4 requests when
it was introduced on August 5, and 16% in its worst hour on August 31. Anthropic wrote that "the
evaluations we ran simply didn't capture the degradation users were reporting", and that it would
start running quality evaluations continuously on production systems. If the provider's own
checks can miss a regression in the model you call, your deploy log will not show it either.

## LLM monitoring metrics: what to watch

Five groups. The first two are what an APM tool already does, in different units. The last three are specific to LLM applications.

| Group | Signal | How to compute it | 
|---|---|---|
| Operational | Error rate by type | Failed model calls over all model calls, split into rate limit (429), provider error (5xx), timeout and invalid request (400) | 
| Operational | Latency | p50 and p95, for the whole task and for each model call | 
| Operational | Time to first token | For streamed replies, time from the request to the first chunk | 
| Operational | Rate-limit headroom | Remaining requests and tokens, read from response headers | 
| Cost | Tokens per task | Input, output and reasoning tokens summed over every call in the task | 
| Cost | Cost per successful task | Tokens times price for each token type, summed, divided by the tasks that succeeded | 
| Cost | Cache hit rate | Input tokens read from cache over total input tokens | 
| Quality | Deterministic check pass rate | Code checks on every output: it parses, matches the schema, has the required fields | 
| Quality | Judged quality | An LLM judge on a sample, one pass-or-fail criterion at a time | 
| Quality | User feedback | Thumbs, edits, retries and escalations to a human, per session | 
| Quality | Refusal and truncation rate | Responses by stop or finish reason | 
| Agent | Tool-call error rate | Tool executions that raised or returned an error over all tool executions | 
| Agent | Steps per task | Model calls and tool calls per task, p95 as well as the median | 
| Agent | Loops | Tasks that repeat a tool call with identical arguments, and tasks that hit the step cap | 
| Change | Model served | Responses counted by the model the response names | 
| Change | Provider notices | Deprecation pages and changelogs, checked on a schedule | 

### Operational signals

Split errors by type before you chart them, because the responses differ. A 429 means back off or
raise a limit, a 5xx means retry or fail over, and an invalid request after a deploy means your
request shape is wrong. Current models reject parameters that older ones accepted, so the same
error can arrive with [a model upgrade](https://www.evalshift.dev/blog/llm-testing).

Rate limits can be watched before they bite. Anthropic's
[rate limit docs ↗](https://platform.claude.com/docs/en/api/rate-limits) list response headers such
as `anthropic-ratelimit-input-tokens-remaining` and `anthropic-ratelimit-output-tokens-remaining`,
plus `retry-after` when a 429 carries one. Chart the remaining share at peak hour and you see the
ceiling before users do.

For anything streamed to a person, time to first token is the latency users feel. Total duration grows with the length of the answer.

### Cost signals

Measure cost per task, not per call. An agent task is several model calls plus tool results fed
back in as input, and a cheaper model that takes one more round per task can cost more.
[The cheapest LLM API](https://www.evalshift.dev/blog/cheapest-llm-api) works through that arithmetic.

Count cached tokens separately, or the cost chart is wrong. In Anthropic's
[prompt caching docs ↗](https://platform.claude.com/docs/en/build-with-claude/prompt-caching), the
`input_tokens` field holds only the tokens after the last cache breakpoint, and the total is
`cache_read_input_tokens + cache_creation_input_tokens + input_tokens`. Cache reads are billed at
0.1 times the base input price or less, and a five-minute cache write at 1.25 times. A
prompt edit that moves the cache breakpoint can multiply input cost without changing the request
count, and the cache hit rate is the chart that shows it.

### Quality signals

Run code checks on every response. They cost nothing and never disagree with themselves: the output parses, it validates against the schema, the order ID from the input appears in the reply. Refusals and truncations come free with the response, so count responses by stop reason too.

User feedback is the signal closest to the truth. Do not rely on thumbs alone: add the implicit signals your product already has, such as the user rephrasing the same question, editing the draft before sending it, or asking for a human.

For everything else, such as groundedness and whether the question was answered, the option is an LLM judge on a sample. That has its own section below.

### Agent signals

An agent adds failures that sit between the model call and the reply. A tool execution fails, and the model may recover or may tell the user it worked. A task loops on the same search until it hits the cap.

Chart the tool-call error rate per tool, steps per task at p95, and the count of tasks that hit
your step limit. All three need tool calls recorded as their own spans, which is the first thing
to check in a tracing library.
[Agent evaluation metrics](https://www.evalshift.dev/blog/agent-evaluation-metrics) has the definitions, and
[evaluating agent tool calls](https://www.evalshift.dev/blog/evaluating-agent-tool-calls) covers why the reply alone hides
these failures.

### Change detection

Record the model that answered, not only the model you asked for. Each provider's response names
it: OpenAI's `model` field is "the model used for the chat completion", and Gemini's
`modelVersion` is "the model version used to generate the response". OpenAI also returns a
`system_fingerprint`, which "represents the backend configuration that the model runs with".

This matters because the two can differ. Google's [model docs ↗](https://aistudio.google.com/docs/models)
say a `latest` alias points to the newest release and is swapped with two weeks' notice by email,
and its [changelog ↗](https://aistudio.google.com/docs/changelog) records `gemini-pro-latest` and
`gemini-flash-latest` switching to the Gemini 3 previews on January 21, 2026. The same changelog
says that from December 1, 2026, requests to `gemini-2.5-pro` will automatically route to
`gemini-3.8-flash`, and requests to `gemini-2.5-flash` to `gemini-3.5-flash-lite`. Those requests
will keep returning 200.

So chart responses by the model named in the response, and alert when a value appears that was
not there yesterday. Then put the provider's retirement dates in a calendar. The
[deprecation schedule](https://www.evalshift.dev/blog/llm-model-deprecation-schedule) lists them for OpenAI, Anthropic and
Google.

## Online evals: scoring a sample of live traffic

An online eval is a check that runs on production traces after they are logged. Every platform in
the table below has the same three controls: a filter for which traces to score, a sampling rate,
and a choice between a code evaluator and an LLM judge. They run in the background.
Braintrust's [docs ↗](https://docs.braintrust.dev/observe/score-online) say evaluations run
"asynchronously in the background without adding latency to your application".

Sampling is the cost control. Arize's
[online eval guide ↗](https://arize.com/docs/ax/evaluate/online-evals) suggests 100% for low-volume
or critical applications, 10 to 50% for high volume and 1 to 5% for very high volume, starting at
10 to 20% until you trust the evaluator. LangSmith's
[example ↗](https://docs.langchain.com/langsmith/online-evaluations) is a rate of 0.1, and
Datadog's is 10%.

### What a judge on production traffic costs

There are two bills: the judge model's tokens, and whatever the platform charges for holding the result.

For the tokens, Langfuse's
[LLM-as-a-judge docs ↗](https://langfuse.com/docs/evaluation/evaluation-methods/llm-as-a-judge)
estimate $0.01 to $0.10 per assessment, depending on the judge model and the size of the input.
Take 100,000 traces a month, score 10% of them with two judges, and you run 20,000 assessments:
$200 to $2,000 a month at that estimate. Score every trace and it is $2,000 to $20,000.

The platform side, as of November 2026:

- +**Langfuse** counts every score as a billable unit, alongside traces and observations.
- +**LangSmith** has no per-score charge, but a new online evaluator[upgrades the traces it scores ↗](https://docs.langchain.com/langsmith/usage-and-billing) to
180-day retention unless you opt out, at $2.50 per 1,000 on top of the base trace price.
- +**Braintrust** counts scores: 50,000 are included on Pro, then $1.50 per 1,000.
- +**Datadog** bills on LLM spans and lists evaluations as unlimited on both plans.

LangSmith also lets you cap an evaluator's LLM spend per week, after which it pauses until the limit resets. If your platform has that setting, use it before the first rule goes live.

### Three rules for a judge in production

Give it one criterion with a pass or fail answer. Check its verdicts against 30 to 50 traces you
labeled by hand before you alert on it. And filter before you sample: a judge for refund
conversations should see only refund conversations.
[When to trust an LLM judge](https://www.evalshift.dev/blog/when-to-trust-an-llm-judge) has the audit procedure, and
[LLM-as-a-judge](https://www.evalshift.dev/blog/llm-as-a-judge) covers the known biases.

## Alert on a rate with its uncertainty

The alerting built into these tools is a threshold on an average over a time window. LangSmith's
[alerts ↗](https://docs.langchain.com/langsmith/alerts) cover run count, cost, errors, feedback
score and latency. Braintrust's [examples ↗](https://docs.braintrust.dev/deploy/monitor) include
"Score drops below 0.8". That works for latency and error counts, where an hour holds thousands of
data points. It breaks on sampled quality scores, where the window may hold fifty.

Say the judged pass rate has been 92% and the alert fires below 90%. Today's sample has 100 scored traces and 87 passed. The 95% interval around 87 out of 100 runs from 79.0% to 92.2%, and the baseline sits inside it. Nothing has been shown to change. With 1,000 scored traces and 870 passes the interval is 84.8% to 88.9%, the baseline is outside it, and the drop is real.

Three settings follow from that:

- +**Size the window to the sample.** Choose the window so it holds a few hundred scored traces,
even if that makes it a day and not an hour. A quality alert that needs a day is still faster
than a support ticket.
- +**Compare with a baseline, not a fixed number.** Alert when this window's interval excludes
last week's rate. A fixed threshold fires the day traffic shifts toward harder questions.
- +**Keep hard failures on counts.** Schema failures, 5xx errors, tool exceptions and an unknown
model in the response need no statistics. Alert on the first few.

[How many eval cases do you need](https://www.evalshift.dev/blog/how-many-eval-cases-do-you-need) has the same arithmetic
for an offline suite.

## OpenTelemetry for LLM monitoring: where the standard stands

OpenTelemetry has semantic conventions for generative AI: agreed names for the spans, attributes and metrics an LLM call produces, so that any instrumentation library can feed any backend. They are what lets you switch monitoring vendors without re-instrumenting. They are also not finished.

As read on November 13, 2026:

- +The conventions moved out of the main specification. The
[pages on opentelemetry.io ↗](https://opentelemetry.io/docs/specs/semconv/gen-ai/) now say they
are no longer maintained there and point to a dedicated repository,[semantic-conventions-genai ↗](https://github.com/open-telemetry/semantic-conventions-genai) ,
created in May 2026.
- +Every page in that repository is marked **Development** , not Stable. The repository has no
tagged release, and its README lists the schema URL as "TODO".
- +The unreleased changelog holds 20 entries marked breaking. One replaces the
`gen_ai.client.token.usage` histogram with separate input and output token metrics. Another
renames`gen_ai.usage.cache_creation.input_tokens` to`gen_ai.usage.cache_write.input_tokens` .

What the conventions define maps closely onto the table above:

| You want to chart | Convention | 
|---|---|
| Model asked for and model served | `gen_ai.request.model` ,`gen_ai.response.model` | 
| Tokens, cached and reasoning tokens | `gen_ai.usage.input_tokens` ,`gen_ai.usage.output_tokens` ,`gen_ai.usage.cache_read.input_tokens` ,`gen_ai.usage.reasoning.output_tokens` | 
| Stop reasons | `gen_ai.response.finish_reasons` | 
| Latency and time to first token | `gen_ai.client.inference.duration` ,`gen_ai.client.inference.time_to_first_chunk` | 
| Tool executions and their errors | An `execute_tool` span with`gen_ai.tool.name` and`error.type` | 
| Steps per agent run | `gen_ai.invoke_agent.inference_calls` ,`gen_ai.invoke_agent.tool_calls` | 

Prompts and completions are off by default. The
[span conventions ↗](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)
say instrumentations should not capture instructions, inputs or outputs unless the user opts in.
That is the right default, and it means a judge has nothing to read until you turn content
capture on and decide where the content lives.

Backends already accept the format. Datadog
[says ↗](https://www.datadoghq.com/blog/llm-otel-semantic-convention/) it natively supports the
GenAI conventions from version 1.37 up. Langfuse
[receives OTLP ↗](https://langfuse.com/integrations/native/opentelemetry) and maps `gen_ai.*`
attributes onto its own data model. [Phoenix ↗](https://arize.com/docs/phoenix) is built on
OpenTelemetry with its own OpenInference instrumentation.

My advice: instrument through OpenTelemetry, because it is the only portable option, pin the instrumentation library's version, and expect renames until the conventions reach Stable.

## LLM monitoring tools

Checked against each vendor's docs and pricing page on November 13, 2026. Prices are list prices for the cloud product.

| Tool | License and hosting | Online evals | Alerts | Free tier | First paid tier | 
|---|---|---|---|---|---|
| [Langfuse ↗](https://langfuse.com/pricing) | MIT except `ee` folders; self-host free | LLM judge on observations, with filters and sampling | Monitors on cost, latency and scores, to Slack, webhook or GitHub Actions | 50k units a month, 30 days of data | Core: $29 a month, 100k units, then $8 per 100k | 
| [LangSmith ↗](https://www.langchain.com/pricing) | Proprietary; self-host on Enterprise | LLM judge on runs or threads, filter and sampling rate | Run count, cost, errors, feedback score, latency, to Slack, PagerDuty or webhook | 1 seat, 5k traces a month | Plus: $39 per seat, 10k traces, then $5 per 1,000 | 
| [Braintrust ↗](https://www.braintrust.dev/pricing) | Proprietary; BYOC on Enterprise | Scoring rules on spans, traces or groups, with sampling | Email, Slack or webhook | 1 GB, 10k scores, 14 days | Pro: $249 a month, 5 GB, 50k scores, 30 days | 
| [Arize Phoenix and AX ↗](https://arize.com/pricing/) | Phoenix: Elastic License 2.0, self-host free. AX: commercial | On AX: LLM judge and code, continuous, with sampling | On AX: monitors to email, Slack, PagerDuty, OpsGenie, Teams or webhook | AX Free: 25k spans, 15 days | AX Pro: $50 a month, 50k spans, 30 days | 
| [Opik ↗](https://www.comet.com/site/pricing/) | Apache-2.0; self-host free | LLM judge and code on traces, threads or spans, with sampling | On errors and scores, to Slack, PagerDuty or webhook | 25k spans a month, 60 days | Pro: $19 a month, 100k spans, then $5 per 100k | 
| [Datadog Agent Observability ↗](https://www.datadoghq.com/pricing/?product=llm-observability) | Proprietary SaaS | Managed, custom LLM judge and code evaluators, with sampling | Datadog monitors | 40k LLM spans a month, 15 days | Pro: $160 a month billed annually, 100k LLM spans, then $3.50 per 10k | 
| [Helicone ↗](https://www.helicone.ai/pricing) | Apache-2.0; gateway and logging | Scores you submit | Error rate and cost, to Slack or email | 10,000 requests, 7 days | Pro: $79 a month plus usage | 

Notes on reading it:

- +**The meters differ.** Langfuse counts every trace, observation and score. LangSmith counts
traces. Braintrust counts gigabytes and scores. Datadog counts LLM spans only, not tool,
workflow or retrieval spans. An agent that makes ten model calls per request is one LangSmith
trace, ten Datadog LLM spans and eleven or more Langfuse units.[LangSmith alternatives](https://www.evalshift.dev/blog/langsmith-alternatives) and[Braintrust vs LangSmith](https://www.evalshift.dev/blog/braintrust-vs-langsmith) work through examples.
- +**Retention is short.** 14 days on LangSmith's base traces and Braintrust's free plan, 15 on
Datadog and AX Free, 30 on Braintrust Pro. A failure you mean to turn into a test has to be
exported before then.
- +**Datadog renamed the product.** Its docs and pricing page call it Agent Observability, and the
URLs still say LLM Observability.
- +**Helicone has changed hands twice.** Mintlify[acquired it ↗](https://www.mintlify.com/blog/mintlify-acquires-helicone) in March 2026 and said
it would continue in maintenance mode. As of mid-November 2026 its site carries a banner
saying it is now part of Experiential Labs, with details to come. Check where that stands
before you build on it.

How to choose: if traces must stay on your infrastructure, Langfuse, Phoenix or Opik. If you are
on LangChain or LangGraph, LangSmith. If you already pay for Datadog, start there. If experiments
are the center of your workflow, Braintrust.
[The best LLM evaluation tools](https://www.evalshift.dev/blog/best-llm-evaluation-tools) compares the same platforms on
their evaluation features.

## From alert to test case

Monitoring tells you after the fact: a user saw the wrong answer before the judge scored it. What monitoring can do is make sure each failure happens in production once. That takes five steps, and the monitoring tool does none of them for you.

**1. Open the trace, not the chart.** Find one failing request and read all of it: the input, the
tool calls, the tool results, the reply.

**2. Export it before retention deletes it.** Copy the input, the conversation so far and the tool
results into a file in your repository, with personal data removed.

**3. Write the expected behavior by hand.** This is the step that gets skipped. The recorded run
is what the agent did, and it did the wrong thing. The test case needs what it should have done:
the right tool, the right arguments, the fact the reply must contain.

**4. Tag it with the failure.** `refund-without-lookup`, `wrong-language`, `loop`. The tag is how
you know later why the case exists.

**5. Run the suite before the fix ships, and on every change after.** The fix has to pass the new
case without failing the old ones. From then on a prompt edit, a model upgrade or a provider's
forced migration is checked against that failure before release.
[LLM regression testing in CI](https://www.evalshift.dev/blog/llm-regression-testing-in-ci) shows the pull-request
version, and [eval-driven development](https://www.evalshift.dev/blog/eval-driven-development) is the same loop treated as
the way you build.

The loop runs the other way too. When a retirement date appears or an alias is about to move, you
have a suite made of your own worst days to run the new model against before the provider
switches it for you.
[Build a golden suite from production traffic](https://www.evalshift.dev/blog/build-a-golden-suite-from-production-traffic)
covers collecting the ordinary cases that sit next to the failures.

## Where EvalShift fits

Disclosure again: I'm the founder. [EvalShift](https://www.evalshift.dev/docs) does not do production monitoring. It has
no dashboards, no alerts and no online evals, so run one of the tools above next to it. What it
covers is steps 2 to 5.

The [capture SDK](https://www.evalshift.dev/docs/sdk) records agent runs in production: the input, each model call with
its model ID, token counts and latency, and each tool call with its result. It writes them as
files to local disk or to a bucket you own on S3, Google Cloud Storage or Azure, and nothing is
sent to EvalShift. Redaction runs in process before a capture is written, and
[`EVALSHIFT_SAMPLE_RATE`](https://www.evalshift.dev/docs/sdk-config) records a fraction of runs.

One command turns a recorded run into a case in the golden suite:

```
evalshift capture promote cap_3f9a2c --suite support --tag refund-without-lookup
```

Two details matter for failures. `promote` refuses a capture whose trace contains an error event
unless you pass `--allow-errored`. And the expected tool calls it writes are marked
`provenance: captured`, which the [docs](https://www.evalshift.dev/docs/golden-suite) describe as transcribed from the
model's own recorded call, where nobody has checked it is right. For a failure it is wrong by
definition, so you edit the case file to the correct calls and mark them `reviewed`. That is
step 3.

After that, `evalshift compare` runs the current model and a candidate over the suite and returns
a verdict from the [migration policy](https://www.evalshift.dev/docs/migration-policy) you wrote, and the
[GitHub Action](https://www.evalshift.dev/docs/action) does the same on a pull request. With
`captures.max_age` set, `evalshift doctor` warns when the newest case in a suite is older than
that, or when cases were recorded on a model other than the one you run now.

## FAQ

**What is LLM monitoring?** LLM monitoring is watching an application built on a language model
while real users are on it: whether model calls succeed, how long they take, what they cost, and
whether the answers and tool calls are still correct. The last part needs checks on the content,
because a wrong answer returns the same HTTP 200 as a right one.

**What is the difference between LLM monitoring and LLM observability?** Monitoring answers
whether something is wrong right now, with metrics over time and alerts. Observability answers
why one request went wrong, with a trace of every model call, tool call and retrieval in it.
Monitoring is built on observability data, so one product usually does both.

**What metrics should you monitor for an LLM application?** Error rate by type, latency and time
to first token; tokens and cost per task and the cache hit rate; the pass rate of code checks, a
judged quality score on a sample, user feedback and the refusal rate; for agents, tool-call
errors, steps per task and loops; and the model named in each response.

**How do you monitor LLM output quality in production?** Run code checks on every response,
count responses by stop reason, collect user feedback, and run an LLM judge on a filtered sample
of traces with one pass-or-fail criterion per judge. Validate the judge against 30 to 50
hand-labeled traces before alerting on it.

**How much does it cost to run LLM judges on production traffic?** Langfuse's docs estimate $0.01
to $0.10 per assessment, depending on the judge model and input size. Scoring 10% of 100,000
monthly traces with two judges is 20,000 assessments, or $200 to $2,000 a month in judge tokens,
before any per-score or retention charge from the platform.

**What are the best LLM monitoring tools?** As of November 2026: Langfuse, Arize Phoenix or Opik
if traces must stay on your own infrastructure, LangSmith for teams on LangChain or LangGraph,
Braintrust for experiment-centered teams, and Datadog Agent Observability for teams already on
Datadog. All of them trace requests, and all but self-hosted Phoenix add online evals with
sampling and alerts; for Phoenix those are on Arize AX.

**Is OpenTelemetry ready for LLM monitoring?** It is usable and not yet stable. As of November
13, 2026, the GenAI semantic conventions live in their own repository, every page is marked
Development, there is no tagged release, and the unreleased changelog holds 20 entries marked
breaking. Instrument through it, pin the library version and expect attribute renames.

**How do you detect that a model changed in production?** Record the model named in each
response, not only the one you requested, and alert when a new value appears. Gemini returns it
in the modelVersion field and OpenAI in the model field. Add the provider's deprecation dates to
a calendar, because a rerouted request still returns 200.

## Keep reading

- +[LLM testing](https://www.evalshift.dev/blog/llm-testing) : the types of tests that run before release, and what to rerun
when the model changes.
- +[Build a golden suite from production traffic](https://www.evalshift.dev/blog/build-a-golden-suite-from-production-traffic) :
recording real runs and promoting them to test cases.
- +[When to trust an LLM judge](https://www.evalshift.dev/blog/when-to-trust-an-llm-judge) : auditing a judge before it
scores live traffic.
- +[LLM model deprecation schedule](https://www.evalshift.dev/blog/llm-model-deprecation-schedule) : the retirement dates to
put next to your alerts.
