Skip to content
Development
Agent

filter-expressions

A filter condition is a Python boolean expression that Phoenix compiles to SQL. There are three filter languages, one each for spans, traces, and sessions, and the argument name picks the language. The vocabularies do not mix.

From plugin
phoenix
12k18 skills18 agents1 MCP

Claude Code

> /plugin marketplace add arize-ai/phoenix
> /plugin install arize-phoenix@arize-phoenix

Agent definition

filter-expressions.md

Filter expressions

A filter condition is a Python boolean expression that Phoenix compiles to SQL. There are three filter languages, one each for spans, traces, and sessions, and the argument name picks the language. The vocabularies do not mix.

| Language | Argument | Keeps | Accepted on | | --- | --- | --- | --- | | Span filter | `filterCondition` | individual spans | `Project.spans`, `Trace.spans`, project aggregates (`recordCount`, `tokenCountTotal`, `costSummary`, `latencyMsQuantile`, ...), `SpanQuery().where(...)` in the Python client, the UI spans filter bar | | Trace filter | `traceFilterCondition` | every span of a matching trace | `Project.spans`, the UI traces filter bar, the `filter` query param on `GET /v1/projects/{id}/traces` and the `filter` argument of `client.traces.get_traces(...)` (Python) and `getTraces({...})` (TypeScript) | | Session filter | `sessionFilterCondition` | sessions | `Project.sessions`, project aggregates, the UI sessions filter bar, the `filter` query param on `GET /v1/projects/{id}/sessions` and the `filter` argument of `client.sessions.list(...)` (Python) and `listSessions({...})` (TypeScript) |

`filterCondition` and `traceFilterCondition` compose on `Project.spans`: matching spans inside matching traces. `filterCondition` and `sessionFilterCondition` are mutually exclusive on the aggregates that accept both.

Checking a condition

