@arizeai/phoenix-client/spans. See Annotations for the shared annotation model and concepts.
Relevant Source Files
src/spans/addSpanAnnotation.tsfor the single-annotation APIsrc/spans/logSpanAnnotations.tsfor batch loggingsrc/spans/getSpanAnnotations.tsfor reading annotations backsrc/spans/getSpans.tsfor fetching span IDs from Phoenixsrc/spans/types.tsfor theSpanAnnotationinterface
Getting The spanId
spanId is the OpenTelemetry span ID for the operation you want to annotate. In practice, you usually get it one of two ways:
From Running Code With @arizeai/phoenix-otel
If you are already tracing the operation at runtime, capture the span ID from the active span and keep it with the application response, evaluation job, or feedback event that will log the annotation later.
trace.getActiveSpan()?.spanContext().spanId gives you the same OpenTelemetry ID.
From Retrieved Spans During Evaluation
If you are annotating spans after the fact, fetch the spans from Phoenix first and read the OpenTelemetry span ID fromspan.context.span_id.
Add A Single Span Annotation
UseaddSpanAnnotation to attach one annotation to a span. This example records an LLM-as-judge groundedness evaluation:
Batch Log Span Annotations
UselogSpanAnnotations to send multiple annotations in a single request. This is ideal for nightly evaluation pipelines that score many spans at once:
Human Feedback (Thumbs Up/Down)
The most common annotation pattern: capture end-user reactions and log them asHUMAN annotations. Include metadata to correlate feedback with your application’s user model:
Idempotent Upserts With identifier
Annotations are unique by (name, spanId, identifier). The identifier field controls whether a write creates a new annotation or updates an existing one.
Without identifier, a span can only have one annotation per name — writing again overwrites it. Adding an identifier lets you store multiple annotations with the same name on the same span, each keyed by a different identifier. Re-sending the same (name, spanId, identifier) tuple updates that specific annotation in place.
Common patterns:
- One annotation per user — use a user ID as the identifier so each user’s feedback is stored separately and re-submitting updates their previous rating.
- One annotation per evaluator version — use the evaluator version string so pipeline reruns update in place rather than duplicating.
- One annotation per reviewer — use the reviewer’s name or ID so multiple reviewers can each annotate the same span independently.
Read Back Span Annotations
UsegetSpanAnnotations to retrieve annotations for one or more spans.
Basic Read
Filtered Read
Fetch only specific annotation names across multiple spans:excludeAnnotationNames to omit specific names instead — for example, to skip "note" annotations.
Pagination
For large result sets, use cursor-based pagination:Span Notes
addSpanNote attaches a free-text comment to a span. Unlike structured annotations (which are keyed by name + identifier), notes are append-only — each call creates a new note with a unique timestamp-based identifier, so multiple notes naturally accumulate on the same span.
This makes notes a good mechanism for open coding: reviewers can leave qualitative observations on spans during exploratory analysis without needing to define annotation names or scoring rubrics up front. The accumulated notes can later inform what structured annotations to create.
Parameter Reference
SpanAnnotation
| Field | Type | Required | Description |
|---|---|---|---|
spanId | string | Yes | OpenTelemetry span ID (hex, no 0x prefix) |
name | string | Yes | Annotation name (e.g. "groundedness") |
annotatorKind | "HUMAN" | "LLM" | "CODE" | No | Defaults to "HUMAN" |
label | string | No* | Categorical label |
score | number | No* | Numeric score |
explanation | string | No* | Free-text explanation |
identifier | string | No | For idempotent upserts |
metadata | Record<string, unknown> | No | Arbitrary metadata |
label, score, or explanation is required.
getSpanAnnotations Options
| Field | Type | Required | Description |
|---|---|---|---|
project | { projectName } | { projectId } | Yes | Project selector |
spanIds | string[] | Yes | Span IDs to fetch annotations for |
includeAnnotationNames | string[] | No | Only return these annotation names |
excludeAnnotationNames | string[] | No | Exclude these annotation names |
cursor | string | No | Pagination cursor |
limit | number | No | Max results per page (default 100) |
Source Map
src/spans/addSpanAnnotation.tssrc/spans/logSpanAnnotations.tssrc/spans/getSpanAnnotations.tssrc/spans/getSpans.tssrc/spans/addSpanNote.tssrc/spans/types.tssrc/types/annotations.ts

