genai:semantic-conventions
SkillMonitoring & opsOpenTelemetry GenAI semantic conventions for agent instrumentation - the standard attributes for LLM observability
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the genai:semantic-conventions skill
What this skill tells your AI
The instructions your AI receives, as published by rossoctl/rossoctl in .claude/skills/genai:semantic-conventions/SKILL.md and read by ahel’s review.
Reference for instrumenting agents with OpenTelemetry GenAI semantic conventions.
Spec: https://opentelemetry.io/docs/specs/semconv/gen-ai/
Architecture
Agent (gen_ai.* only) → OTEL Collector → Transform → Phoenix (llm.*) + MLflow (mlflow.trace.*)
Agents emit only gen_ai.* attributes. The OTEL Collector transforms these to:
- OpenInference format (
llm.*) for Phoenix - MLflow metadata (
mlflow.trace.*) for MLflow session tracking
Core Attributes
Request Attributes (on LLM call spans)
| Attribute | Type | Description | Example |
|---|---|---|---|
gen_ai.system | string | GenAI provider/system | openai, anthropic, langchain |
gen_ai.request.model | string | Model requested | gpt-4, claude-3-opus |
gen_ai.request.max_tokens | int | Max tokens to generate | 1024 |
gen_ai.request.temperature | float | Sampling temperature | 0.7 |
gen_ai.request.top_p | float | Nucleus sampling | 0.9 |
Response Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
gen_ai.response.model | string | Model that responded | gpt-4-0613 |
gen_ai.response.id | string | Response identifier | chatcmpl-abc123 |
gen_ai.response.finish_reasons | string[] | Why generation stopped | ["stop"] |
gen_ai.usage.input_tokens | int | Prompt tokens | 150 |
gen_ai.usage.output_tokens | int | Completion tokens | 250 |
Conversation/Session Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
gen_ai.conversation.id | string | Session/conversation ID | uuid-123-456 |
gen_ai.prompt | string | User prompt (truncated) | What is the weather? |
gen_ai.completion | string | Response (truncated) | The weather is sunny |
Agent Attributes (custom, for A2A agents)
| Attribute | Type | Description | Example |
|---|---|---|---|
gen_ai.agent.name | string | Agent name | weather-assistant |
gen_ai.agent.id | string | Agent/task ID | task-uuid-789 |
Python Usage
Auto-instrumentation (Recommended)
# Install: pip install opentelemetry-instrumentation-openai
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
# Instruments all OpenAI SDK calls automatically
OpenAIInstrumentor().instrument()
Manual Span Attributes
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(
"gen_ai.agent.invoke",
attributes={
"gen_ai.conversation.id": context_id,
"gen_ai.agent.name": "my-agent",
"gen_ai.system": "langchain",
"gen_ai.request.model": "gpt-4",
"gen_ai.prompt": user_input[:500], # Truncate for size
}
) as span:
# Agent logic here
result = await agent.run(user_input)
# Add response attributes
span.set_attribute("gen_ai.completion", str(result)[:500])
Adding to Existing Span
current_span = trace.get_current_span()
if current_span and current_span.is_recording():
current_span.set_attribute("gen_ai.conversation.id", session_id)
current_span.set_attribute("gen_ai.agent.name", "weather-assistant")
OTEL Collector Transforms
The collector transforms gen_ai.* to target formats:
GenAI → OpenInference (Phoenix)
| GenAI Attribute | OpenInference Attribute |
|---|---|
gen_ai.request.model | llm.model_name |
gen_ai.usage.input_tokens | llm.token_count.prompt |
gen_ai.usage.output_tokens | llm.token_count.completion |
gen_ai.system | llm.provider, llm.system |
GenAI → MLflow
| GenAI Attribute | MLflow Metadata |
|---|---|
gen_ai.conversation.id | mlflow.trace.session (resource) |
Span name gen_ai.agent.* | mlflow.spanType=AGENT |
Span with gen_ai.request.model | mlflow.spanType=LLM |
Span name gen_ai.tool.* | mlflow.spanType=TOOL |
Span Naming Conventions
Use GenAI operation names for spans:
| Operation | Span Name |
|---|---|
| Agent invocation | gen_ai.agent.invoke |
| LLM chat completion | gen_ai.chat |
| Tool call | gen_ai.tool.{tool_name} |
| Embedding | gen_ai.embeddings |
Best Practices
- Always set
gen_ai.conversation.idfor session tracking in MLflow - Truncate prompts/completions to ~500 chars to avoid span size issues
- Use auto-instrumentation when available (OpenAI, Anthropic SDKs)
- Add manual attributes for custom agent spans
- Never emit OpenInference (
llm.*) directly - let the collector transform
Dependencies
# pyproject.toml
dependencies = [
"opentelemetry-sdk",
"opentelemetry-exporter-otlp",
"opentelemetry-instrumentation-openai>=0.34b0", # For OpenAI auto-instrumentation
]
Related Skills
auth:otel-oauth2-exporter- Configure OTel Collector with OAuth2k8s:health- Platform health including observability components- OpenTelemetry GenAI Spec
- MLflow Tracing
- OpenInference Spec
Signals
- GitHub stars
- 300
- Forks
- 107
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
genai-semantic-conventions- Source
- github.com/rossoctl/rossoctl