Integrations: from stand-in to real backends
An integration is a real backend that replaces a keyless stand-in you built on, such as a hosted model for the scripted one, a persisted store for in-memory history, or a remote server for a local MCP script.
Last updated: 28 Sep, 2026 · Pydantic AI 2.51
Every lesson so far ran with no key, on a stand-in. That is right for learning and testing, but a shipped desk needs the real thing. This lesson maps each stand-in to its production backend and shows the one line that swaps it in.
The stand-in and the real model share a base
The swap is a drop-in because the scripted FunctionModel and a hosted model are both subclasses of the same Model base, so the agent code around them does not change:
from pydantic_ai.models import Model
from pydantic_ai.models.openai import OpenAIChatModel
# both are Model subclasses, so either can go in Agent(model=...)Proving the drop-in shares the base
Both classes answer to issubclass(..., Model), which is why swapping one for the other needs no other change:
from pydantic_ai.models import Model
from pydantic_ai.models.function import FunctionModel
from pydantic_ai.models.openai import OpenAIChatModel
print(issubclass(FunctionModel, Model)) # the stand-in you used
print(issubclass(OpenAIChatModel, Model)) # a real hosted modelFrom stand-in to a real backend
Each piece you used maps to a production backend from the framework's own integrations, added the same way you added the stand-in:
| What you used | A real one | Package or string |
|---|---|---|
FunctionModel / TestModel stand-in | A hosted model by provider string | "openai:gpt-4.1", "groq:openai/gpt-oss-120b" |
| In-memory message history | A persisted conversation store you load and save | Your own database, keyed by conversation id |
| An MCP script started per run | A remote MCP server over HTTP | MCPToolset("https://host/mcp") |
| No tracing | Pydantic Logfire over OpenTelemetry | logfire |
run_sync in one process | Durable execution that survives a crash | Temporal, DBOS, Prefect or Restate (optional) |
The one-line real-model swap
Naming a provider string in place of the stand-in is the whole change. It needs a key, so it is shown, not run:
from pydantic_ai import Agent
# was: Agent(FunctionModel(desk_reply), ...)
agent = Agent("openai:gpt-4.1", ...) # needs OPENAI_API_KEY
# or another provider, same shape:
agent = Agent("groq:openai/gpt-oss-120b", ...) # needs GROQ_API_KEYPersisting the conversation
The in-memory history from Message history: continuing a conversation lives only for the program's life. In production you save result.all_messages_json() under a conversation id and load it back on the next ticket, so a restart does not lose the thread. The store is your own database; the framework gives the bytes to save.
Durable execution, when a run must not be lost
A long run that calls tools and pauses for approval can be wrapped so it survives a crash and resumes where it stopped. Pydantic AI supports Temporal, DBOS, Prefect and Restate for this. It is optional: reach for it when a lost run costs money, not for a chat reply.
Stand-in vs production
| Stand-in (this course) | Production | |
|---|---|---|
| Model | Scripted, no key | Hosted, by provider string, with a key |
| History | A list in memory | A store keyed by conversation id |
| Tools from another program | A script started per run | A remote MCP server over HTTP |
| Visibility | Print the message list | Logfire traces over OpenTelemetry |
Where you use real backends
- Turning the tested desk into one that answers real customers.
- Moving a local MCP script to a server the whole team shares.
- Adding durable execution before a refund flow that must never be dropped.
"openai:gpt-4.1" is only a name until a key is present; the model that name points to changes over time. Read the key from the environment, pick the model per your own cost and quality test, and do not hardcode a model as the one right answer.Related
- Previous: Observability: tracing runs with Logfire
- Next: Support desk project: the finished agent
- See also: Real models: providers, keys and model names
- Reference: Models overview, MCP overview, Durable execution
- Swap
desk_modelfor"openai:gpt-4.1"inapp.py, setOPENAI_API_KEY, and run one ticket. - Save a run with
all_messages_json()to a file and load it back on the next run. - Point an
MCPToolsetat a URL instead of a script path.
You understood something today that you didn't yesterday.