Use Xantly with DSPy

Stanford DSPy's programming-not-prompting framework routes via LiteLLM. Point dspy.LM at Xantly and optimizer runs hit semantic cache hard, 40-70% cost savings on BootstrapFewShot compilation.

DSPy is Stanford's "programming-not-prompting" framework, you declare signatures and modules, DSPy optimizes the prompts. Its dspy.LM class accepts any OpenAI-compatible endpoint. Point it at Xantly and DSPy's optimizer runs + program execution both route through smart routing + cache + memory.

Prerequisites

Setup

import dspy

lm = dspy.LM(
    "openai/xantly/auto-quality",  # protocol/model
    api_base="https://api.xantly.com/v1",
    api_key="xantly_sk_...",
)
dspy.configure(lm=lm)

That's the entire setup, now every DSPy module uses Xantly.

Signature + module

import dspy

class QA(dspy.Signature):
    """Answer the question concisely."""
    question = dspy.InputField()
    answer = dspy.OutputField()

qa = dspy.Predict(QA)
result = qa(question="What is DSPy?")
print(result.answer)

Chain-of-thought

cot = dspy.ChainOfThought(QA)
result = cot(question="What's 17 * 23?")
print(result.reasoning)
print(result.answer)

ReAct

def search(query: str) -> str:
    """Search the web."""
    return f"results for {query}"

agent = dspy.ReAct(QA, tools=[search])
result = agent(question="What is the capital of France?")
print(result.answer)

Optimizer (MIPROv2, BootstrapFewShot)

DSPy's differentiator, it optimizes your prompts against a train set:

from dspy.teleprompt import BootstrapFewShot

trainset = [
    dspy.Example(question="What is 2+2?", answer="4").with_inputs("question"),
    dspy.Example(question="What is 3*3?", answer="9").with_inputs("question"),
]

def accuracy(example, pred, trace=None):
    return pred.answer.strip() == example.answer

compiler = BootstrapFewShot(metric=accuracy, max_bootstrapped_demos=4)
optimized = compiler.compile(qa, trainset=trainset)

The compiler issues many LM calls during optimization. Xantly's semantic cache absorbs the repeated ones → 40-70% cost savings on big training runs.

Per-module models

Use different tiers for different modules:

fast = dspy.LM(
    "openai/xantly/auto-speed",
    api_base="https://api.xantly.com/v1",
    api_key="xantly_sk_...",
)
quality = dspy.LM(
    "openai/xantly/auto-quality",
    api_base="https://api.xantly.com/v1",
    api_key="xantly_sk_...",
)

classifier = dspy.Predict(MyClassifierSig, lm=fast)
reasoner = dspy.ChainOfThought(MyReasoningSig, lm=quality)

Streaming

for chunk in dspy.streamify(qa)(question="Stream an explanation of DSPy."):
    print(chunk, end="", flush=True)

Model choice

Model IDWhen
xantly/auto-qualityOptimizer runs + production reasoning.
xantly/auto-valueHigh-volume predict modules.
xantly/auto-speedClassifiers, short completions.
anthropic/claude-sonnet-4.6ReAct + tool-heavy modules.
openai/gpt-5.4Structured-signature adherence.

Verify

import dspy

lm = dspy.LM(
    "openai/xantly/auto-speed",
    api_base="https://api.xantly.com/v1",
    api_key="xantly_sk_...",
)
dspy.configure(lm=lm)
print(dspy.Predict("input -> output")(input="say pong").output)

What you get

Gotchas

The openai/ prefix is required. DSPy uses LiteLLM under the hood. Full model ID: openai/xantly/auto-quality (openai is the protocol, xantly/auto-quality is the model).

api_base not base_url. DSPy matches the LiteLLM kwarg name.

/v1 required in api_base.

Optimizer cost explosion. If you set max_bootstrapped_demos=16 with a quality model, expect thousands of calls. Use a value tier LM for compilation and a quality tier for the final compiled program.

dspy.settings is thread-local. If you multithread, each thread needs dspy.configure(lm=...).

Next steps