Skip to main content

OpenInference spans and traces

Agentic metrics evaluate OpenInference telemetry — not free-form prompt / output strings. This page shows the shapes Aegis expects so you can prepare payloads for metrics such as Tool Selection Correctness (tool_select).

Contents

Span vs trace

ConceptShapeTypical use
SpanOne object (dictionary) for a single operation — usually an LLM callSpan-level metrics (e.g. tool_select)
TraceOrdered list of spans that share a trace_id, linked by parent_idTrace-level metrics (not yet documented)

A real agent run is almost always a trace: a root AGENT wrapper, nested AGENT / LLM / TOOL (and sometimes CHAIN, RETRIEVER, …) children. Span-level metrics take one of those spans (typically an LLM span that advertised tools and emitted tool calls). Trace-level metrics take the full list.

Exporter tip

Use an OpenInference-compatible exporter (OpenTelemetry + OpenInference semantic conventions). Aegis reads flattened attribute keys such as llm.input_messages.0.message.role, not only nested JSON blobs under input.value / output.value.

What Aegis reads

Identity and timing live on the span object; semantic payload lives under attributes.

Top-level / context

  • name — span display name
  • context.span_id, context.trace_id
  • parent_id — parent span id (null for the root)
  • start_time, end_time — used for duration on trace-level metrics
  • status.status_code — e.g. OK

Common attributes

  • openinference.span.kind — semantic kind: AGENT, LLM, TOOL, …
  • llm.input_messages.{i}.message.role / .content — conversation for LLM spans
  • llm.tools.{n}.tool.json_schema — advertised tool catalogue (OpenAI function-definition shape; string or object)
  • llm.output_messages.{m}.message.tool_calls.{c}.tool_call.(id|function.name|function.arguments) — tools the model requested
  • llm.token_count.prompt / .completion / .total — token usage when present
  • For TOOL spans: tool.name, optional tool.call.id (or gen_ai.tool.call.id), plus input.value / output.value

Example LLM span

Minimal shape sufficient for tool-selection evaluation. Real exporter spans include more fields (resource, events, full token/invocation metadata); those are fine to keep.

{
"name": "response",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x64e5562a83068b87"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:57.729073Z",
"end_time": "2026-07-08T11:07:59.573356Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "LLM",
"llm.model_name": "gpt-4.1-2025-04-14",
"llm.token_count.prompt": 113,
"llm.token_count.completion": 59,
"llm.token_count.total": 172,
"llm.input_messages.0.message.role": "system",
"llm.input_messages.0.message.content": "You complete tasks by running shell commands with the Bash tool.",
"llm.input_messages.1.message.role": "user",
"llm.input_messages.1.message.content": "Use the Bash tool to run these two commands:\n1. `printf 'hello' | wc -c`\n2. `printf 'world' | wc -c`",
"llm.tools.0.tool.json_schema": {
"type": "function",
"function": {
"name": "bash",
"description": "Run a shell command.",
"parameters": {
"type": "object",
"properties": { "command": { "type": "string" } },
"required": ["command"]
}
}
},
"llm.output_messages.0.message.role": "assistant",
"llm.output_messages.0.message.tool_calls.0.tool_call.id": "call_wn595Y17jc1yKPnucs5jrjG7",
"llm.output_messages.0.message.tool_calls.0.tool_call.function.name": "bash",
"llm.output_messages.0.message.tool_calls.0.tool_call.function.arguments": {
"command": "printf 'hello' | wc -c"
},
"llm.output_messages.0.message.tool_calls.1.tool_call.id": "call_6tj5lKELXQ4wpWBaZ6HUaRMV",
"llm.output_messages.0.message.tool_calls.1.tool_call.function.name": "bash",
"llm.output_messages.0.message.tool_calls.1.tool_call.function.arguments": {
"command": "printf 'world' | wc -c"
}
}
}

Example TOOL span

Tool execution spans sit under the agent (or the LLM that invoked them). Trace-level metrics use them to join call ids, inputs, and results.

