soev for developers
soev-agentsReference

soev_agents.observability

Optional observers. Import an implementation only when the server enables it.

This package needs the otel extra: install soev-agents[otel]. Without the extra, its import raises an ImportError that names the extra.

OpenTelemetry

The OpenTelemetry observer exports spans of turns, model calls and , with no content.

OtelObserver

classOtelObserver(tracer=None, *, tracer_provider=None, model_for_endpoint=None)

An Observer that exports turns, model calls and as OpenTelemetry spans, with no content.

Each is a span soev.agents.turn. Each model call is a child span soev.agents.model, and each a child span soev.agents.tool. The observer also records a model span for each . The spans hold only metadata: the id, the , the id, the model names, the token usage, the finish reasons, the name and the . They hold no prompt, text, reasoning, argument, result or error message.

A span has the attributes soev.thread.id, soev.turn.id, soev.agent and gen_ai.request.model. A model span has soev.endpoint.id, gen_ai.request.model, gen_ai.response.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, soev.usage.total_tokens and gen_ai.response.finish_reasons. A span has soev.tool.name. An attribute is absent when the observer does not know its value. A span and a span end with soev.status: ok, error, cancelled or interrupted. A model span gets soev.status only when the observer ends it before the output of its call.

The owns the tracer provider, its exporter and its shutdown. The observer installs no global provider. It keeps the open spans in memory: after a restart of the process, a resumed turn gets a new span with the same id.

Example

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter

from soev_agents.adapters import InMemoryTraceStore
from soev_agents.entrypoints.http import create_app
from soev_agents.observability import OtelObserver

exporter = ConsoleSpanExporter()
store = InMemoryTraceStore()
agents = {"assistant": agent}  # agent is an Agent of your own
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
app = create_app(store, agents, version="1.0", observer=OtelObserver(tracer_provider=provider))

Make an observer that writes spans with a tracer of the .

paramtracerTracer | None
= None

The tracer to write the spans with. Give this or tracer_provider, not both.

paramtracer_providerTracerProvider | None
= None

The provider to get the tracer from. With neither argument, the observer uses the 's global OpenTelemetry configuration.

parammodel_for_endpointCallable[[str], str] | None
= None

A function that maps the name of an endpoint to the name of the provider's model, for the gen_ai.request.model and gen_ai.response.model attributes. None uses the endpoint's name.

Raises:

  • ValueError: Both tracer and tracer_provider are given.
methodrequest(headers) -> AbstractContextManager[None]

Attach the W3C traceparent context of the caller for the time of one HTTP request.

The observer reads traceparent and tracestate from the headers, in upper or lower case. A that the HTTP request starts gets the span of the caller as its parent. The previous context comes back when the HTTP request ends.

paramheadersMapping[str, str]

The headers of the HTTP request.

Returns

AbstractContextManager[None]

A context manager that holds the traceparent context of the caller while it is entered.

methodrun(thread_id, agent, opening) -> AbstractContextManager[None]

Attach the span of the 's for the time of one .

A that a that this observer has no span for starts a new span from opening. When the stops, the observer ends each model span and span that is still open, with the soev.status interrupted. The span stays open, so a that waits for a response continues under it.

paramthread_idstr

The that runs.

paramagentstr | None

The 's , or None.

paramopeningInput | None

The input that opened the current when that turn is not over, else None.

Returns

AbstractContextManager[None]

A context manager that holds the span as the current span while it is entered.

methodevent(thread_id, agent, event) -> None

Start, continue or end spans from one .

An input of the root stream starts a new span, and ends an unfinished earlier one as interrupted. An input that responds to a request continues the . A model output or a ends its model span, and a output ends its span. A failure marks the as an error. A Finished or Cancelled of the root stream ends the span.

paramthread_idstr

The of the .

paramagentstr | None

The 's , or None.

parameventEvent
methodcall(thread_id, stream, node, kind, name, call_id) -> None

Start a model span or a span under the 's span.

A call of a without an open turn span gives no span. The span ends when the output of the call is recorded, or when the stops.

paramthread_idstr

The that makes the call.

paramstreamstr

The that makes the call.

paramnodestr | None

The that makes the call, or None.

paramkindCallKind

Whether it is a model call or a .

paramnamestr

The model of a model call, or the of a .

paramcall_idstr | None

The id of a , or None for a model call.

methodclose() -> None

End every open span with the soev.status interrupted.

The observer does not flush or shut down the tracer provider: the does.

On this page