Instrumentation()

Overview

All Respan instrumentation plugins implement a simple protocol with name, activate(), and deactivate(). This lets you build plugins for any vendor SDK and have them work with Respan().

Protocol

from respan import Instrumentation
class Instrumentation(Protocol):
name: str
def activate(self) -> None:
"""Start intercepting spans and injecting them into the OTEL pipeline."""
...
def deactivate(self) -> None:
"""Stop intercepting spans and clean up resources."""
...
Attribute/MethodDescription
nameUnique identifier for the plugin (e.g. "openai-agents", "openai").
activate()Called by Respan.__init__(). Registers hooks/processors with the vendor SDK.
deactivate()Called by Respan.shutdown(). Cleans up hooks/processors.

Building a custom plugin

A plugin typically:

  1. Registers a hook or processor with the vendor SDK in activate().
  2. On each SDK event, converts it to a ReadableSpan using build_readable_span().
  3. Injects the span into the OTEL pipeline using inject_span().

Minimal example

from respan import Respan
from respan_tracing.utils.span_factory import build_readable_span, inject_span
class MySDKInstrumentor:
name = "my-sdk"
def activate(self) -> None:
# Register a callback with the vendor SDK
import my_sdk
my_sdk.on_completion(self._on_completion)
def deactivate(self) -> None:
import my_sdk
my_sdk.remove_callback(self._on_completion)
def _on_completion(self, event):
span = build_readable_span(
name=f"my-sdk.completion",
trace_id=event.trace_id,
attributes={
"llm.request.type": "chat",
"gen_ai.request.model": event.model,
"gen_ai.usage.prompt_tokens": event.input_tokens,
"gen_ai.usage.completion_tokens": event.output_tokens,
"traceloop.span.kind": "task",
"traceloop.entity.name": "completion",
},
)
inject_span(span)
# Use it
respan = Respan(
api_key="your-api-key",
instrumentations=[MySDKInstrumentor()],
)

Key functions

FunctionModuleDescription
build_readable_span()respan_tracing.utils.span_factoryCreates a ReadableSpan with proper trace/span IDs, timestamps, and attributes. Automatically reads propagated attributes from the current context.
inject_span()respan_tracing.utils.span_factoryInjects a ReadableSpan into the global OTEL processor chain for export.
read_propagated_attributes()respan_tracing.utils.span_factoryReads the current propagate_attributes() context. Useful if you need to inspect attributes before building the span.

Required attributes

For spans to be processed and displayed correctly by the Respan backend:

AttributeRequiredDescription
traceloop.span.kindStructural spansOne of "workflow", "agent", "task", "tool". LLM spans may omit this and rely on llm.request.type for backend classification.
traceloop.entity.nameYesHuman-readable span name.
llm.request.typeFor LLM spansSet to "chat" to trigger prompt/completion parsing.
gen_ai.request.modelFor LLM spansModel name.

Existing plugins

PluginPackageSDK
OpenAI Agents SDKrespan-instrumentation-openai-agentsopenai-agents
Claude Agent SDKrespan-instrumentation-claude-agent-sdkclaude-agent-sdk
Pydantic AIrespan-instrumentation-pydantic-aipydantic-ai
OpenAIrespan-instrumentation-openaiopenai
Vertex AIrespan-instrumentation-vertexaigoogle-cloud-aiplatform