Judgment Labs Logo
PythonJQL

Queries and terminals

Python JQL roots, time bounds, select terminals, and result row shapes.

judgeval JQL source on GitHub

Root builders

traces(filter=None) -> QueryBuilder
spans(filter=None) -> QueryBuilder
sessions(filter=None) -> QueryBuilder
SourceGrainCanonical fields
tracesOne row per tracetrace_id, span_id, span_name, name, input, output, duration, status, timestamp, session, customer, error
spansOne row per spanCommon fields plus cost, model, parent_span_id
sessionsOne row per sessionCommon fields plus error

Field catalogs can evolve. Use client.discover("fields", source="spans") before generating dynamic query UIs or relying on project-specific attributes.

Builder methods

.where(filter) -> QueryBuilder
.last(window) -> QueryBuilder
.since(since) -> QueryBuilder
.between(start, end) -> QueryBuilder
.rows(*, fields=None, limit=None) -> QueryBuilder
.ids() -> QueryBuilder
.count(by=None) -> QueryBuilder
.recent(n) -> QueryBuilder
.top(n, by) -> QueryBuilder
.ranked(*, by=None, pick=None, within=None) -> QueryBuilder
.agg(func, field, q=None) -> QueryBuilder
.trend(*, metric=None, bucket=None) -> QueryBuilder
.pipe() -> PipelineBuilder
.to_json() -> dict[str, Any]

Builders are immutable: every method returns a new builder. Calling .where() multiple times combines the root filters with canonical all (AND). Calling .last(), .since(), or .between() replaces any earlier time bound.

Serialize without executing with query.to_json().

Time object

The JSON time object must contain exactly one key:

BuilderJSONInput
.last(window){"last":"7d"}Relative duration string
.since(since){"since":"2026-07-01"}Date/time string accepted by the server
.between(start, end){"between":["2026-07-01","2026-07-08"]}Exactly two date/time strings

Omitting time searches all available history unless a deployment-level policy adds a default window.

Select terminals

A source query can contain at most one select. In Python, a second select raises ValueError in the builder. The server also rejects a query containing both select and pipe.

TerminalInputs and defaultsResult rows
rowsfields?: string[], limit?: numberRequested fields, or the source's default row projection
idsNoneDistinct ID columns for the grain: traces returns trace_id; spans returns both trace_id and span_id; sessions returns session_id
countby?: stringNo by: {"count": number}; with by: {"key": value, "count": number}
recentn: intSource rows ordered by newest timestamp
topn: int, by: stringSource rows ordered by the numeric field descending
rankedwithin?: string, by="timestamp", pick=1Traces/spans only. Positional rows plus _rn; pick is a nonzero rank or two-item range 1 <= a <= b
aggfunc, field, q?Traces/spans only. Exactly one row: {"value": number | null}
trendmetric="count", bucket="1d"Count: {"bucket": datetime, "n": number}; rate: adds total and rate

Aggregate rules

func is one of avg, sum, min, max, quantile, or count_distinct. field is always required. q is required only for quantile, rejected for every other function, and must satisfy 0 < q < 1.

Trend rules

metric is count or rate. bucket is a duration string such as 1d or 1w. Rate trends require a filter that defines the numerator.