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:
| Parameter | Type | Description |
|---|---|---|
trace_id | Optional[str] | Unique trace identifier |
run_id | Optional[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:
| Parameter | Type | Default | Description |
|---|---|---|---|
run_id | Optional[str] | None | Filter by run ID |
session_id | Optional[str] | None | Filter by session ID |
user_id | Optional[str] | None | Filter by user ID |
agent_id | Optional[str] | None | Filter by agent ID |
team_id | Optional[str] | None | Filter by team ID |
workflow_id | Optional[str] | None | Filter by workflow ID |
status | Optional[str] | None | Filter by status (OK, ERROR, UNSET) |
start_time | Optional[datetime] | None | Filter traces after this time |
end_time | Optional[datetime] | None | Filter traces before this time |
limit | Optional[int] | 20 | Max traces to return |
page | Optional[int] | 1 | Page number for pagination |
filter_expr | Optional[Dict[str, Any]] | None | Advanced 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:
| Parameter | Type | Description |
|---|---|---|
span_id | str | Unique 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
trace_id | Optional[str] | None | Filter by trace ID |
parent_span_id | Optional[str] | None | Filter by parent span ID |
limit | Optional[int] | 1000 | Max 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
- Trace Reference - Full
Traceobject definition - Span Reference - Full
Spanobject definition