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

# DSPy

> Trace DSPy with Braintrust

If you are a coding agent, prefer the Braintrust [`bt` CLI](/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, such as ad-hoc lookups and exploration from your IDE.

[DSPy](https://dspy.ai) is a framework for programming language model pipelines. Braintrust instruments DSPy runs so you can inspect module spans, adapter formatting and parsing steps, underlying LLM calls, and tool usage in a single trace.

## Setup

Install Braintrust and DSPy:

<CodeGroup>
  ```bash Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # uv
  uv add braintrust dspy
  # pip
  pip install braintrust dspy
  ```
</CodeGroup>

Set your API keys before you run your app:

```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
BRAINTRUST_API_KEY=<your-braintrust-api-key>
OPENAI_API_KEY=<your-openai-api-key>
```

## Instrument DSPy

<Tabs>
  <Tab title="Python">
    Braintrust's DSPy integration requires `dspy>=2.6.0`.

    #### Automatic Instrumentation

    `braintrust.auto_instrument()` patches `dspy.configure()` so Braintrust's DSPy callback is added automatically when you configure DSPy.

    ```python title="trace-dspy-auto.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    import braintrust

    braintrust.auto_instrument()
    braintrust.init_logger(
        api_key=os.environ["BRAINTRUST_API_KEY"],
        project="dspy-example",  # Replace with your project name
    )

    import dspy

    lm = dspy.LM("openai/gpt-5-mini")
    dspy.configure(lm=lm)

    cot = dspy.ChainOfThought("question -> answer")
    result = cot(question="What is the capital of France?")
    print(result.answer)
    ```

    If you only want to patch DSPy instead of enabling all supported Python integrations, use `patch_dspy()`.

    ```python title="trace-dspy-patch-only.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    from braintrust import init_logger
    from braintrust.integrations.dspy import patch_dspy

    init_logger(
        api_key=os.environ["BRAINTRUST_API_KEY"],
        project="dspy-example",  # Replace with your project name
    )
    patch_dspy()

    import dspy

    lm = dspy.LM("openai/gpt-5-mini")
    dspy.configure(lm=lm)

    predict = dspy.Predict("question -> answer")
    result = predict(question="What is 2 + 2?")
    print(result.answer)
    ```

    #### Manual callback setup

    Use `BraintrustDSpyCallback()` when you want to attach the callback explicitly. If you also want detailed LiteLLM token and cost spans, patch LiteLLM before importing DSPy.

    ```python title="trace-dspy-manual.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    from braintrust import init_logger
    from braintrust.integrations.dspy import BraintrustDSpyCallback
    from braintrust.integrations.litellm import patch_litellm

    patch_litellm()

    import dspy

    init_logger(
        api_key=os.environ["BRAINTRUST_API_KEY"],
        project="dspy-example",  # Replace with your project name
    )

    # Disable DSPy's disk cache if you want every LiteLLM call to be traced.
    dspy.configure_cache(enable_disk_cache=False, enable_memory_cache=True)

    lm = dspy.LM("openai/gpt-5-mini")
    dspy.configure(lm=lm, callbacks=[BraintrustDSpyCallback()])

    cot = dspy.ChainOfThought("question -> answer")
    result = cot(question="What is the capital of France?")
    print(result.answer)
    ```

    Python resources:

    * [DSPy documentation](https://dspy.ai)
    * [Trace LLM calls](/instrument/trace-llm-calls)
    * [LiteLLM integration](/integrations/sdk-integrations/litellm)
  </Tab>
</Tabs>

## Examples

In Braintrust, a DSPy execution typically appears as a parent DSPy module span with child spans for adapter work and model calls.

Example trace shape:

```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
trace-dspy-auto
└── dspy.module.ChainOfThought
    ├── dspy.adapter.format
    ├── dspy.lm
    └── dspy.adapter.parse
```

Braintrust captures:

* DSPy module spans such as `Predict`, `ChainOfThought`, and other module executions
* Adapter formatting and parsing spans
* LLM call inputs, outputs, and latency on `dspy.lm` spans
* Tool execution when your DSPy program invokes tools
* Extra LiteLLM token and cost spans when you patch LiteLLM

## Resources

* [Integrations](/integrations)
* [Trace LLM calls](/instrument/trace-llm-calls)
* [Advanced tracing](/instrument/advanced-tracing)
