Pydantic AI
Integrate Pydantic AI with Agent Kernel. Pydantic AI is built by the
Pydantic team and gives Agent Kernel native, first-class support for many model providers
(OpenAI, Anthropic, Google, Bedrock, Groq, Mistral, Cohere, xAI, Ollama, …) plus FallbackModel
for automatic provider failover.
Installation
pip install agentkernel[pydanticai]
agentkernel[pydanticai] installs the provider-agnostic pydantic-ai-slim core — it ships no
model provider. Install the provider you intend to use:
pip install "pydantic-ai-slim[openai]" # or [anthropic], [google], [bedrock], [groq], ...
Switching providers is then a one-line change to the model string — that provider freedom is the main reason to reach for this adapter.
Basic Usage
from pydantic_ai import Agent
from agentkernel.cli import CLI
from agentkernel.pydanticai import PydanticAIModule
agent = Agent(
model="openai:gpt-4o-mini",
name="assistant",
description="A helpful assistant.",
instructions="You are a helpful assistant.",
)
PydanticAIModule([agent])
if __name__ == "__main__":
CLI.main()
name=is mandatory. Pydantic AI infers an agent's name lazily from the call frame on first run, but Agent Kernel registers agents by name immediately at load time — before any run. A Pydantic AI agent without an explicitname=therefore reaches registration withname is None, andPydanticAIModuleraises aValueError. Always passname=.description=should be set. Unlike the OpenAI adapter (whereinstructionsis effectively mandatory and doubles as the description), Pydantic AI'sdescriptionis an optional, separate field — and it is what Agent Kernel reports as the agent's description and A2A card summary. Whendescription=is unset, Agent Kernel falls back to the agent's staticinstructions=on a best-effort basis (Pydantic AI has no public getter for instructions, so this reads a private attribute and degrades to an empty string if that attribute changes in a future release). Settingdescription=explicitly is the reliable path; an agent with neither yields an empty description, not an error.
Multi-Agent System
Pydantic AI has no built-in handoffs= primitive. Route between agents with
delegation-via-tool: give a triage agent a tool that runs the specialist agent and returns its
output.
from pydantic_ai import Agent
from agentkernel.pydanticai import PydanticAIModule, PydanticAIToolBuilder
MODEL = "openai:gpt-4o-mini"
math_agent = Agent(model=MODEL, name="math", description="Specialist for math problems",
instructions="You solve math problems.")
general_agent = Agent(model=MODEL, name="general", description="Agent for general questions",
instructions="You provide general assistance.")
async def ask_math(question: str) -> str:
"""Delegate a math question to the math specialist."""
return str((await math_agent.run(question)).output)
async def ask_general(question: str) -> str:
"""Delegate a general question to the general agent."""
return str((await general_agent.run(question)).output)
triage_agent = Agent(
model=MODEL,
name="triage",
description="Routes each question to the right specialist",
instructions="Call ask_math for math questions and ask_general for everything else. "
"Return the specialist's answer directly.",
tools=PydanticAIToolBuilder.bind([ask_math, ask_general]),
)
PydanticAIModule([triage_agent, math_agent, general_agent])
Configuration
export OPENAI_API_KEY=sk-... # or the key for whichever provider your model string names
Pydantic AI resolves the provider eagerly, at Agent(...) construction — so the relevant
provider key must be set in the environment when your module is imported, not just when a run
happens. (This differs from the OpenAI Agents SDK, which defers the credential check to run time.)
Tool Binding
Use PydanticAIToolBuilder to bind plain Python functions as tools:
from pydantic_ai import Agent
from agentkernel.pydanticai import PydanticAIModule, PydanticAIToolBuilder
def get_weather(city: str) -> str:
"""Returns the weather for a given city."""
return f"Weather in {city}: sunny, 25°C"
agent = Agent(
model="openai:gpt-4o-mini",
name="weather",
description="Provides weather information.",
instructions="You provide weather information.",
tools=PydanticAIToolBuilder.bind([get_weather]),
)
PydanticAIModule([agent])
Tools reach execution context (session, agent, requests) through ToolContext.get() — the same
portable mechanism as every other adapter. Agent Kernel does not use Pydantic AI's
deps_type/RunContext dependency injection, so a tool function bound here also works unchanged on
any other framework. See Tools for the full guide.
Structured Output
Configure structured output with Pydantic AI's output_type parameter. Agent Kernel detects the
structured result and returns an AgentReplyAny whose content is the result as a dict; no
re-parsing of text needed:
from pydantic_ai import Agent
from pydantic import BaseModel
from agentkernel.pydanticai import PydanticAIModule
class CalendarEvent(BaseModel):
name: str
date: str
agent = Agent(
model="openai:gpt-4o-mini",
name="extractor",
description="Extracts calendar events from text.",
output_type=CalendarEvent,
)
PydanticAIModule([agent])
Pydantic results are converted via model_dump(), and str(reply) returns the JSON-serialized
content, so text-based consumers (chat integrations, logging) work unchanged. See
Reply Types for how structured replies are surfaced,
and Execution Hooks for how hooks receive them.
Structured output applies to non-streaming execution only. In Agent Kernel's streaming mode a
Pydantic AI run stops at the first output_type match and ends the run, so combining
output_type with streaming truncates differently than the non-streaming path. Plain text
streaming (the common case) is unaffected — it emits token-by-token deltas as usual.
Features
- ✅ Function calling
- ✅ Multi-agent delegation (delegation-via-tool; no
handoffs=primitive) - ✅ Streaming responses (native token streaming)
- ✅ Structured output (
output_type→AgentReplyAny) - ✅ Session management (message history persisted per session)
- ✅ Framework-agnostic tool binding
- ✅ Native multi-provider support (
FallbackModelfor failover)
Example
See examples/cli/pydanticai for a complete triage/math/weather delegation-via-tool example.