| Need | GraphQL field on `Project` | | --- | --- | | Validate before running | `validateSpanFilterCondition(condition:)`, `validateTraceFilterCondition(condition:)`, `validateSessionFilterCondition(condition:)` → `{ isValid errorMessage }` | | List bindable names | `traceFilterVocabulary`, `sessionFilterVocabulary` → `{ name type category description iterableName }` | | Span filter names | no vocabulary field; the table under [Span filter](#span-filter) is exhaustive |

A span filter that returns no rows may be misspelled rather than unmatched. Check the spelling against the vocabulary before concluding there is no data.

Syntax shared by all three languages

Operators

| Category | Accepted | Rejected | | --- | --- | --- | | Comparison | `==` `!=` `<` `<=` `>` `>=`; chained: `500 < latency_ms <= 2000` | `=` | | Missing values | `is None`, `is not None` | `is null`, `null`, `is` with any other value | | Membership | `x in [...]` exact; `'text' in field` case-insensitive substring; `not in` | `None` inside a list; a literal on the left (`1 in [1, 2]`); `like` | | Logic | `and`, `or`, `not`, parentheses | `&&`, `\|\|`, `&`, `\|`, `!` | | Arithmetic | `+` `-` `*` `/` `%` | `**`, `//`, bitwise operators | | Casts | `float(x)`, `int(x)`, `str(x)` | `bool(x)`, any other function | | Comprehensions | `any`, `all`, `len`, `sum`, `max`, `min` over a declared collection: `any(d.cost > 0 for d in cost_details)`; `len` takes a list comprehension | method calls (`name.startswith(...)`), `len(name)` |

Literals

| Kind | Write | Not | | --- | --- | --- | | String | `'LLM'` or `"LLM"` | unquoted: `LLM` | | Number | `100`, `0.5` | quoted: `'100'` | | Boolean | `True`, `False` | `true`, `false` | | Missing | `None` | `null`, `nil` | | Datetime | ISO 8601 with an offset: `'2026-09-01T00:00:00Z'`, `'2026-09-01T00:00:00+00:00'` | without an offset | | List | `['LLM', 'TOOL']`, same type throughout | mixed types; `None` elements |

Rules that differ from Python

  • A missing value fails every comparison, including `!=`. A span without `metadata['tier']`

matches neither `metadata['tier'] == 'premium'` nor `metadata['tier'] != 'premium'`. Spell the missing case out: `metadata['tier'] != 'premium' or metadata['tier'] is None`.

  • `is None` is true for an absent key and for a stored JSON `null`.
  • Every operand of `and`, `or`, and `not` must itself be a condition. `name == 'x' and

metadata['flag']` is rejected; write `metadata['flag'] == True`.

  • The whole expression must be a condition. A bare `True` or a bare field is rejected.
  • `'text' in field` ignores case. `==` and list membership are exact.
  • Annotation accessors expose `.label` (string), `.score` (number), `.explanation` (string), and

`.identifier` (string). The bare accessor is an existence check: `annotations['quality']`.

  • `.identifier` is never missing: it is `''` on an annotation written without one, so test for

that with `== ''` rather than `is None`.

Span filter

Root spans

There is no `traces` connection and no root-span argument. Root-span scoping is a clause in `filterCondition`, and it composes with everything else. The UI's traces table is `spans(filterCondition: "parent_span is None", traceFilterCondition: ...)`.

| Clause | Keeps | Use when | | --- | --- | --- | | `parent_id is None` | spans with no parent id | the default | | `parent_span is None` | those, plus orphans whose parent span was never received | you want every top-level span, including ones whose parent was dropped |

A root span is usually one per trace. Fragmented traces can have several.

Vocabulary

This table is exhaustive. Every identifier not in it is read as an attribute path.

| Name | Type | Notes | | --- | --- | --- | | `span_id`, `trace_id`, `parent_id` | string | OpenTelemetry hex ids | | `name` | string | span name | | `span_kind` | enum | `'CHAIN'`, `'LLM'`, `'RETRIEVER'`, `'EMBEDDING'`, `'TOOL'`, `'AGENT'`, `'RERANKER'`, `'GUARDRAIL'`, `'EVALUATOR'`, `'PROMPT'`, `'DECISION'`, `'UNKNOWN'`; literals are uppercased for you | | `status_code` | enum | `'OK'`, `'ERROR'`, `'UNSET'`; literals are uppercased for you | | `status_message` | string | error text | | `latency_ms` | number | | | `start_time`, `end_time` | datetime | | | `cumulative_llm_token_count_prompt`, `cumulative_llm_token_count_completion`, `cumulative_llm_token_count_total` | number | this span plus its descendants | | `llm.token_count.prompt`, `llm.token_count.completion`, `llm.token_count.total` | number | this span alone | | `total_cost`, `prompt_cost`, `completion_cost` | number | `0` whe

Read more
@arize-ai
Ships withphoenix

AI Observability & Evaluation

12k10 skills18 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
12.1k
Star history of arize-ai/phoenix on GitHub, a chart by star-history.com

Other agents on phoenix.

bug-fixer

bug-fixer

Agent

Leads one Phoenix bug from report to draft PR - reproduce, fix, review, revise.

@arize-ai@arize-aiInstall Agent
bug-reproducer

bug-reproducer

Agent

Reproduces a reported Phoenix bug as a failing automated test. Give it the issue number, labels, the bootstrap report and the…

@arize-ai@arize-aiInstall Agent
cloud-triage

cloud-triage

Agent

Reads a day of Phoenix Cloud production errors from Datadog, decides which are bugs a maintainer should fix, and makes sure each…

@arize-ai@arize-aiInstall Agent
docs-writer

docs-writer

Agent

Makes one Phoenix documentation change, grounded in the current code, and opens a draft PR.

@arize-ai@arize-aiInstall Agent
feature-analyst

feature-analyst

Agent

Analyst that turns a Phoenix feature request into an implementation plan grounded in the existing code, starting with a probe…

@arize-ai@arize-aiInstall Agent

More agents from other plugins.

a11y-architect
Auto-invoked

a11y-architect

Agent

Accessibility Architect specializing in WCAG 2.2 compliance for Web and Native platforms. Use PROACTIVELY when designing UI…

ecc12d293k
@affaan-m@affaan-mInstall Agent
analyze-pass-impact

analyze-pass-impact

Agent

Analyzes how a specific topic affects a group of compiler passes. Used by the /plan-update skill to parallelize research across…

react2d252k
@facebook@facebookInstall Agent
orchestrator

orchestrator

Agent

- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as…

codex1d135k
@openai@openaiInstall Agent
cavecrew-builder

cavecrew-builder

Agent

Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard…

caveman2d119k
@juliusbrussee@juliusbrusseeInstall Agent

Questions about filter-expressions.

Which coding agents can use filter-expressions?
filter-expressions installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.