datasets
There is **no `getDatasetByName`** — fetch via `node(id:) { ... on Dataset { ... } }` or the `datasets(filter: DatasetFilter, sort)` connection.
Annotations are named labels/scores attached to spans, traces, sessions, or experiment runs by humans, code, or LLM judges. A **note** is an annotation with the reserved name `note` whose text lives in `explanation`; notes have their own mutations below.
> /plugin marketplace add arize-ai/phoenix > /plugin install arize-phoenix@arize-phoenix
How it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Annotations are named labels/scores attached to spans, traces, sessions, or experiment runs by humans, code, or LLM judges. A **note** is an annotation with the reserved name `note` whose text lives in `explanation`; notes have their own mutations below.
Annotations are named labels/scores attached to spans, traces, sessions, or experiment runs by humans, code, or LLM judges. A **note** is an annotation with the reserved name `note` whose text lives in `explanation`; notes have their own mutations below.
`SpanAnnotation` and `TraceAnnotation` share these fields:
`SpanAnnotation` additionally has `spanId: GlobalID!` and `span`; `TraceAnnotation` has `trace` (but no `traceId` global-id field). `ProjectSessionAnnotation` has the same scalar shape.
`ExperimentRunAnnotation` has the same scalar shape plus `error: String`, and uses `startTime`/`endTime` instead of `createdAt`/`updatedAt`.
Spans that an LLM judge labelled as hallucinated, with the annotation detail:
query Hallucinations($id: ID!) {
node(id: $id) {
... on Project {
spans(first: 20, filterCondition: "annotations['Hallucination'].label == 'hallucinated'") {
edges {
node {
spanId
spanAnnotations { name label score explanation }
}
}
}
}
}
}Root spans for traces with a poor quality annotation:
query PoorQualityTraces($id: ID!) {
node(id: $id) {
... on Project {
spans(
first: 20
rootSpansOnly: true
filterCondition: "trace_annotations['quality'].label == 'poor'"
) {
edges { node { spanId name trace { traceId } } }
}
}
}
}Notes are free-text observations, one mutation per entity kind. Each input takes the entity by **either** its OpenTelemetry id or its Phoenix node id (never both), the text, `annotatorKind` (`LLM` for your own judgment, `HUMAN` only for one the user gave you), `source: API`, and an optional `identifier`. Passing the same `identifier` again for the same entity upserts the note instead of adding a second one; passing none creates a fresh note each time.
mutation NoteTrace($traceId: String!, $note: String!, $identifier: String!) {
createTraceNotes(
input: [{ trace: { otelId: $traceId }, note: $note, annotatorKind: LLM, source: API, identifier: $identifier }]
) {
traceAnnotations { id name explanation identifier }
}
}The mutation is synchronous: the row exists when the response returns. Batch several entities in one call by passing more inputs.
Labelled annotations carry a `name` (the dimension) and a `label` (the outcome), optionally `score` and `explanation`. Their inputs take **Phoenix node ids only** — read `id` when sampling, not the OTel hex id — and require `metadata` (pass `{}`).
Writes upsert on `(entity, name, identifier)`. `patchSpanAnnotations` / `patchTraceAnnotations` edit an existing annotation by its node id; `deleteSpanAnnotations`, `deleteTraceAnnotations`, and `deleteProjectSessionAnnotations` remove by node id — there is no filter-based sweep, so collect ids first (e.g. `Span.spanAnnotations { id identifier }`).
A categorical config makes a label set first-class in the UI (dropdown for annotators, shared vocabulary across runs). The annotation `name` and the config `name` must match.
Repo: arize-ai/phoenix
There is **no `getDatasetByName`** — fetch via `node(id:) { ... on Dataset { ... } }` or the `datasets(filter: DatasetFilter, sort)` connection.
An experiment is one run of a prompt or pipeline over every example in a dataset.
- `Project.spans(timeRange, first, after, sort: SpanSort, rootSpansOnly: Boolean, filterCondition: String)` → connection of `Span`. There is **no `traces`…
There is **no `getPromptByName`** — fetch via `node(id:)` or the `prompts(filter: PromptFilter, labelIds)` connection.
A session groups the traces of one multi-turn conversation.