Which OpenTelemetry GenAI attribute records the provider that served a call?
gen_ai.system. It is a stable, low-cardinality string naming the provider (openai, anthropic, bedrock) for each span.
Imagine you order food from different restaurants through a delivery app. Each order has a label showing which restaurant cooked it: Pizza Place, Sushi Spot, Burger Joint. That label is the same idea as gen_ai.system. It does not say which specific dish you ordered or how much it cost. It just says which kitchen served you. Knowing the kitchen matters because each one has different prices, different cooking times, and different rules. If you later notice all the slow orders came from the same kitchen, you can spot the pattern. OpenTelemetry uses the same trick for model calls. One small label on every span tells you which provider answered, separately from which specific model was used or how many tokens were burned.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Recognizing gen_ai.system is the entry point into the OpenTelemetry GenAI semantic conventions. It is one of the first attributes any auto-instrumentation library sets, and it is the field most dashboards group by when comparing across providers.
The value of getting this question right is not the trivia. It is that knowing where the provider identity lives forces you to internalize the rest of the namespace structure: request, response, usage, operation. From there, every other attribute is a one-line spec lookup.
What gen_ai.system actually is
The OpenTelemetry GenAI conventions define gen_ai.system as a string attribute identifying the provider serving the model. The spec lists canonical values: openai, anthropic, vertex_ai, bedrock, azure_openai, cohere, mistral_ai, ibm_watsonx_ai, and a few more.
The value is set once per span, at the point where the auto-instrumentation library knows which provider client it wrapped. For manually instrumented calls, you set it yourself, typically in a shared helper that wraps your LLM SDK calls.
The attribute is in the stable tier of the spec, which means a future SDK upgrade will not rename it or change its semantics in a backward-incompatible way. Dashboards pinned to it are safe to keep.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Langfuse 3.x indexes gen_ai.system as a filter facet in the trace search UI.
- OpenLLMetry sets gen_ai.system automatically based on which provider client the auto-instrumentation wrapped.
What an interviewer would ask next. Try answering before peeking at the approach.
QWhy is gen_ai.system kept as a separate attribute when the model id already implies the provider?
Talk about model-id reuse across providers, low cardinality, and dashboard group-by semantics.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Confusing gen_ai.system with the model id. The system is the provider (openai); the model is the specific snapshot (gpt-4o-2024-08-06).
60 second bullets to scan on the way to the call.
Name the attribute that identifies the provider on an OTel GenAI span
Distinguish gen_ai.system from gen_ai.request.model
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.