{
"name": "bash",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x6c9868e6283f0ed1"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:59.574350Z",
"end_time": "2026-07-08T11:07:59.589819Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "bash",
"tool.call.id": "call_wn595Y17jc1yKPnucs5jrjG7",
"input.value": { "command": "printf 'hello' | wc -c" },
"output.value": " 5\n"
}
}

Example trace

A trace is an array of spans in chronological (or exporter) order, sharing one trace_id. Hierarchy is expressed with parent_id. The sketch below mirrors a typical agent-with-tools run: root agent → child agent → LLM that requests tools → TOOL executions → follow-up LLM that returns the final text.

[
{
"name": "Agent workflow",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x145e3c64b3b99a77"
},
"parent_id": null,
"start_time": "2026-07-08T11:07:57.725353Z",
"end_time": "2026-07-08T11:08:00.333260Z",
"status": { "status_code": "OK" },
"attributes": { "openinference.span.kind": "AGENT" }
},
{
"name": "Bash Agent",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x083b5fc1127d658a"
},
"parent_id": "0x145e3c64b3b99a77",
"start_time": "2026-07-08T11:07:57.725590Z",
"end_time": "2026-07-08T11:08:00.332983Z",
"status": { "status_code": "OK" },
"attributes": { "openinference.span.kind": "AGENT" }
},
{
"name": "response",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x64e5562a83068b87"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:57.729073Z",
"end_time": "2026-07-08T11:07:59.573356Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "LLM",
"llm.input_messages.0.message.role": "system",
"llm.input_messages.0.message.content": "You complete tasks by running shell commands with the Bash tool.",
"llm.input_messages.1.message.role": "user",
"llm.input_messages.1.message.content": "Run two bash commands and return both counts.",
"llm.tools.0.tool.json_schema": {
"type": "function",
"function": { "name": "bash", "parameters": { "type": "object" } }
},
"llm.output_messages.0.message.tool_calls.0.tool_call.id": "call_a",
"llm.output_messages.0.message.tool_calls.0.tool_call.function.name": "bash",
"llm.output_messages.0.message.tool_calls.1.tool_call.id": "call_b",
"llm.output_messages.0.message.tool_calls.1.tool_call.function.name": "bash",
"llm.token_count.total": 172
}
},
{
"name": "bash",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0x6c9868e6283f0ed1"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:59.574350Z",
"end_time": "2026-07-08T11:07:59.589819Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "bash",
"tool.call.id": "call_a",
"input.value": { "command": "printf 'hello' | wc -c" },
"output.value": "5\n"
}
},
{
"name": "bash",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0xaaaaaaaaaaaaaaaa"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:59.590000Z",
"end_time": "2026-07-08T11:07:59.600000Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "bash",
"tool.call.id": "call_b",
"input.value": { "command": "printf 'world' | wc -c" },
"output.value": "5\n"
}
},
{
"name": "response",
"context": {
"trace_id": "0x3c25552ecfec75f0dfa5baad5a544c4c",
"span_id": "0xbbbbbbbbbbbbbbbb"
},
"parent_id": "0x083b5fc1127d658a",
"start_time": "2026-07-08T11:07:59.610000Z",
"end_time": "2026-07-08T11:08:00.300000Z",
"status": { "status_code": "OK" },
"attributes": {
"openinference.span.kind": "LLM",
"llm.input_messages.0.message.role": "system",
"llm.input_messages.0.message.content": "You complete tasks by running shell commands with the Bash tool.",
"llm.input_messages.1.message.role": "user",
"llm.input_messages.1.message.content": "Run two bash commands and return both counts.",
"llm.output_messages.0.message.role": "assistant",
"llm.output_messages.0.message.contents.0.message_content.type": "text",
"llm.output_messages.0.message.contents.0.message_content.text": "5\n5",
"llm.token_count.total": 200
}
}
]

For a span-level metric, pass one LLM object from a list like this (not the whole array). For a trace-level metric, pass the entire array.