Tutorials

Pydantic AI with Claude, GPT and open models on one key

Use Pydantic AI with Claude, GPT and open models like DeepSeek on one key: point the OpenAI and Anthropic providers at SayGM and switch models per run.

5 min read · Python · Verified on Sep 26, 2026

The project

Pydantic AI lets you write an agent once and run it on many models. The usual catch is keys: one for OpenAI, one for Anthropic, and one for each open-model host.

In this tutorial we build one weather agent and run it three times: on an open model, on GPT and on Claude. The instructions and the tool stay the same, and one SayGM key covers all three.

At the end you have a script that prints three answers, one from each model, and a pattern for choosing the model per request in your own app.

What you'll learn

  • How to point Pydantic AI's OpenAI and Anthropic providers at SayGM.
  • Which model class fits each API: Chat Completions, Responses and Messages.
  • How to switch models for a single run with run_sync(model=...).

How it works

The agent is defined once. Each run passes a different model, and the request goes through SayGM to that model.

One agent, three modelsOne Pydantic AI agent, with its instructions and the get_weather tool, runs three times through the SayGM gateway on one key: on the open model deepseek-v4-flash-0731 over Chat Completions, on gpt-5.4-nano over the Responses API, and on Claude, claude-haiku-4-5, over the Messages API. The instructions and the tool stay the same; each run passes its own question and model to run_sync.One agentrun_sync(model=...)get_weatherthe agent'stoolSayGM gatewayone keyOpen modeldeepseek-v4-flash-0731ChatCompletionsGPTgpt-5.4-nanoResponsesClaudeclaude-haiku-4-5Messages
Your codeSayGM gatewayModel

What you need

  • Python 3.13.
  • A SayGM key in the SAYGM_API_KEY environment variable.

Setup

Install Pydantic AI with its OpenAI and Anthropic extras.

commands.sh
pip install "pydantic-ai-slim[anthropic,openai]==2.50.0"

Create an OpenAIProvider with the base URL https://api.saygm.com/v1.

main.py
import os

from pydantic_ai import Agent
from pydantic_ai.models.anthropic import AnthropicModel
from pydantic_ai.models.openai import OpenAIChatModel, OpenAIResponsesModel
from pydantic_ai.providers.anthropic import AnthropicProvider
from pydantic_ai.providers.openai import OpenAIProvider

saygm = OpenAIProvider(base_url="https://api.saygm.com/v1", api_key=os.environ["SAYGM_API_KEY"])

Steps

Build the agent on an open model

OpenAIChatModel sends the request to Chat Completions. The agent starts on deepseek-v4-flash-0731, a low-cost place to develop and test it.

main.py
agent = Agent(
    OpenAIChatModel("deepseek-v4-flash-0731", provider=saygm),
    instructions="Answer weather questions. Use the get_weather tool for current conditions.",
)


@agent.tool_plain
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"{city}: 18 C and light rain"


result = agent.run_sync("What is the weather in Paris? Should I take an umbrella?")
print(result.output)

Run it on GPT

OpenAIResponsesModel uses the Responses API, which GPT models serve. This run uses gpt-5.4-nano. The provider and the key stay the same.

main.py
gpt = OpenAIResponsesModel("gpt-5.4-nano", provider=saygm)

gpt_result = agent.run_sync("Will I need sunglasses in Paris today?", model=gpt)
print(gpt_result.output)

Run it on Claude

AnthropicProvider takes the base URL https://api.saygm.com and the same key. This run uses claude-haiku-4-5. Claude speaks the Messages API, which is why it has a provider of its own.

main.py
claude = AnthropicModel(
    "claude-haiku-4-5",
    provider=AnthropicProvider(
        base_url="https://api.saygm.com",
        api_key=os.environ["SAYGM_API_KEY"],
    ),
)

claude_result = agent.run_sync("Is it a good day for a walk in Paris?", model=claude)
print(claude_result.output)

Run it

Put the code in main.py in the order above, export your key, and run it. You see one answer from each model.

commands.sh
python main.py

What you'll see

Three questions, three answers: the open model first, then GPT, then Claude. Each model called get_weather before it answered, so all three work from the same 18°C and light rain.

Terminal
$ python main.py
The current weather in **Paris** is **18°C (64°F)** with **light rain**.
So yes, I'd definitely recommend bringing an umbrella with you today! ☂️
You’ll likely want sunglasses in Paris today—there’s light rain, and at **18°C** the sky may still have some brightness between showers. If you don’t have sunglasses, **rain protection** (umbrella/waterproof outerwear) is the bigger priority.
Based on the current weather in Paris, it's **moderately good** for a walk, but with some caveats:
**Recommendation:** Yes, it's still a good day for a walk! Paris in light rain can actually be quite charming and atmospheric. Just make sure to dress appropriately with a raincoat or waterproof jacket and bring an umbrella.
From a run of the example on Sep 27, 2026. Long answers are trimmed, and replies change a little from run to run.

Where this stops

Here you choose the model in code. In a real app, choose it per request: a low-cost model for simple questions and a stronger one for long or sensitive ones. Compare the answers on your own tasks before you move a whole feature.

Each model writes in its own style. If your app reads the answer, use output_type for a structured reply that every model has to match.

Take it further

  • Add output_type with a Pydantic model so all three return the same fields.
  • Read the model for each request from a setting, so you can move traffic between models without a deploy.
  • Run the same ten questions on all three and compare answers, speed and cost.
  • See the customer support tutorial, which uses this pattern to hand hard questions to Claude.

What it costs

You pay per token, from a prepaid balance. SayGM rates are live and typically below list. USD per 1M tokens, uncached input / output. SayGM’s side is the best rate a provider offered, as of 44 minutes ago.

ModelSayGMList priceYou save
DeepSeek-V4-Flash-0731DeepSeek$0.13 / $0.40$0.44 / $1.3269%
GPT-5.4 nanoOpenAI$0.16 / $1.02$0.20 / $1.2518%
Claude Haiku 4.5Anthropic$0.89 / $4.47$1.00 / $5.0010%

The last verified run of this example used 2,515 tokens, which costs less than one centat today’s SayGM rates.

Swap the model

Change the model id in the code to any model that serves the same API, such as a larger model for harder prompts or a confidential model for private data. This tutorial uses:

Every model, its API and its live rate is on the models page.

Next steps

Questions

Which provider do I use for each model?
OpenAIProvider for open models and GPT, with base_url https://api.saygm.com/v1. AnthropicProvider for Claude, with base_url https://api.saygm.com. Both take the same SayGM key.
When do I use OpenAIResponsesModel instead of OpenAIChatModel?
Use OpenAIResponsesModel for GPT models, which serve the Responses API. Use OpenAIChatModel for open models, which serve Chat Completions.
Can one agent switch models?
Yes. Pass model= to run_sync to run the same agent, with the same tools and instructions, on another model.
How am I billed?
Per token, from a prepaid SayGM balance. The rates on this page are live and typically below list.

Sources

Run it with your own key.

One SayGM key works for every model in this tutorial. Top up once and pay per token.