Span

Span attributes, common span names, and OpenTelemetry attribute conventions.

A Span represents a single operation within an agent execution. Spans form a parent-child hierarchy within a trace, allowing you to understand the execution flow.

Span Attributes

AttributeTypeDefaultDescription
span_idstrRequiredUnique span identifier
trace_idstrRequiredUnique identifier of the trace that contains this span
parent_span_idOptional[str]RequiredParent span ID (None for root spans)
namestrRequiredOperation name (e.g., OpenAIChat.invoke, get_weather)
span_kindstrRequiredSpan kind (e.g., INTERNAL, CLIENT)
status_codestrRequiredStatus: OK, ERROR, or UNSET
status_messageOptional[str]RequiredStatus message (typically error details, None when there is none)
duration_msintRequiredExecution time in milliseconds
start_timedatetimeRequiredWhen the span started
end_timedatetimeRequiredWhen the span completed
attributesDict[str, Any]RequiredOpenTelemetry attributes (tokens, params, etc.)
created_atdatetimeRequiredWhen the span record was created

Common Span Names

Configured instrumentation creates spans for operations such as those below. Exact names vary with the instrumentor and synchronous or asynchronous execution path:

Span Name PatternDescription
{AgentName}.runAgent execution
{TeamName}.runTeam execution
{ModelName}.invokeLLM model call
{tool_name}Tool execution

Attributes by Operation Type

The attributes field contains OpenTelemetry semantic attributes that vary by operation:

LLM Spans

AttributeDescription
llm.token_count.promptInput token count
llm.token_count.completionOutput token count
llm.model_nameModel identifier
llm.providerModel provider name

Tool Spans

AttributeDescription
tool.nameTool function name
tool.parametersTool input parameters (JSON)

Methods

The following method snippets assume an existing span object or its serialized data. Import the type with from agno.tracing.schemas import Span.

to_dict()

Convert the span to a dictionary.

span_dict = span.to_dict()

Returns: dict

from_dict()

Create a span from a dictionary.

span = Span.from_dict(data)

Parameters:

  • data (dict): Dictionary containing span data

Returns: Span

Usage

First follow the tracing setup, including its OpenTelemetry and instrumentation dependencies, to record a run in tmp/traces.db. Run this query from the same working directory after spans have been exported. Creating SqliteDb alone does not enable instrumentation or populate traces. For a separate query environment, install uv pip install -U agno sqlalchemy opentelemetry-sdk.

from agno.db.sqlite import SqliteDb

db = SqliteDb(db_file="tmp/traces.db")

# Get the most recent trace, then load its spans
traces, _ = db.get_traces(limit=1)
if not traces:
    raise RuntimeError("No traces found")

trace_id = traces[0].trace_id
spans = db.get_spans(trace_id=trace_id)

for span in spans:
    print(f"Span: {span.name}")
    print(f"  Duration: {span.duration_ms}ms")
    print(f"  Status: {span.status_code}")
    
    # Check for token usage (LLM spans)
    if span.attributes:
        tokens = span.attributes.get("llm.token_count.completion")
        if tokens:
            print(f"  Tokens: {tokens}")

Building a Span Tree

def print_span_tree(spans, parent_id=None, indent=0):
    """Recursively print spans as a tree."""
    for span in spans:
        if span.parent_span_id == parent_id:
            prefix = "  " * indent + ("└─ " if indent > 0 else "")
            print(f"{prefix}{span.name} ({span.duration_ms}ms)")
            print_span_tree(spans, span.span_id, indent + 1)

# Print the spans loaded above
print_span_tree(spans)

See Also