Accessing your Traces

Database convenience functions for querying traces and spans

Agno provides convenience functions on your database instance to query traces and spans. Parameter support can vary by database implementation.

The fragments below assume an existing database db with stored traces, an agent, and a completed run response. Run the basic agent example first and retain its run output when querying by run_id. With an async database, await the corresponding methods.

Trace Functions

db.get_trace()

Get a single trace by identifier.

# Get by trace_id
trace = db.get_trace(trace_id="abc123...")

# Get by run_id (returns most recent match)
trace = db.get_trace(run_id=response.run_id)

Parameters:

ParameterTypeDescription
trace_idOptional[str]Unique trace identifier
run_idOptional[str]Filter by run ID

Returns: Trace or None

See the Trace reference.

db.get_traces()

Get multiple traces with filtering and pagination.

# Get recent traces
traces, total_count = db.get_traces(limit=20)

# Filter by agent
traces, count = db.get_traces(agent_id=agent.id)

# Filter by time range
from datetime import datetime, timedelta, timezone

now = datetime.now(timezone.utc)
traces, count = db.get_traces(
    start_time=now - timedelta(hours=1),
    end_time=now,
    limit=100
)

Parameters:

ParameterTypeDefaultDescription
run_idOptional[str]NoneFilter by run ID
session_idOptional[str]NoneFilter by session ID
user_idOptional[str]NoneFilter by user ID
agent_idOptional[str]NoneFilter by agent ID
team_idOptional[str]NoneFilter by team ID
workflow_idOptional[str]NoneFilter by workflow ID
statusOptional[str]NoneFilter by status (OK, ERROR, UNSET)
start_timeOptional[datetime]NoneFilter traces after this time
end_timeOptional[datetime]NoneFilter traces before this time
limitOptional[int]20Max traces to return
pageOptional[int]1Page number for pagination
filter_exprOptional[Dict[str, Any]]NoneAdvanced filter expression dict, built with agno.filters (e.g. EQ("status", "OK").to_dict()). Supports AND/OR/NOT logic and operators like EQ, NEQ, GT, GTE, LT, LTE, IN, CONTAINS, STARTSWITH

Returns: tuple[List[Trace], int] - (traces, total_count)

Span Functions

db.get_span()

Get a single span by ID.

span = db.get_span(span_id="xyz789...")
if span:
    print(f"{span.name}: {span.duration_ms}ms")

Parameters:

ParameterTypeDescription
span_idstrUnique span identifier

Returns: Span or None

See the Span reference.

db.get_spans()

Get multiple spans for a trace or parent.

# Get all spans in a trace
spans = db.get_spans(trace_id=trace.trace_id)

# Get child spans of a specific parent
children = db.get_spans(parent_span_id=root_span.span_id)

Parameters:

ParameterTypeDefaultDescription
trace_idOptional[str]NoneFilter by trace ID
parent_span_idOptional[str]NoneFilter by parent span ID
limitOptional[int]1000Max spans to return

Returns: List[Span]

Synchronous SqliteDb.get_spans() does not accept limit in the current implementation. Omit limit when using SQLite. The other filters and the SQLite example below work as shown.

Unlike get_traces(), get_spans() returns a list without a count.

Example: Analyzing a Run

from agno.db.sqlite import SqliteDb

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

# Get trace for a run
trace = db.get_trace(run_id=response.run_id)

if trace:
    print(f"Trace: {trace.name} ({trace.duration_ms}ms)")

    # Get all spans
    spans = db.get_spans(trace_id=trace.trace_id)

    # Print execution tree
    for span in sorted(spans, key=lambda s: s.start_time):
        indent = "  " if span.parent_span_id else ""
        print(f"{indent}- {span.name} ({span.duration_ms}ms)")

See Also