How to Add ATXP to Pydantic AI
Pydantic AI produces some of the cleanest agent code in Python — type-safe, well-structured, easy to reason about. What it doesn’t address: the payment layer. Your agents call LLMs with your keys and have no spending ceiling.
ATXP adds that layer with minimal changes to your existing code.
What Changes (Minimally)
You change one thing: the LLM provider configuration. Instead of pointing Pydantic AI at OpenAI or Anthropic directly, you point it at ATXP’s proxy endpoint with an agent-specific key. The agent key is tied to an ATXP account with a real credit balance that ATXP enforces.
Everything else — structured outputs, tool calls, retry logic, validation — stays the same.
Prerequisites
- Python 3.10+
pydantic-aiinstalled- An ATXP account (atxp.ai)
Step 1: Create an Agent Account
import httpx
import os
ATXP_API_KEY = os.environ["ATXP_API_KEY"]
with httpx.Client() as client:
response = client.post(
"https://api.atxp.ai/v1/agents",
headers={"Authorization": f"Bearer {ATXP_API_KEY}"},
json={
"name": "pydantic-research-agent",
"budget": 4.00,
"currency": "usd",
}
)
agent_data = response.json()
agent_id = agent_data["id"]
agent_key = agent_data["api_key"]
Step 2: Configure Pydantic AI to Use ATXP
Pydantic AI uses OpenAI-compatible model providers. Configure the model to use ATXP’s proxy:
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from openai import AsyncOpenAI
# OpenAI client pointing at ATXP's proxy with the agent key
atxp_client = AsyncOpenAI(
api_key=agent_key,
base_url="https://api.atxp.ai/v1/proxy/openai",
)
model = OpenAIModel("gpt-4o", openai_client=atxp_client)
For Anthropic models:
from pydantic_ai.models.anthropic import AnthropicModel
import anthropic
atxp_anthropic = anthropic.AsyncAnthropic(
api_key=agent_key,
base_url="https://api.atxp.ai/v1/proxy/anthropic",
)
model = AnthropicModel("claude-sonnet-4-6", anthropic_client=atxp_anthropic)
Step 3: Define Your Agent Normally
from pydantic import BaseModel
class ResearchResult(BaseModel):
summary: str
key_findings: list[str]
confidence: float
research_agent = Agent(
model,
result_type=ResearchResult,
system_prompt=(
"You are a research agent. Analyze the provided topic and return "
"structured findings with a confidence score."
),
)
Step 4: Run It
import asyncio
async def main():
result = await research_agent.run(
"What are the current agent payment protocols and their tradeoffs?"
)
print(f"Summary: {result.data.summary}")
print(f"Findings: {result.data.key_findings}")
print(f"Confidence: {result.data.confidence:.0%}")
asyncio.run(main())
Step 5: Check Spend
async def check_agent_spend(agent_id: str) -> dict:
async with httpx.AsyncClient() as client:
txns = await client.get(
f"https://api.atxp.ai/v1/agents/{agent_id}/transactions",
headers={"Authorization": f"Bearer {ATXP_API_KEY}"}
)
balance = await client.get(
f"https://api.atxp.ai/v1/agents/{agent_id}/balance",
headers={"Authorization": f"Bearer {ATXP_API_KEY}"}
)
return {
"transactions": txns.json()["data"],
"balance": balance.json()["available_usd"]
}
Handling Budget Depletion
When the agent’s ATXP account hits zero, the proxy returns a 402. Pydantic AI surfaces this as a ModelHTTPError. Handle it:
from pydantic_ai.exceptions import ModelHTTPError
async def run_with_budget_handling(query: str):
try:
result = await research_agent.run(query)
return result.data
except ModelHTTPError as e:
if e.status_code == 402:
# Agent is out of credits
raise BudgetExhaustedError(
f"Agent {agent_id} exhausted its budget. Refill at atxp.ai."
)
raise
Multi-Tenant Pattern
For applications where multiple users run the same agent type, create one ATXP account per user session:
async def create_user_agent(user_id: str, budget_usd: float):
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.atxp.ai/v1/agents",
headers={"Authorization": f"Bearer {ATXP_API_KEY}"},
json={
"name": f"user-{user_id}-agent",
"budget": budget_usd,
"metadata": {"user_id": user_id},
}
)
agent_data = response.json()
# Configure Pydantic AI model for this user's agent
atxp_client = AsyncOpenAI(
api_key=agent_data["api_key"],
base_url="https://api.atxp.ai/v1/proxy/openai",
)
return Agent(
OpenAIModel("gpt-4o", openai_client=atxp_client),
result_type=ResearchResult,
system_prompt="...",
)
Each user’s agent has an isolated key and a separate spending limit. You can attribute costs per user and prevent any single user from running up an outsized bill.
For the broader infrastructure pattern — how identity, payments, and permissions fit together for agent systems — see how to give an AI agent payments and identity.