Spans#
- class Spans(client, *, _guard=None)#
Bases:
objectProvides methods for interacting with span resources.
This class offers both regular and DataFrame-based methods for retrieving, logging, and managing spans and their annotations.
Examples
Non-DataFrame methods:
from phoenix.client import Client client = Client() # Get spans as list spans = client.spans.get_spans( project_identifier="my-project", limit=100 ) # Get span annotations as list annotations = client.spans.get_span_annotations( span_ids=["span1", "span2"], project_identifier="my-project" ) # Log spans spans = [ { "id": "1", "name": "test", "context": {"trace_id": "123", "span_id": "456"}, } ] result = client.spans.log_spans( project_identifier="my-project", spans=spans ) print(f"Queued {result['total_queued']} spans")
DataFrame methods:
from phoenix.client.types.spans import SpanQuery # Get spans as DataFrame query = SpanQuery().select(annotations["relevance"]) df = client.spans.get_spans_dataframe(query=query) # Get span annotations as DataFrame annotations_df = client.spans.get_span_annotations_dataframe( span_ids=["span1", "span2"], project_identifier="my-project" ) # Delete a span client.spans.delete(span_identifier="abc123def456")
- add_document_annotation(*, span_id, document_position, annotation_name, annotator_kind='HUMAN', label=None, score=None, explanation=None, metadata=None, sync=False)#
Add a single span document annotation.
- Parameters:
span_id (str) – The ID of the span to annotate.
document_position (int) – The 0-based index of the document within the span.
annotation_name (str) – The name of the annotation.
annotator_kind (Literal["LLM", "CODE", "HUMAN"]) – The kind of annotator used for the annotation. Must be one of “LLM”, “CODE”, or “HUMAN”. Defaults to “HUMAN”.
label (Optional[str]) – The label assigned by the annotation.
score (Optional[float]) – The score assigned by the annotation.
explanation (Optional[str]) – Explanation of the annotation result.
metadata (Optional[dict[str, Any]]) – Additional metadata for the annotation.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation ID. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, the inserted span document
annotation containing an ID. If sync is False, None.
- Return type:
Optional[InsertedSpanDocumentAnnotation]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if at least one of label, score, or explanation is not provided.
Example:
from phoenix.client import Client client = Client() # Add a single document annotation with sync response annotation = client.spans.add_document_annotation( span_id="abc123", document_position=0, annotation_name="relevance", label="relevant", score=0.9, explanation="The document is relevant to the query.", sync=True, )
- add_span_annotation(*, span_id, annotation_name, annotator_kind='HUMAN', label=None, score=None, explanation=None, metadata=None, identifier=None, sync=False)#
Add a single span annotation.
- Parameters:
span_id (str) – The ID of the span to annotate.
annotation_name (str) – The name of the annotation.
annotator_kind (Literal["LLM", "CODE", "HUMAN"]) – The kind of annotator used for the annotation. Must be one of “LLM”, “CODE”, or “HUMAN”. Defaults to “HUMAN”.
label (Optional[str]) – The label assigned by the annotation.
score (Optional[float]) – The score assigned by the annotation.
explanation (Optional[str]) – Explanation of the annotation result.
metadata (Optional[dict[str, Any]]) – Additional metadata for the annotation.
identifier (Optional[str]) – An optional identifier for the annotation. Each annotation is uniquely identified by the combination of name, span_id, and identifier (where a null identifier is equivalent to an empty string). If an annotation with the same name, span_id, and identifier already exists, it will be updated. Using a non-empty identifier allows you to have multiple annotations with the same name and span_id. Most of the time, you can leave this as None - it will also update the record with identifier=”” if it exists.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation ID. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, the inserted span annotation
containing an ID. If sync is False, None.
- Return type:
Optional[InsertedSpanAnnotation]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if at least one of label, score, or explanation is not provided.
Example:
from phoenix.client import Client client = Client() # Add a single annotation with sync response annotation = client.spans.add_span_annotation( span_id="abc123", annotation_name="sentiment", label="positive", score=0.9, explanation="The text expresses a positive sentiment.", sync=True, )
- add_span_note(*, span_id, note)#
Add a note to a span.
Notes are append-only: each call creates a new note with an auto-generated UUIDv4 identifier, so multiple notes accumulate on the same span. Structured annotations, by contrast, are keyed by (name, span_id, identifier) — to keep multiple structured annotations with the same name on a span, supply distinct identifiers; otherwise re-writing the same name overwrites the existing one.
- Parameters:
span_id (str) – The OpenTelemetry span ID of the span to add the note to.
note (str) – The text content of the note.
- Returns:
The inserted span annotation containing the ID.
- Return type:
InsertedSpanAnnotation
- Raises:
ValueError – If span_id or note is empty (after stripping whitespace).
httpx.HTTPStatusError – If the span is not found (404) or other API errors.
httpx.HTTPError – If the request fails.
Example:
from phoenix.client import Client client = Client() # Add a note to a span result = client.spans.add_span_note( span_id="abc123def456", note="This span shows interesting behavior.", ) print(f"Note created with ID: {result['id']}")
- delete(*, span_identifier, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Deletes a single span by identifier.
Important: This operation deletes ONLY the specified span itself and does NOT delete its descendants/children. All child spans will remain in the trace and become orphaned (their parent_id will point to a non-existent span).
- Behavior:
Deletes only the target span (preserves all descendant spans)
If this was the last span in the trace, the trace record is also deleted
If the deleted span had a parent, its cumulative metrics (error count, token counts) are subtracted from all ancestor spans in the chain
Note
This operation is irreversible and may create orphaned spans.
- Parameters:
span_identifier (str) – The span identifier: either a relay GlobalID or OpenTelemetry span_id.
timeout (Optional[int]) – Optional request timeout in seconds.
- Raises:
httpx.HTTPStatusError – If the span is not found (404) or other API errors.
httpx.TimeoutException – If the request times out.
Example:
from phoenix.client import Client client = Client() # Delete by OpenTelemetry span_id client.spans.delete_span(span_identifier="051581bf3cb55c13") # Delete by Phoenix Global ID client.spans.delete(span_identifier="U3BhbjoxMjM=")
- get_span_annotations(*, span_ids=None, spans=None, project_identifier, include_annotation_names=None, exclude_annotation_names=None, limit=1000, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Fetches span annotations and returns them as a list of SpanAnnotation objects.
Exactly one of span_ids or spans should be provided.
- Parameters:
span_ids (Optional[Iterable[str]]) – An iterable of span IDs.
spans (Optional[Iterable[v1.Span]]) – A list of Span objects (typically returned by get_spans).
project_identifier (str) – The project identifier (name or ID) used in the API path.
include_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to include. If provided, only annotations with these names will be returned.
exclude_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to exclude from results. Defaults to [“note”] to exclude note annotations, which are reserved for notes added via the UI.
limit (int) – Maximum number of annotations returned per request page. Defaults to 1000.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A list of SpanAnnotation objects.
- Return type:
list[SpanAnnotation]
- Raises:
ValueError – If not exactly one of span_ids or spans is provided.
httpx.HTTPStatusError – If the API returns an error response.
- get_span_annotations_dataframe(*, spans_dataframe=None, span_ids=None, spans=None, project_identifier='default', include_annotation_names=None, exclude_annotation_names=None, limit=1000, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Fetches span annotations and returns them as a pandas DataFrame.
Exactly one of spans_dataframe, span_ids, or spans should be provided.
- Parameters:
spans_dataframe (Optional[pd.DataFrame]) – A DataFrame (typically returned by get_spans_dataframe) with a context.span_id or span_id column.
span_ids (Optional[Iterable[str]]) – An iterable of span IDs.
spans (Optional[Iterable[v1.Span]]) – A list of Span objects (typically returned by get_spans).
project_identifier (str) – The project identifier (name or ID) used in the API path. Defaults to “default”.
include_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to include. If provided, only annotations with these names will be returned.
exclude_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to exclude from results. Defaults to [“note”] to exclude note annotations, which are reserved for notes added via the UI.
limit (int) – Maximum number of annotations returned per request page. Defaults to 1000.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A DataFrame where each row corresponds to a single span annotation.
- Return type:
pd.DataFrame
- Raises:
ValueError – If not exactly one of spans_dataframe, span_ids, or spans is provided, or if the context.span_id or span_id column is missing from spans_dataframe.
ImportError – If pandas is not installed.
httpx.HTTPStatusError – If the API returns an error response.
- get_spans(*, project_identifier, start_time=None, end_time=None, trace_ids=None, parent_id=None, name=None, span_kind=None, status_code=None, attributes=None, limit=100, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Retrieves spans with simple filtering options.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
start_time (Optional[datetime]) – Optional start time for filtering (inclusive lower bound).
end_time (Optional[datetime]) – Optional end time for filtering (exclusive upper bound).
trace_ids (Optional[Sequence[str]]) – Optional list of trace IDs to filter by. Requires Phoenix server >= 13.9.0.
parent_id (Optional[str]) – Optional parent span ID to filter by. Use “null” to get root spans only.
name (Optional[Union[str, Sequence[str]]]) – Optional span name(s) to filter by. Requires Phoenix server >= 13.15.0.
span_kind (Optional[Union[str, Sequence[str]]]) – Optional span kind(s) to filter by (e.g. LLM, CHAIN, TOOL). Requires Phoenix server >= 13.15.0.
status_code (Optional[Union[str, Sequence[str]]]) – Optional status code(s) to filter by (e.g. OK, ERROR, UNSET). Requires Phoenix server >= 13.15.0.
attributes (Optional[dict[str, Union[str, int, float, bool]]]) – Optional dictionary of attribute key-value pairs to filter by; multiple entries are AND-ed together. The Python type of each value selects how the stored attribute is matched: a
strmatches a stored string;int,float, andboolmatch the corresponding native type. To match a stored string whose contents look like a number or boolean (e.g. a user ID stored as"12345"), pass it as a Pythonstr. Requires Phoenix server >= 14.9.0.limit (int) – Maximum number of spans to return. Defaults to 100.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A list of Span objects.
- Return type:
list[v1.Span]
- Raises:
httpx.HTTPStatusError – If the API returns an error response.
ValueError – If a float value in
attributesis non-finite (nan or inf).
- get_spans_dataframe(*, query=None, start_time=None, end_time=None, limit=1000, root_spans_only=None, project_identifier=None, project_name=None, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Retrieves spans based on the provided filter conditions.
- Parameters:
query (Optional[SpanQuery]) – A SpanQuery object defining the query criteria.
start_time (Optional[datetime]) – Optional start time for filtering.
end_time (Optional[datetime]) – Optional end time for filtering.
limit (int) – Maximum number of spans to return. Defaults to 1000.
root_spans_only (Optional[bool]) – Whether to return only root spans.
project_name (Optional[str]) – Optional project name to filter by. Deprecated, use project_identifier to also specify by the project id.
project_identifier (Optional[str]) – Optional project identifier (name or id) to filter by.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A pandas DataFrame containing the retrieved spans.
- Return type:
pd.DataFrame
- Raises:
ImportError – If pandas is not installed.
- log_document_annotations(*, document_annotations, sync=False)#
Log multiple span document annotations.
- Parameters:
document_annotations (list[SpanDocumentAnnotationData]) – A list of span document annotation data objects.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, a list of inserted
span document annotations containing IDs. If sync is False, None.
- Return type:
Optional[list[InsertedSpanDocumentAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If span_document_annotations is empty.
Example:
from phoenix.client import Client from phoenix.client.resources.spans import SpanDocumentAnnotationData client = Client() # Log multiple document annotations annotations = [ SpanDocumentAnnotationData( name="relevance", span_id="span-123", document_position=0, annotator_kind="HUMAN", result={"label": "relevant", "score": 0.9} ), SpanDocumentAnnotationData( name="accuracy", span_id="span-123", document_position=1, annotator_kind="LLM", result={"label": "accurate", "score": 0.8} ), ] client.spans.log_document_annotations( span_document_annotations=annotations )
- log_document_annotations_dataframe(*, dataframe, annotation_name=None, annotator_kind=None, sync=False)#
Log multiple span document annotations from a pandas DataFrame.
This method allows you to create multiple span document annotations at once by providing the data in a pandas DataFrame. The DataFrame can either include name or annotation_name columns (but not both) and annotator_kind column, or you can specify global values for all rows. The data is processed in chunks of 100 rows for efficient batch processing.
- Parameters:
dataframe (pd.DataFrame) – A pandas DataFrame containing the annotation data. Must include either a “name” or “annotation_name” column (but not both) or provide a global annotation_name parameter. Similarly, must include an “annotator_kind” column or provide a global annotator_kind. The span_id and document_position can be either columns in the DataFrame or span_id will be taken from the DataFrame index. Optional columns include: “label”, “score”, “explanation”, and “metadata”.
annotation_name (Optional[str]) – The name to use for all annotations. If provided, this name will be used for all rows in the DataFrame. Cannot be used if the DataFrame contains a “name” or “annotation_name” column.
annotator_kind (Optional[Literal["LLM", "CODE", "HUMAN"]]) – The annotator kind to use for all annotations. If provided, this kind will be used for all rows in the DataFrame. Cannot be used if the DataFrame contains an “annotator_kind” column.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, a list of inserted
span document annotations containing IDs. If sync is False, None.
- Return type:
Optional[list[InsertedSpanDocumentAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the DataFrame is invalid or empty.
Example:
import pandas as pd from phoenix.client import Client client = Client() # Log document annotations from DataFrame df = pd.DataFrame({ "name": ["relevance", "accuracy"], "span_id": ["span_123", "span_456"], "document_position": [0, 1], "annotator_kind": ["HUMAN", "LLM"], "label": ["relevant", "accurate"], "score": [0.9, 0.8] }) client.spans.log_document_annotations_dataframe(dataframe=df)
- log_span_annotations(*, span_annotations, sync=False)#
Log multiple span annotations.
- Parameters:
span_annotations (Iterable[SpanAnnotationData]) – An iterable of span annotation data to log. Each annotation must include at least a span_id, name, and annotator_kind, and at least one of label, score, or explanation.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
If sync is True, a list of inserted span annotations, each containing an ID. If sync is False, None.
- Return type:
Optional[list[InsertedSpanAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if the input is invalid.
- log_span_annotations_dataframe(*, dataframe, annotator_kind=None, annotation_name=None, sync=False)#
Log multiple span annotations from a pandas DataFrame.
This method allows you to create multiple span annotations at once by providing the data in a pandas DataFrame. The DataFrame can either include name or annotation_name columns (but not both) and annotator_kind column, or you can specify global values for all rows. The data is processed in chunks of 100 rows for efficient batch processing.
- Parameters:
dataframe (pd.DataFrame) – A pandas DataFrame containing the annotation data. Must include either a “name” or “annotation_name” column (but not both) or provide a global annotation_name parameter. Similarly, must include an “annotator_kind” column or provide a global annotator_kind. The span_id can be either a column in the DataFrame or will be taken from the DataFrame index. Optional columns include: “label”, “score”, “explanation”, “metadata”, and “identifier”.
annotator_kind (Optional[Literal["LLM", "CODE", "HUMAN"]]) – The kind of annotator used for all annotations. If provided, this value will be used for all rows and the DataFrame does not need to include an “annotator_kind” column. Must be one of “LLM”, “CODE”, or “HUMAN”.
annotation_name (Optional[str]) – The name to use for all annotations. If provided, this value will be used for all rows and the DataFrame does not need to include a “name” or “annotation_name” column.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, a list of all inserted span
annotations. If sync is False, None.
- Return type:
Optional[list[InsertedSpanAnnotation]]
- Raises:
ImportError – If pandas is not installed.
ValueError – If the DataFrame is missing required columns, if both “name” and “annotation_name” columns are present, or if no valid annotation data is provided.
Example:
import pandas as pd from phoenix.client import Client client = Client() # Using name and annotator_kind from DataFrame with span_id column df1 = pd.DataFrame({ "name": ["sentiment", "toxicity"], "span_id": ["span_123", "span_456"], "annotator_kind": ["HUMAN", "LLM"], "label": ["positive", "low"], "score": [0.9, 0.1] }) client.spans.log_span_annotations_dataframe(dataframe=df1) # Using annotation_name and annotator_kind from DataFrame df2 = pd.DataFrame({ "annotation_name": ["sentiment", "toxicity"], "span_id": ["span_789", "span_012"], "annotator_kind": ["HUMAN", "LLM"], "label": ["positive", "low"], "score": [0.9, 0.1] }) client.spans.log_span_annotations_dataframe(dataframe=df2) # Using global name and annotator_kind with span_id from index df3 = pd.DataFrame({ "label": ["positive", "low"] }, index=["span_345", "span_678"]) client.spans.log_span_annotations_dataframe( dataframe=df3, annotation_name="sentiment", # applies to all rows annotator_kind="HUMAN" # applies to all rows )
- log_spans(*, project_identifier, spans, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Logs spans to a project.
If any spans are invalid or duplicates, no spans will be logged and a SpanCreationError will be raised with details about the failed spans.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
spans (Sequence[v1.Span]) – A sequence of Span objects to log.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
- A CreateSpansResponseBody with statistics about
the operation. When successful, total_queued will equal total_received.
- Return type:
v1.CreateSpansResponseBody
- Raises:
SpanCreationError – If any spans failed validation (invalid or duplicates).
httpx.HTTPStatusError – If the API returns an unexpected error response.
httpx.TimeoutException – If the request times out.
- log_spans_dataframe(*, project_identifier, spans_dataframe, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Logs spans to a project from a pandas DataFrame.
If any spans are invalid or duplicates, no spans will be logged and a SpanCreationError will be raised with details about the failed spans.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
spans_dataframe (pd.DataFrame) – A pandas DataFrame with a context.span_id or span_id column.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
- A CreateSpansResponseBody with statistics about
the operation. When successful, total_queued will equal total_received.
- Return type:
v1.CreateSpansResponseBody
- Raises:
SpanCreationError – If any spans failed validation (invalid or duplicates).
httpx.HTTPStatusError – If the API returns an unexpected error response.
httpx.TimeoutException – If the request times out.
- class AsyncSpans(client, *, _guard=None)#
Bases:
objectProvides async methods for interacting with span resources.
This class offers both regular and DataFrame-based async methods for retrieving, logging, and managing spans and their annotations.
Examples
Non-DataFrame methods:
from phoenix.client import AsyncClient client = AsyncClient() # Get spans as list spans = await client.spans.get_spans( project_identifier="my-project", limit=100 ) # Get span annotations as list annotations = await client.spans.get_span_annotations( span_ids=["span1", "span2"], project_identifier="my-project" ) # Log spans spans = [ { "id": "1", "name": "test", "context": {"trace_id": "123", "span_id": "456"}, } ] result = await client.spans.log_spans( project_identifier="my-project", spans=spans ) print(f"Queued {result['total_queued']} spans")
DataFrame methods:
from phoenix.client.types.spans import SpanQuery # Get spans as DataFrame query = SpanQuery().select(annotations["relevance"]) df = await client.spans.get_spans_dataframe(query=query) # Get span annotations as DataFrame annotations_df = await client.spans.get_span_annotations_dataframe( span_ids=["span1", "span2"], project_identifier="my-project" ) # Delete a span await client.spans.delete(span_identifier="abc123def456")
- async add_document_annotation(*, span_id, document_position, annotation_name, annotator_kind='HUMAN', label=None, score=None, explanation=None, metadata=None, sync=False)#
Add a single span document annotation asynchronously.
- Parameters:
span_id (str) – The ID of the span to annotate.
document_position (int) – The 0-based index of the document within the span.
annotation_name (str) – The name of the annotation.
annotator_kind (Literal["LLM", "CODE", "HUMAN"]) – The kind of annotator used for the annotation. Must be one of “LLM”, “CODE”, or “HUMAN”. Defaults to “HUMAN”.
label (Optional[str]) – The label assigned by the annotation.
score (Optional[float]) – The score assigned by the annotation.
explanation (Optional[str]) – Explanation of the annotation result.
metadata (Optional[dict[str, Any]]) – Additional metadata for the annotation.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation ID. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, the inserted span document
annotation containing an ID. If sync is False, None.
- Return type:
Optional[InsertedSpanDocumentAnnotation]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if at least one of label, score, or explanation is not provided.
Example:
from phoenix.client import AsyncClient async_client = AsyncClient() # Add a single document annotation with sync response annotation = await async_client.spans.add_document_annotation( span_id="abc123", document_position=0, annotation_name="relevance", label="relevant", score=0.9, explanation="The document is relevant to the query.", sync=True, )
- async add_span_annotation(*, span_id, annotation_name, annotator_kind='HUMAN', label=None, score=None, explanation=None, metadata=None, identifier=None, sync=False)#
Add a single span annotation asynchronously.
- Parameters:
span_id (str) – The ID of the span to annotate.
annotation_name (str) – The name of the annotation.
annotator_kind (Literal["LLM", "CODE", "HUMAN"]) – The kind of annotator used for the annotation. Must be one of “LLM”, “CODE”, or “HUMAN”. Defaults to “HUMAN”.
label (Optional[str]) – The label assigned by the annotation.
score (Optional[float]) – The score assigned by the annotation.
explanation (Optional[str]) – Explanation of the annotation result.
metadata (Optional[dict[str, Any]]) – Additional metadata for the annotation.
identifier (Optional[str]) – An optional identifier for the annotation. Each annotation is uniquely identified by the combination of name, span_id, and identifier (where a null identifier is equivalent to an empty string). If an annotation with the same name, span_id, and identifier already exists, it will be updated. Using a non-empty identifier allows you to have multiple annotations with the same name and span_id. Most of the time, you can leave this as None - it will also update the record with identifier=”” if it exists.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation ID. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
If sync is True, the inserted span annotation containing an ID. If sync is False, None.
- Return type:
Optional[InsertedSpanAnnotation]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if at least one of label, score, or explanation is not provided.
Example:
from phoenix.client import AsyncClient async_client = AsyncClient() # Add a single annotation with sync response annotation = await async_client.spans.add_span_annotation( span_id="abc123", annotation_name="sentiment", label="positive", score=0.9, explanation="The text expresses a positive sentiment.", sync=True, )
- async add_span_note(*, span_id, note)#
Add a note to a span asynchronously.
Notes are append-only: each call creates a new note with an auto-generated UUIDv4 identifier, so multiple notes accumulate on the same span. Structured annotations, by contrast, are keyed by (name, span_id, identifier) — to keep multiple structured annotations with the same name on a span, supply distinct identifiers; otherwise re-writing the same name overwrites the existing one.
- Parameters:
span_id (str) – The OpenTelemetry span ID of the span to add the note to.
note (str) – The text content of the note.
- Returns:
The inserted span annotation containing the ID.
- Return type:
InsertedSpanAnnotation
- Raises:
ValueError – If span_id or note is empty (after stripping whitespace).
httpx.HTTPStatusError – If the span is not found (404) or other API errors.
httpx.HTTPError – If the request fails.
Example:
from phoenix.client import AsyncClient client = AsyncClient() # Add a note to a span result = await client.spans.add_span_note( span_id="abc123def456", note="This span shows interesting behavior.", ) print(f"Note created with ID: {result['id']}")
- async delete(*, span_identifier, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Deletes a single span by identifier.
Important: This operation deletes ONLY the specified span itself and does NOT delete its descendants/children. All child spans will remain in the trace and become orphaned (their parent_id will point to a non-existent span).
- Behavior:
Deletes only the target span (preserves all descendant spans)
If this was the last span in the trace, the trace record is also deleted
If the deleted span had a parent, its cumulative metrics (error count, token counts) are subtracted from all ancestor spans in the chain
Note
This operation is irreversible and may create orphaned spans.
- Parameters:
span_identifier (str) – The span identifier: either a relay GlobalID or OpenTelemetry span_id.
timeout (Optional[int]) – Optional request timeout in seconds.
- Raises:
httpx.HTTPStatusError – If the span is not found (404) or other API errors.
httpx.TimeoutException – If the request times out.
Examples:
from phoenix.client import AsyncClient client = AsyncClient() # Delete by OpenTelemetry span_id await client.spans.delete(span_identifier="abc123def456") # Delete by Phoenix Global ID await client.spans.delete(span_identifier="U3BhbjoxMjM=")
- async get_span_annotations(*, span_ids=None, spans=None, project_identifier, include_annotation_names=None, exclude_annotation_names=None, limit=1000, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Fetches span annotations and returns them as a list of SpanAnnotation objects.
Exactly one of span_ids or spans should be provided.
- Parameters:
span_ids (Optional[Iterable[str]]) – An iterable of span IDs.
spans (Optional[Iterable[v1.Span]]) – A list of Span objects (typically returned by get_spans).
project_identifier (str) – The project identifier (name or ID) used in the API path.
include_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to include. If provided, only annotations with these names will be returned.
exclude_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to exclude from results. Defaults to [“note”] to exclude note annotations, which are reserved for notes added via the UI.
limit (int) – Maximum number of annotations returned per request page. Defaults to 1000.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A list of SpanAnnotation objects.
- Return type:
list[SpanAnnotation]
- Raises:
ValueError – If not exactly one of span_ids or spans is provided.
httpx.HTTPStatusError – If the API returns an error response.
- async get_span_annotations_dataframe(*, spans_dataframe=None, span_ids=None, spans=None, project_identifier, include_annotation_names=None, exclude_annotation_names=None, limit=1000, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Fetches span annotations and returns them as a pandas DataFrame.
Exactly one of spans_dataframe, span_ids, or spans should be provided.
- Parameters:
spans_dataframe (Optional[pd.DataFrame]) – A DataFrame (typically returned by get_spans_dataframe) with a context.span_id or span_id column.
span_ids (Optional[Iterable[str]]) – An iterable of span IDs.
spans (Optional[Iterable[v1.Span]]) – A list of Span objects (typically returned by get_spans).
project_identifier (str) – The project identifier (name or ID) used in the API path.
include_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to include. If provided, only annotations with these names will be returned.
exclude_annotation_names (Optional[Sequence[str]]) – Optional list of annotation names to exclude from results. Defaults to [“note”] to exclude note annotations, which are reserved for notes added via the UI.
limit (int) – Maximum number of annotations returned per request page. Defaults to 1000.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A DataFrame where each row corresponds to a single span annotation.
- Return type:
pd.DataFrame
- Raises:
ValueError – If not exactly one of spans_dataframe, span_ids, or spans is provided, or if the context.span_id or span_id column is missing from spans_dataframe.
ImportError – If pandas is not installed.
httpx.HTTPStatusError – If the API returns an error response.
- async get_spans(*, project_identifier, start_time=None, end_time=None, trace_ids=None, parent_id=None, name=None, span_kind=None, status_code=None, attributes=None, limit=100, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Retrieves spans with simple filtering options.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
start_time (Optional[datetime]) – Optional start time for filtering (inclusive lower bound).
end_time (Optional[datetime]) – Optional end time for filtering (exclusive upper bound).
trace_ids (Optional[Sequence[str]]) – Optional list of trace IDs to filter by. Requires Phoenix server >= 13.9.0.
parent_id (Optional[str]) – Optional parent span ID to filter by. Use “null” to get root spans only.
name (Optional[Union[str, Sequence[str]]]) – Optional span name(s) to filter by. Requires Phoenix server >= 13.15.0.
span_kind (Optional[Union[str, Sequence[str]]]) – Optional span kind(s) to filter by (e.g. LLM, CHAIN, TOOL). Requires Phoenix server >= 13.15.0.
status_code (Optional[Union[str, Sequence[str]]]) – Optional status code(s) to filter by (e.g. OK, ERROR, UNSET). Requires Phoenix server >= 13.15.0.
attributes (Optional[dict[str, Union[str, int, float, bool]]]) – Optional dictionary of attribute key-value pairs to filter by; multiple entries are AND-ed together. The Python type of each value selects how the stored attribute is matched: a
strmatches a stored string;int,float, andboolmatch the corresponding native type. To match a stored string whose contents look like a number or boolean (e.g. a user ID stored as"12345"), pass it as a Pythonstr. Requires Phoenix server >= 14.9.0.limit (int) – Maximum number of spans to return. Defaults to 100.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A list of Span objects.
- Return type:
list[v1.Span]
- Raises:
httpx.HTTPStatusError – If the API returns an error response.
ValueError – If a float value in
attributesis non-finite (nan or inf).
- async get_spans_dataframe(*, query=None, start_time=None, end_time=None, limit=1000, root_spans_only=None, project_name=None, project_identifier=None, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Retrieves spans based on the provided filter conditions.
- Parameters:
query (Optional[SpanQuery]) – A SpanQuery object defining the query criteria.
start_time (Optional[datetime]) – Optional start time for filtering.
end_time (Optional[datetime]) – Optional end time for filtering.
limit (int) – Maximum number of spans to return. Defaults to 1000.
root_spans_only (Optional[bool]) – Whether to return only root spans.
project_name (Optional[str]) – Optional project name to filter by. Deprecated, use project_identifier to also specify by the project id.
project_identifier (Optional[str]) – Optional project identifier (name or id) to filter by.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
A pandas DataFrame containing the retrieved spans.
- Return type:
pd.DataFrame
- Raises:
ImportError – If pandas is not installed.
- async log_document_annotations(*, document_annotations, sync=False)#
Log multiple span document annotations asynchronously.
- Parameters:
document_annotations (list[SpanDocumentAnnotationData]) – A list of span document annotation data objects.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, a list of inserted
span document annotations containing IDs. If sync is False, None.
- Return type:
Optional[list[InsertedSpanDocumentAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If span_document_annotations is empty.
Example:
from phoenix.client import AsyncClient from phoenix.client.resources.spans import SpanDocumentAnnotationData async_client = AsyncClient() # Log multiple document annotations annotations = [ SpanDocumentAnnotationData( name="relevance", span_id="span-123", document_position=0, annotator_kind="HUMAN", result={"label": "relevant", "score": 0.9} ), SpanDocumentAnnotationData( name="accuracy", span_id="span-123", document_position=1, annotator_kind="LLM", result={"label": "accurate", "score": 0.8} ), ] await async_client.spans.log_document_annotations( span_document_annotations=annotations )
- async log_document_annotations_dataframe(*, dataframe, annotation_name=None, annotator_kind=None, sync=False)#
Log multiple span document annotations from a pandas DataFrame asynchronously.
This method allows you to create multiple span document annotations at once by providing the data in a pandas DataFrame. The DataFrame can either include name or annotation_name columns (but not both) and annotator_kind column, or you can specify global values for all rows. The data is processed in chunks of 100 rows for efficient batch processing.
- Parameters:
dataframe (pd.DataFrame) – A pandas DataFrame containing the annotation data. Must include either a “name” or “annotation_name” column (but not both) or provide a global annotation_name parameter. Similarly, must include an “annotator_kind” column or provide a global annotator_kind. The span_id and document_position can be either columns in the DataFrame or span_id will be taken from the DataFrame index. Optional columns include: “label”, “score”, “explanation”, “metadata”, and “identifier”.
annotation_name (Optional[str]) – The name to use for all annotations. If provided, this name will be used for all rows in the DataFrame. Cannot be used if the DataFrame contains a “name” or “annotation_name” column.
annotator_kind (Optional[Literal["LLM", "CODE", "HUMAN"]]) – The annotator kind to use for all annotations. If provided, this kind will be used for all rows in the DataFrame. Cannot be used if the DataFrame contains an “annotator_kind” column.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
- If sync is True, a list of inserted
span document annotations containing IDs. If sync is False, None.
- Return type:
Optional[list[InsertedSpanDocumentAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the DataFrame is invalid or empty.
Example:
import pandas as pd from phoenix.client import AsyncClient async_client = AsyncClient() # Log document annotations from DataFrame df = pd.DataFrame({ "name": ["relevance", "accuracy"], "span_id": ["span_123", "span_456"], "document_position": [0, 1], "annotator_kind": ["HUMAN", "LLM"], "label": ["relevant", "accurate"], "score": [0.9, 0.8] }) await async_client.spans.log_document_annotations_dataframe(dataframe=df)
- async log_span_annotations(*, span_annotations, sync=False)#
Log multiple span annotations asynchronously.
- Parameters:
span_annotations (Iterable[SpanAnnotationData]) – An iterable of span annotation data to log. Each annotation must include at least a span_id, name, and annotator_kind, and at least one of label, score, or explanation.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
If sync is True, a list of inserted span annotations, each containing an ID. If sync is False, None.
- Return type:
Optional[list[InsertedSpanAnnotation]]
- Raises:
httpx.HTTPError – If the request fails.
ValueError – If the response is invalid or if the input is invalid.
Example:
from phoenix.client import AsyncClient from phoenix.client.resources.spans import SpanAnnotationData async_client = AsyncClient() # Create span annotation data objects using dictionaries annotation1 = SpanAnnotationData( name="sentiment", span_id="72dda197b0e1b3ef", annotator_kind="HUMAN", result={"label": "positive", "score": 0.9}, ) annotation2 = SpanAnnotationData( name="sentiment", span_id="72dda197b0e1b3ef", annotator_kind="HUMAN", result={"label": "negative", "score": 0.1}, ) # Log multiple annotations at once await async_client.spans.log_span_annotations( span_annotations=[annotation1, annotation2], )
- async log_span_annotations_dataframe(*, dataframe, annotation_name=None, annotator_kind=None, sync=False)#
Log multiple span annotations from a pandas DataFrame asynchronously.
This method allows you to create multiple span annotations at once by providing the data in a pandas DataFrame. The DataFrame can either include name or annotation_name columns (but not both) and annotator_kind column, or you can specify global values for all rows. The data is processed in chunks of 100 rows for efficient batch processing.
- Parameters:
dataframe (pd.DataFrame) – A pandas DataFrame containing the annotation data. Must include either a “name” or “annotation_name” column (but not both) or provide a global annotation_name parameter. Similarly, must include an “annotator_kind” column or provide a global annotator_kind. The span_id can be either a column in the DataFrame or will be taken from the DataFrame index. Optional columns include: “label”, “score”, “explanation”, “metadata”, and “identifier”.
annotation_name (Optional[str]) – The name to use for all annotations. If provided, this value will be used for all rows and the DataFrame does not need to include a “name” or “annotation_name” column.
annotator_kind (Optional[Literal["LLM", "CODE", "HUMAN"]]) – The kind of annotator used for all annotations. If provided, this value will be used for all rows and the DataFrame does not need to include an “annotator_kind” column. Must be one of “LLM”, “CODE”, or “HUMAN”.
sync (bool) – If True, the request will be fulfilled synchronously and the response will contain the inserted annotation IDs. If False, the request will be processed asynchronously. Defaults to False.
- Returns:
If sync is True, a list of all inserted span annotations. If sync is False, None.
- Return type:
Optional[list[dict]]
- Raises:
ImportError – If pandas is not installed.
ValueError – If the DataFrame is missing required columns or if no valid annotation data is provided.
Example:
import pandas as pd from phoenix.client import AsyncClient async_client = AsyncClient() # Using name and annotator_kind from DataFrame with span_id column df1 = pd.DataFrame({ "name": ["sentiment", "toxicity"], "span_id": ["span_123", "span_456"], "annotator_kind": ["HUMAN", "LLM"], "label": ["positive", "low"], "score": [0.9, 0.1] }) await async_client.spans.log_span_annotations_dataframe(dataframe=df1) # Using global name and annotator_kind with span_id from index df2 = pd.DataFrame({ "label": ["positive", "low"] }, index=["span_345", "span_678"]) await async_client.spans.log_span_annotations_dataframe( dataframe=df2, annotation_name="sentiment", # applies to all rows annotator_kind="HUMAN" # applies to all rows )
- async log_spans(*, project_identifier, spans, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Logs spans to a project.
If any spans are invalid or duplicates, no spans will be logged and a SpanCreationError will be raised with details about the failed spans.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
spans (Sequence[v1.Span]) – A sequence of Span objects to log.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
- A CreateSpansResponseBody with statistics about
the operation. When successful, total_queued will equal total_received.
- Return type:
v1.CreateSpansResponseBody
- Raises:
SpanCreationError – If any spans failed validation (invalid or duplicates).
httpx.HTTPStatusError – If the API returns an unexpected error response.
httpx.TimeoutException – If the request times out.
- async log_spans_dataframe(*, project_identifier, spans_dataframe, timeout=DEFAULT_TIMEOUT_IN_SECONDS)#
Logs spans to a project from a pandas DataFrame.
If any spans are invalid or duplicates, no spans will be logged and a SpanCreationError will be raised with details about the failed spans.
- Parameters:
project_identifier (str) – The project identifier (name or ID) used in the API path.
spans_dataframe (pd.DataFrame) – A pandas DataFrame with a context.span_id or span_id column.
timeout (Optional[int]) – Optional request timeout in seconds.
- Returns:
- A CreateSpansResponseBody with statistics about
the operation. When successful, total_queued will equal total_received.
- Return type:
v1.CreateSpansResponseBody
- Raises:
SpanCreationError – If any spans failed validation (invalid or duplicates).
httpx.HTTPStatusError – If the API returns an unexpected error response.
httpx.TimeoutException – If the request times out.