The eleven OpenInference span kinds — LLM, Tool, Agent, Chain, Retriever, and the rest — with the canonical attributes Arize AX expects on each.
A span kind is the category of operation a span represents. OpenTelemetry has its own span kinds for network calls (SERVER, CLIENT, PRODUCER, …). OpenInference adds an AI-specific set: LLM, Tool, Agent, Chain, Retriever, and more.Span kind is what drives the span-kind icons in the Arize AX UI. It’s also how Arize AX knows which attributes to expect — an LLM span gets a different visual treatment from a tool span.
Span kind is set via the openinference.span.kind attribute. The value is ALL CAPS — "TOOL", not "Tool". Casing matters: the canonical OpenInference Python enum is OpenInferenceSpanKindValues.TOOL = "TOOL".
from openinference.semconv.trace import ( SpanAttributes, OpenInferenceSpanKindValues,)span.set_attribute( SpanAttributes.OPENINFERENCE_SPAN_KIND, OpenInferenceSpanKindValues.TOOL.value,)
Arize AX UI behavior: span-kind icons in the Arize AX trace tree come directly from the openinference.span.kind attribute. A span without that attribute renders with a blank icon. Auto-instrumentors set this for you — set it explicitly on every manual span.
Arize AX UI behavior: Arize AX reads the trace-level input and output from the root span’sinput.value and output.value. If your root span doesn’t set them, the trace list view shows those columns as blank even if child spans have data.
A call to an external tool, API, or function on behalf of an LLM.
Attribute
Description
tool.id
A unique identifier for the tool invocation (often correlated with the LLM’s tool-call ID).
tool.name
The tool’s name.
tool.description
The tool’s description (often matches what was shown to the model).
tool.parameters
The JSON-serialized parameters passed to the tool.
tool.json_schema
The tool’s full JSON schema as exposed to the model.
Tool calls are one of the clearest cases where you must instrument manually when making an LLM calls directly, instead of via a framework. When you call OpenAI directly, the auto-instrumentor traces the model’s request for a tool call — but the actual execution of the tool function happens in your Python code, where the instrumentor can’t see it. Wrap the function in a tool span yourself.
A starting point or a link between different application steps. Use a chain span to group pre/post-processing logic that doesn’t fit any of the more specific kinds.Chain spans use only the common attributes — input.value, output.value, metadata, session.id, etc.
The remaining seven span kinds — RETRIEVER, EMBEDDING, RERANKER, GUARDRAIL, EVALUATOR, PROMPT, UNKNOWN — each have their own attribute schemas. Consult the canonical source for the full per-kind attribute list.Some auto-instrumentors also emit additional kinds that aren’t (yet) in the canonical enum — see Voice Extensions below for the AUDIO and USER kinds used by the realtime/voice tracing path.
The OpenAI Agents realtime instrumentor introduces two additional span-kind values for voice tracing — AUDIO and USER — that aren’t (yet) in the canonical OpenInferenceSpanKindValues enum. They’re set as string-literal values on openinference.span.kind, and Arize AX renders them with audio-aware UI: a play button, waveform, and the input/output transcripts inline.A single conversational turn in a Realtime API session produces this span tree:
AUDIO "conversation.turn" ← parent; aggregated transcripts, llm.model_name, llm.invocation_parameters├─ USER "user" ← input.audio.url, input.audio.transcript├─ LLM "assistant" ← output.audio.url, output.audio.transcript, token counts, time_to_first_token_ms│ └─ TOOL "<tool_name>" ← one per function call within the turn└─ ... ← additional siblings for split input or tool round-trips
A single user utterance inside an AUDIO turn — emitted when server-side VAD detects the user has finished speaking.
Attribute
Description
input.audio.url
URL of the user audio for this utterance. A data:audio/wav;base64,... URI by default, or any HTTPS URL if an external storage backend is wired in.
input.audio.mime_type
MIME type of the input audio (e.g. audio/wav).
input.audio.transcript
Transcript of just this utterance.
The corresponding assistant span inside an AUDIO turn uses the canonical LLM kind, with the standard LLM attributes plus a few realtime-specific extras:
Attribute
Description
output.audio.url
URL of the assistant audio for this response.
output.audio.mime_type
MIME type of the output audio.
output.audio.transcript
Transcript of the assistant response.
time_to_first_token_ms
Latency from the user’s audio commit to the first byte of the model’s audio response — the metric that matters most for perceived voice-agent responsiveness.
llm.token_count.prompt_details.audio
Audio input tokens consumed.
llm.token_count.completion_details.audio
Audio output tokens generated.
AUDIO and USER are emitted as string-literal openinference.span.kind values rather than via the OpenInferenceSpanKindValues enum. Treat them as instrumentor-introduced extensions used by the realtime/voice tracing path, pending promotion into the canonical enum.
For an end-to-end example that produces these spans and runs evaluations against the captured audio, see the voice tracing guide.
Inputs and outputs in modern AI applications aren’t always plain text. OpenInference defines a message_content attribute family for multimodal content:
Attribute
Description
message_content.type
One of text, image, audio, reasoning, tool_use.
message_content.text
The text payload (when type is text or reasoning).
message_content.image
The image payload — URL or inline base64 (when type=image).
message_content.id
Provider-assigned identifier for the message content item (e.g., OpenAI Responses reasoning IDs).