GenAI Semantic Conventions are the OpenTelemetry specification for describing generative AI operations in telemetry. They define span names, operation types, metrics, events and gen_ai.* attributes such as gen_ai.request.model and gen_ai.usage.input_tokens for model calls, embeddings, retrieval, agents and tool execution, so LLM telemetry looks the same across providers, frameworks and backends.
What are the GenAI semantic conventions?
OpenTelemetry semantic conventions define common names and meanings for telemetry, for example http.request.method for HTTP or db.system.name for databases. The GenAI semantic conventions extend this vocabulary to generative AI: calls to language models, embeddings, retrieval, agents and tools. Their goal is that a chat completion traced through one provider's SDK or agent framework produces the same span structure and attribute names as one traced through another.
The conventions are developed by the OpenTelemetry GenAI special interest group and are now maintained in a dedicated repository, semantic-conventions-genai, in the OpenTelemetry GitHub organization. As of 2026 their status is development: attribute names and structures can still change between versions, which matters for dashboards and queries built on them.
What the conventions cover
- Model spans for inference operations such as
chat,generate_content,text_completionandembeddings, plusretrievalfor searches in a knowledge source. - Agent spans for
create_agent,invoke_agentandexecute_tool, used for AI agent observability, along with spans for workflows and skills. - Metrics such as
gen_ai.client.operation.duration, token usage counters, and server-side metrics such asgen_ai.server.time_to_first_tokenandgen_ai.server.time_per_output_token. - Events for inputs and outputs, and conventions for exceptions.
- Provider-specific conventions, for example for Anthropic, AWS Bedrock, Azure AI Inference and OpenAI, and conventions for the Model Context Protocol.
The practical benefit is comparability. Without shared names, each library invents its own attributes, for example one framework records the model as llm.model and another as model_name, and every dashboard, alert and cost report has to be rebuilt per integration. With the conventions, GenAI spans fit into existing distributed traces next to HTTP and database spans, and switching a model provider or framework does not break your queries. It also reduces vendor lock-in, because the data model belongs to an open standard rather than to an observability product.
Key gen_ai attributes
| Attribute | Meaning |
|---|---|
gen_ai.operation.name | Operation type, for example chat or invoke_agent (required) |
gen_ai.provider.name | Provider, for example openai or aws.bedrock; replaces the older gen_ai.system |
gen_ai.request.model | Model requested by the client |
gen_ai.response.model | Model that actually produced the response |
gen_ai.usage.input_tokens / gen_ai.usage.output_tokens | Input tokens (including cached) and output tokens |
gen_ai.response.finish_reasons | Why generation stopped, for example stop or length |
gen_ai.conversation.id | Identifier that groups the calls of one conversation or session |
gen_ai.agent.name, gen_ai.tool.name | Agent and tool involved in a step |
Span names follow the pattern {gen_ai.operation.name} {gen_ai.request.model}, for example chat gpt-4o. Token counts are covered in more detail under token usage.
Content capture and privacy
Prompt and response content is sensitive. The conventions therefore define attributes such as gen_ai.input.messages, gen_ai.output.messages and gen_ai.system_instructions as opt-in: instrumentations should not record them unless the user explicitly enables it, for example through a setting like OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT. The same applies to retrieved documents and tool call arguments. If you enable content capture, mask personal data in a pipeline before storage and restrict access and retention.
Example: a traced chat call
An illustrative span emitted by an instrumented model client, shown in simplified form:
span: chat gpt-4o (kind: CLIENT, duration 1.84 s)
gen_ai.operation.name = "chat"
gen_ai.provider.name = "openai"
gen_ai.request.model = "gpt-4o"
gen_ai.response.model = "gpt-4o-2024-08-06"
gen_ai.request.max_tokens = 500
gen_ai.usage.input_tokens = 1240
gen_ai.usage.output_tokens = 312
gen_ai.response.finish_reasons = ["stop"]
server.address = "api.openai.com"
Because these names are standardized, a query such as "p95 duration and output tokens per gen_ai.request.model" works regardless of which SDK or framework produced the spans.
Best practices for adoption
- Prefer instrumentations that emit the GenAI conventions over custom attribute names, so data stays portable.
- Record which convention version your instrumentation emits. Some instrumentations let you opt into the latest experimental version, for example via
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental; check the documentation of your library. - Plan for renames: build dashboards on a small set of core attributes and review them when upgrading instrumentation.
- Keep content capture off by default and enable it deliberately per environment.
- Propagate trace context into tools and sub-agents so that GenAI spans join the rest of the distributed trace.
How Obseria helps
Obseria is OpenTelemetry-native and stores GenAI spans, metrics and events as they arrive over OTLP, without a proprietary schema. Because Obseria Lake uses schema-on-read, new or renamed gen_ai.* attributes are queryable immediately with PromQL, OQL or SQL. The Obseria Pipeline can drop or mask content attributes before storage. See OpenTelemetry in Obseria.