Skip to content

Filter language ​

One small language filters traces, experiments, experiment rows and dataset rows, on the web (Logs, Experiments, an experiment's rows, a dataset, online scoring rules, review queues' daily fill) and in the API's filter= parameter.

text
field op value [AND|OR field op value …]

Grammar ​

  • A clause is field op value, for example score.factuality < 0.5.
  • Join clauses with AND and OR (any case). AND binds tighter than OR; use parentheses to group: (tag = a OR tag = b) AND score.x >= 1.
  • There is no NOT; use !=.
  • An empty filter matches everything. A filter is at most 2,000 characters.

Operators ​

OperatorMeaningWorks on
= !=Equal, not equal (exact, case-sensitive)Every field
> >= < <=Compare numbersscore.*, delta.*
~Contains, case-insensitiveText fields (not score.* or delta.*)

A missing or undecided value matches only !=. On a field with several values (the models, tools or tags of a trace), = matches when any value is equal, != when none is, and ~ when any contains the text.

Values ​

  • A bare word runs until a space or one of ( ) " ' = ! < > ~, so builtin:task_done, gpt-4.1 and sc_01J9…@2 need no quotes.
  • Quote anything else with "…" or '…'; a backslash escapes the next character: input ~ "say \"hi\"".
  • Quote a value spelled and or or, which would otherwise read as a keyword.
  • Numbers (0.5, -0.25, .5) count as numbers only for score.* and delta.*.

Fields ​

FieldTraces (Logs)Experiments (list)Experiment rowsDataset rows
score.<scorer>The trace's online or human scoreThe scorer's meanThe row's score (mean of its decided trials)—
delta.<scorer>——The row's score minus the baseline row's—
statusok, error, cancelledrunning, done, cancelled, failed, invaliddecided, undecided—
sourceotlp, sdk, gateway, sandboxround, run, sdk, playgroundrun (from a sandbox or runner report), nativemanual, import, log, experiment, review, ai, scenario, test_set
environmentdev, staging, prod, ciThe same——
modelEvery model the trace calledThe target's modelThe judge models—
toolEvery tool span's name———
tagThe trace's metadata.tagsThe experiment's metadata.tagsThe row's tagsThe row's tags
condition——normal, fault, attack, or finer: fault:<tool>:<fault>, attack:<vector>[:<plugin>]The same
input, outputThe trace's input and output (the first 500 characters)—The row's input and outputThe row's input and its expected output

<scorer> is a scorer id: builtin:<slug>, or a project scorer sc_…. On experiment rows, sc_… matches the scorer at any version; on traces, a project scorer is written with its version, sc_…@2.

Field names are case-insensitive; the <scorer> part keeps its case. A field that doesn't apply (marked —) has no value, so only != matches it.

Examples ​

FilterFinds
score.factuality < 0.5Rows (or experiments) whose factuality is below 0.5
delta.builtin:task_done <= -0.25Rows that got clearly worse than the baseline
output ~ "not found"Outputs that mention "not found"
model != 'gpt-4.1'Traces that never called gpt-4.1
tool = refund_create AND status = errorTraces where the refund tool was called and the trace errored
(tag = billing OR tag = refunds) AND score.correctness >= 0.8Rows tagged billing or refunds that scored well
condition = attack AND score.builtin:attack_success > 0Attacks that got through
environment = prod AND score.builtin:correctness < 0.5Production traces online scoring marked low

Errors ​

A filter that doesn't read is underlined on the web where it goes wrong. The API answers 400 bad_filter, with the 0-based character position. For score.factuality ~ high:

json
{ "error": { "code": "bad_filter", "message": "The filter isn't right: score is a number: \"~\" compares words (at 17)", "position": 17 } }

A filter longer than 2,000 characters is 400 invalid_body. The list of datasets and the list of scorers accept filter= but don't apply it yet.

The legal texts on this site are drafts pending legal review and are not yet in force.