By Sagar Shankaran, Founder of CallSphere
Learn how to use Pydantic v2 for robust data validation, settings management, and serialization in AI agent applications with BaseModel, Field validators, and model_config.
Key takeaways
Nearly every major AI framework in Python depends on Pydantic. LangChain, LlamaIndex, the OpenAI Agents SDK, Instructor, and FastAPI all use it for data validation and serialization. Understanding Pydantic v2 is not optional for AI engineers — it is foundational.
Pydantic v2 was rewritten with a Rust-powered core that makes validation 5-50x faster than v1. It also introduced cleaner APIs for validators, configuration, and serialization that directly benefit AI applications where you constantly parse model outputs, validate tool arguments, and manage configuration.
Every data structure in your agent pipeline should start as a Pydantic model.
flowchart LR
INPUT(["User intent"])
PARSE["Parse plus<br/>classify"]
PLAN["Plan and tool<br/>selection"]
AGENT["Agent loop<br/>LLM plus tools"]
GUARD{"Guardrails<br/>and policy"}
EXEC["Execute and<br/>verify result"]
OBS[("Trace and metrics")]
OUT(["Outcome plus<br/>next action"])
INPUT --> PARSE --> PLAN --> AGENT --> GUARD
GUARD -->|Pass| EXEC --> OUT
GUARD -->|Fail| AGENT
AGENT --> OBS
style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
style OBS fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style OUT fill:#059669,stroke:#047857,color:#fff
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
from enum import Enum
class AgentRole(str, Enum):
RESEARCHER = "researcher"
CODER = "coder"
REVIEWER = "reviewer"
class AgentConfig(BaseModel):
model_config = {"strict": False, "extra": "forbid"}
name: str = Field(min_length=1, max_length=100)
role: AgentRole
model: str = Field(default="gpt-4o", pattern=r"^[a-z0-9-]+$")
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
max_tokens: Optional[int] = Field(default=None, gt=0, le=128000)
system_prompt: str = Field(default="You are a helpful assistant.")
created_at: datetime = Field(default_factory=datetime.now)
The model_config with extra="forbid" prevents silent data corruption — if someone passes an unknown field, Pydantic raises an error instead of ignoring it.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
Pydantic v2 uses field_validator and model_validator decorators. These are critical for validating LLM outputs that often contain unexpected formats.
from pydantic import BaseModel, field_validator, model_validator
class ToolCall(BaseModel):
name: str
arguments: dict
@field_validator("name")
@classmethod
def validate_tool_name(cls, v: str) -> str:
allowed = {"web_search", "calculator", "code_exec", "file_read"}
if v not in allowed:
raise ValueError(f"Unknown tool: {v}. Allowed: {allowed}")
return v
@field_validator("arguments", mode="before")
@classmethod
def parse_arguments(cls, v):
if isinstance(v, str):
import json
return json.loads(v)
return v
class AgentResponse(BaseModel):
content: str
tool_calls: list[ToolCall] = []
confidence: float = Field(ge=0.0, le=1.0)
@model_validator(mode="after")
def check_tool_calls_have_content(self):
if self.tool_calls and not self.content:
self.content = f"Executing {len(self.tool_calls)} tool(s)"
return self
AI applications are configuration-heavy. Pydantic's BaseSettings loads values from environment variables automatically, with type validation.
from pydantic_settings import BaseSettings
from pydantic import Field, SecretStr
class AISettings(BaseSettings):
model_config = {"env_prefix": "AI_", "env_file": ".env"}
openai_api_key: SecretStr
anthropic_api_key: SecretStr = Field(default=SecretStr(""))
default_model: str = "gpt-4o"
max_retries: int = 3
request_timeout: float = 30.0
embedding_model: str = "text-embedding-3-small"
vector_db_url: str = "http://localhost:6333"
settings = AISettings()
# Reads AI_OPENAI_API_KEY, AI_DEFAULT_MODEL, etc. from environment
# SecretStr prevents accidental logging of API keys
print(settings.openai_api_key) # prints SecretStr('**********')
print(settings.openai_api_key.get_secret_value()) # actual key
Pydantic v2 gives you fine-grained control over serialization with model_dump and model_dump_json.
config = AgentConfig(name="researcher", role=AgentRole.RESEARCHER)
# Exclude defaults for cleaner API responses
config.model_dump(exclude_defaults=True)
# {"name": "researcher", "role": "researcher"}
# Include only specific fields
config.model_dump(include={"name", "model", "temperature"})
# JSON serialization with custom formatting
config.model_dump_json(indent=2)
LLMs do not always return perfectly formatted JSON. Use Pydantic with try/except to handle partial or malformed outputs gracefully.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
from pydantic import ValidationError
def parse_agent_response(raw_json: str) -> AgentResponse:
try:
return AgentResponse.model_validate_json(raw_json)
except ValidationError as e:
# Log the errors, return a safe fallback
errors = e.error_count()
print(f"Validation failed with {errors} error(s)")
return AgentResponse(content="[Parse error]", confidence=0.0)
The biggest changes are: field_validator replaces @validator, model_validator replaces @root_validator, model_dump() replaces .dict(), model_dump_json() replaces .json(), and model_config dict replaces the inner class Config. The Rust core makes v2 significantly faster for high-throughput agent pipelines.
Generally no. LLM outputs are messy — numbers come as strings, booleans as "true"/"false" text. Pydantic's default lax mode coerces these automatically. Use strict mode only for internal APIs where you control both ends of the data flow.
Pydantic adds validation, serialization, and settings management that dataclasses lack. For internal data containers with no external input, dataclasses are fine. For anything touching LLM outputs, API boundaries, or configuration, Pydantic is the better choice.
#Python #Pydantic #DataValidation #AIEngineering #AgenticAI #LearnAI

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
The 2026 desktop AI agent landscape — ServiceNow Project Arc, Anthropic Claude offerings, OpenAI agents, and Google Mariner. A buyer's map.
A clean before/after of agent architecture in 2026. The control loop moved from your framework code into the model's reasoning chain. What that looks like.
Google's May 2026 MCP 1.0 + A2A developers guide is the cleanest protocol picker we have seen. The takeaways, in plain English, with a CallSphere lens.
Workspace Studio puts a Gemini-powered AI agent builder inside Google Workspace. A walkthrough of what it does, who it is for, and where it fits in 2026.
Gemini 3.1 Ultra ships with a 2-million token context window and full text, image, audio, and video multimodality. What changes and how to build for it.
A 'did the agent answer correctly?' pass/fail hides broken tool calls, wasted tokens, and silent retries. Here is how to evaluate intermediate steps.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.
Try Live DemoBook a DemoCalculate Your ROI