Use Xantly with PydanticAI
PydanticAI's OpenAIModel accepts a base_url via OpenAIProvider. Point it at Xantly for typed agents with smart routing, cache, and memory.
PydanticAI is Pydantic's agent framework, strongly-typed agents with pluggable providers. Its OpenAIModel takes a base_url kwarg, so pointing it at Xantly unlocks smart routing, semantic cache, and memory under every agent run.
Prerequisites
- Python 3.10+
pip install pydantic-ai- A Xantly API key, create one
Setup
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
model = OpenAIModel(
"xantly/auto-quality",
provider=OpenAIProvider(
base_url="https://api.xantly.com/v1",
api_key="xantly_sk_...",
),
)
agent = Agent(model)
result = agent.run_sync("What is PydanticAI?")
print(result.output)
Typed output
PydanticAI's headline feature, enforce a Pydantic return type:
from pydantic import BaseModel
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
class CityInfo(BaseModel):
name: str
country: str
population: int
model = OpenAIModel(
"openai/gpt-5.4",
provider=OpenAIProvider(
base_url="https://api.xantly.com/v1",
api_key="xantly_sk_...",
),
)
agent = Agent(model, output_type=CityInfo)
result = agent.run_sync("Tell me about Tokyo.")
assert isinstance(result.output, CityInfo)
print(result.output.name, result.output.population)
Tools
from pydantic_ai import Agent, RunContext
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
model = OpenAIModel(
"anthropic/claude-sonnet-4.6",
provider=OpenAIProvider(
base_url="https://api.xantly.com/v1",
api_key="xantly_sk_...",
),
)
agent = Agent(model)
@agent.tool
def multiply(ctx: RunContext[None], a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
print(agent.run_sync("What is 17 * 23?").output)
Streaming
import asyncio
async def main():
async with agent.run_stream("Stream a haiku.") as result:
async for chunk in result.stream_text(delta=True):
print(chunk, end="", flush=True)
asyncio.run(main())
System prompt + dependencies
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
@dataclass
class Deps:
user_id: str
agent = Agent(
model,
deps_type=Deps,
system_prompt="You are a concise assistant for user {user_id}.",
)
@agent.system_prompt
def add_context(ctx: RunContext[Deps]) -> str:
return f"The user's ID is {ctx.deps.user_id}."
result = agent.run_sync("Hi!", deps=Deps(user_id="u_123"))
print(result.output)
Model choice
| Model ID | When |
|---|---|
xantly/auto-quality | Typed agents, tool use, default. |
anthropic/claude-sonnet-4.6 | Strong tool-calling for complex agents. |
openai/gpt-5.4 | Tight typed output adherence. |
xantly/auto-value | High-volume typed classification workloads. |
Verify
agent = Agent(
OpenAIModel(
"xantly/auto-speed",
provider=OpenAIProvider(
base_url="https://api.xantly.com/v1",
api_key="xantly_sk_...",
),
),
)
print(agent.run_sync("say pong").output)
Check your Xantly dashboard, the run logs with routed-to model + cost.
What you get
- Every PydanticAI feature proxied. Typed output, tools, dependencies, streaming, multi-agent handoffs.
- Tool-call translation across providers, pick
xantly/auto-qualityand BaRP may swap between Claude/GPT/Groq while your typed agent keeps working. - Semantic cache. Repeat queries with the same output schema hit cache.
- Memory. Set
extra_headersviaOpenAIProvider's client config to opt into Xantly's L3 memory. - Cost per run. Each
agent.run_sync(...)call shows up with model + cost.
Gotchas
Use OpenAIProvider with base_url. The older base_url= kwarg directly on OpenAIModel was deprecated in recent versions. Wrap it via OpenAIProvider.
/v1 suffix required.
PydanticAI validates tool outputs against their schema. If a provider returns malformed JSON, PydanticAI will reprompt. Xantly's waterfall will swap to a more reliable provider automatically on repeated schema failures.
Async-only for streaming. stream_text is async. Use asyncio.run(...) or inside an event loop.
Next steps
- Instructor, alternative structured-output library.
- OpenAI SDK (Python), lower-level control.
- LangChain (Python), if you want a bigger agent framework.
- Multi-Agent Orchestration, Xantly-native agent chaining.