I connected my code to the LLM’s API.
I was giddy.
I was building a simple tool to process some information. I wrote a prompt that felt foolproof:
“Please extract the username and the order ID from this email text. Return it in JSON format.”
I ran the script. It worked!
I got back:
{"username": "Dylan", "order_id": 101}
I thought, “AI engineering thing is easy.”
Then I ran it again.
The response:
Here is your JSON: {"username": "Dylan", "order_id": 101}.
My code failed because it didn’t expect the conversational filler text.
I ran it a third time.
The response:
{"user_name": "Dylan", "order_id": "unknown"}
The field name changed from “username” to “user_name”, and the “order_id” became a string instead of an integer.
Damn it.
I spent the next few hours handling the randomness of the output.
I felt like I wasn’t building software.
I was trying to patch holes in a sinking boat with duct tape. How do I guarantee it won’t give me something unexpected in the future, especially when I deploy to production?
Welcome to AI Engineering.
You are trying to build reliable systems on top of unreliable, probabilistic models.
This is exactly why you need a library like Pydantic.
The Club Bouncer
If you come from a background in Java or any OOP language, you are used to safety. You have Interfaces and DTOs (Data Transfer Objects).
If you try to pass a String into an Integer field, the compiler yells at you before the code even runs.
Python, however, is the “Wild West.” It is dynamic. It lets you do whatever you want. And when you combine Python’s looseness with an LLM’s hallucination, you get chaos.
This is where Pydantic comes in.
Think of your function as an exclusive Nightclub. Think of the LLM as a Drunk Genius Guest. They are brilliant and can answer any question, but they are sloppy, unpredictable, and might show up to a black-tie event in flip-flops.
Pydantic is the Bouncer standing at the door.

Pydantic holds a strict checklist (the Schema).
“Name must be a String.”
“Age must be an Integer.”
“User ID must be valid.”
When the LLM stumbles up to the door and hands over data, Pydantic checks it.
If the LLM hands over age: “twenty-five” (String), the Bouncer blocks it.
If the LLM hands over age: 25, the Bouncer lets it in.
Pydantic turns Python from a loose scripting language into a strict, industrial-grade tool capable of handling the chaos of AI.
The Mechanics: Parsing vs. Validation
This is where the magic happens.
The old way, without Pydantic, your code looks like defensive spaghetti:
# You can do a bunch of manual checkings...class User: def __init__(self, id, name): if isinstance(id, str): if id.isdigit(): id = int(id) else: raise ValueError(”ID is messed up”)
# Checking if name exists... if not name: raise ValueError(”Name is missing”)
self.id = id self.name = name
The Pydantic Way, you declare what you want, not how to validate it.
from pydantic import BaseModel
class User(BaseModel): id: int name: str is_active: bool = True
Type Coercion Pydantic does something traditional validation libraries don’t do:
It fixes the data.
If the LLM hands you {”id”: “123”} (a String), a normal validator would scream “Error! I wanted an Integer, not a String!”
Pydantic is smarter. It says,
“I see you gave me a string ‘123’. I know you probably meant the integer 123. Let me fix that for you.”
It automatically converts (parses) the string “123” into the integer 123.
For an AI Engineer, this Type Coercion is a lifesaver, because LLMs love to output numbers as text.
The AI Connection: Schema is the New Prompt
Here is the insight that changed my perspective on AI development.
In the past, we tried to control AI output using Prompt Engineering (English).
“Please give me JSON. Please don’t add extra text. Please use this format...”
This is fragile. It relies on the AI “listening” to you. At least this is what we do when we are talking to a Chatbot.
But we are not talking through a chat interface now, we are building the AI agent from ground up.
With Pydantic, we shift to Schema Engineering (Code).
Modern AI APIs (like OpenAI’s Function Calling or Gemini’s Structured Output) allow us to feed a Pydantic class directly into the model.
Under the hood, Pydantic translates your Python class into a JSON Schema. The AI sees this schema as a “Fill-in-the-Blanks” template. It effectively forces the model to ignore its creative tendencies and strictly follow the structure you defined.
We are no longer begging the AI to be structured. We are constraining it with code.
The Pydantic AI
The same team that developed Pydantic has also developed an agent framework, Pydantic AI, centered on schema-first data validation and reliable, structured output.
Well, what’s the difference?
While Pydantic is the library for data validation, Pydantic AI is the framework for building Agents. It is the Club Manager.
As a club manager, it negotiates with suppliers (OpenAI, Gemini), manages the staff (the tools), and handles the VIP requests (Dependency Injection).
Model Agnostic: Today you want to use GPT-5.1. Tomorrow you might want to switch to Gemini 3 Pro because it’s cheaper (maybe). With Pydantic AI, you just change one string of code. The Manager handles the negotiation; the Bouncer (validation) stays the same.
Streaming Validation: Pydantic AI can validate data as it streams in. It doesn’t have to wait for the LLM to finish speaking. The Manager checks the data in real-time, making your app feel faster (solving potential latency issues).
Dependency Injection: If you need to give your AI access to a database connection or an API key, Pydantic AI handles this in a type-safe way (just like Spring Boot). It brings engineering rigor to the messy world of AI scripts.
The Verdict
As Software Engineers, we are trained to write logic. But in the AI era, a huge part of our job is simply taming the input.
If you are just building a simple script, raw Pydantic is enough. It is the oxygen of reliable AI. But if you are building a complex Agent that needs to take actions and switch models, look into Pydantic AI to manage the workflow.
The next time you start an AI project, don’t just write a prompt string.
Start by defining your data structure.
Define the output first, then ask the AI to fill it.
This simple shift in mindset, from “Prompting” to “Modeling” (which is what we traditional software engineers are good at), will save you 80% of your debugging time and let you sleep better at night, knowing the Bouncer is watching the door.
Subscribe to “Till We Code Again” for more easy-to-understand breakdowns on pivoting from Software Engineering to AI Engineering.
Cheers.