> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zespan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# DSPy

> Trace DSPy modules and optimizers via OpenTelemetry auto-instrumentation, no Zespan SDK required.

<Note>
  Available via: **OpenTelemetry auto-instrumentation** (Python). This is not a Zespan SDK wrapper — see [Send traces from any OTel-instrumented app](/sdk/otel-integration#send-traces-from-any-otel-instrumented-app-no-zespan-sdk) for how the underlying endpoint works.
</Note>

[OpenInference](https://github.com/Arize-ai/openinference)'s `openinference-instrumentation-dspy` package instruments DSPy's module and predictor calls (`Predict`, `ChainOfThought`, `ReAct`, and DSPy's own LM calls underneath) so every step of a DSPy pipeline — including compiled/optimized programs — shows up as a span, no changes to your DSPy code.

## Installation

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
pip install dspy openinference-instrumentation-dspy \
  opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
```

## Setup

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import dspy
from opentelemetry import trace as trace_api
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from openinference.instrumentation.dspy import DSPyInstrumentor

provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter(
    endpoint="https://api.zespan.com/v1/traces",
    headers={"x-api-key": "zsp_..."},
)))
trace_api.set_tracer_provider(provider)

DSPyInstrumentor().instrument()

# Every module call below is now traced automatically
lm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=lm)
predictor = dspy.ChainOfThought("question -> answer")
result = predictor(question="What is 2+2?")
```

<Tip>
  Use `BatchSpanProcessor` instead of `SimpleSpanProcessor` in production — the example above uses `SimpleSpanProcessor` (synchronous, one export per span) since it's simpler for a first run, but it adds latency to every call at real traffic volume.
</Tip>

## What gets captured

Each DSPy module invocation and its underlying LM call become spans in the same trace, so a compiled multi-step pipeline (retrieval, reasoning, self-refinement) shows up as one flame graph rather than disconnected calls. Fields map through the standard [OpenTelemetry GenAI semantic conventions](/sdk/otel-integration#attributes-zespan-reads) Zespan reads — model, tokens, prompts, and completions per step.
