DSPy

Trace a DSPy module with Neatlogs (Python).

Wrap a DSPy module with neatlogs.wrap() and its module runs (CHAIN), LM calls (LLM), and retrieval (RETRIEVER) are captured. Wrapping a dspy.Module self-roots — the module run becomes the trace root — so a single run renders in the dashboard with no extra code.

Prerequisites

pip install -U "neatlogs[dspy]" dspy

Usage

import os
import neatlogs
import dspy

neatlogs.init(api_key=os.environ["NEATLOGS_API_KEY"], workflow_name="dspy-demo")

dspy.configure(lm=dspy.LM("openai/gpt-4o"))

class QA(dspy.Module):
    def __init__(self):
        super().__init__()
        self.answer = dspy.Predict("question -> answer")

    def forward(self, question: str):
        return self.answer(question=question)

program = neatlogs.wrap(QA())

result = program(question="In one sentence, what is DSPy?")
print(result.answer)

neatlogs.flush()
neatlogs.shutdown()

wrap() works on any DSPy version. If you call a bare predictor (e.g. dspy.Predict(...)) outside a dspy.Module, the LM span self-roots on its own; wrap a dspy.Module (as above) to group a multi-step program under one root.

instrumentations=["dspy"] requires DSPy ≥ 2.6.0. Neatlogs also supports DSPy through neatlogs.init(instrumentations=["dspy"]), which uses the OpenInference DSPy instrumentor — but that instrumentor only attaches to DSPy 2.6.0 or newer. On older DSPy it silently emits no spans. If you can't upgrade, use the neatlogs.wrap(module) path above, which has no version requirement.

A runnable end-to-end example lives at examples/sdk_examples/dspy_basic.py in the SDK repo.

On this page