★ Reading this for free? Get 20 structured AI courses + per-chapter AI tutor — the first chapter of every course free, no card.Start free in 30 seconds
AI Agents

Pydantic AI + Ollama: Type-Safe Local Agents in Python

August 30, 2026
13 min read
LocalAimaster Research Team

Want to go deeper than this article?

Free account unlocks the first chapter of all 25 courses — RAG, agents, MCP, voice AI, MLOps, real GitHub repos.

📚AI Learning Path

Ollama’s running. Here’s what to build with it. Go from “ollama run” to RAG apps, agents, and fine-tuned models — structured and hands-on. First chapter free.

Start free
Or own it for life — Lifetime $149, pay once

Short answer: Pydantic AI has first-class Ollama support — pip install "pydantic-ai-slim[openai]", point OllamaProvider at http://localhost:11434/v1, and qwen3:8b (5.2GB download, fits an 8GB GPU) gives you a tool-calling agent whose output is a validated Pydantic model, not a string you regex-parse. On self-hosted Ollama v0.5.0+, NativeOutput mode is genuinely schema-enforced — Ollama constrains generation to your JSON schema — and MCP servers plug in with three lines via MCPToolset. Everything on this page runs free, offline, with no API key.

That is the whole pitch, and it is a strong one: of the big Python agent frameworks, Pydantic AI is the one built by the Pydantic team itself, so "the LLM returns typed, validated data or the run fails loudly" is the core design rather than an add-on. Below is the complete working stack — setup, model choice, structured output, tools, MCP — verified against the official docs and current package versions in August 2026, plus the failure modes the tutorials skip.


Why Choose Pydantic AI for Local Agents?

Answer first: pick Pydantic AI when agent output feeds real code — its whole design is typed input/output with Pydantic validation, it is MIT-licensed with ~19k GitHub stars, and version 2.25 (August 2026) has a dedicated Ollama provider, so local is a first-class citizen, not a workaround.

Every agent framework demo looks the same: model plans, calls a tool, prints a paragraph. The difference shows up the day you need the result in a program — an InvoiceData object going into a database, not markdown that mostly resembles one. Pydantic AI's bet is that this boundary is the hard part. An Agent is parameterized by an output type; the run returns an instance of that type or raises. Your IDE autocompletes result.output.total. That is the feature.

Where it sits against the frameworks we have covered before:

  • LangChain + Ollama has the largest integration catalog by far, at the cost of a much larger API surface.
  • CrewAI owns the multi-agent "crew of roles" pattern.
  • Pydantic AI is the smallest of the three to hold in your head, and the only one where schema-validated output is the default posture rather than an output-parser bolted on.

Our broader agent framework comparison covers the field; this page is the local-first Pydantic AI track specifically. Current version: pydantic-ai 2.25.0 as of early August 2026, Python 3.10+ (PyPI). The docs are maintained by the Pydantic team and have been notably stable — but note the project moved fast through 2025, so older community tutorials show APIs (like MCPServerStdio) that current releases have replaced. Everything below matches the 2.x docs.


Reading articles is good. Building is better.

Free account = 20+ free chapters across 25 courses, with a per-chapter AI tutor. No card. Cancel anytime if you ever upgrade.

Setup in Five Minutes

Answer first: two installs and one pull — Ollama itself, qwen3:8b (5.2GB), and pydantic-ai-slim[openai]. The openai extra is not a cloud dependency; it provides the OpenAI-compatible transport that Ollama's local endpoint speaks.

# 1. Install Ollama from ollama.com/download, then pull a tool-capable model
ollama pull qwen3:8b        # 5.2GB download

# 2. Install Pydantic AI (slim install + the transport the Ollama provider uses)
pip install "pydantic-ai-slim[openai]"

The minimal agent, exactly per the official Ollama docs page:

from pydantic_ai import Agent
from pydantic_ai.models.ollama import OllamaModel
from pydantic_ai.providers.ollama import OllamaProvider

model = OllamaModel(
    'qwen3:8b',
    provider=OllamaProvider(base_url='http://localhost:11434/v1'),
)
agent = Agent(model, instructions='Answer in one sentence.')

result = agent.run_sync('Why is the sky blue?')
print(result.output)

Two things worth noticing. First, OllamaModel and OllamaProvider are dedicated classes now — the old pattern of aiming a generic OpenAI model class at localhost still floats around in 2025-era tutorials, but the dedicated provider is what the docs specify and what knows Ollama's quirks (more on that in the structured-output section). Second, base_url ends in /v1 — Ollama's OpenAI-compatible endpoint, not the bare :11434. Leaving off the /v1 is the most common "connection refused-ish" mistake in the project's issue threads.

There is nothing else. No API key, no environment variable, no billing page. If ollama list shows the model, the agent runs.


Which Local Model Should You Use?

Answer first: qwen3:8b is the default pick — it is the family Pydantic's own docs use, it has both tools and thinking capabilities on its Ollama library page, and 5.2GB fits an 8GB card. Move to qwen3:14b (9.3GB) on a 12-16GB GPU for visibly steadier multi-step tool use.

Agent work is the one workload where model choice is not negotiable: the model must emit well-formed tool calls, repeatedly, mid-conversation. The qwen3 family is the safest local bet right now — the Ollama library marks the whole line with tool support, and it sits at 33.4M+ downloads. Download sizes below are from the Ollama library (August 2026). The VRAM column is arithmetic, not a measurement: a quantized model needs roughly its download size in memory plus headroom for context and the KV cache, so round up a tier if you plan to run long conversations.

Model tagDownloadRuns comfortably onAgent verdict
qwen3:4b2.5GB6GB+ VRAM, or CPUSimple single-tool agents only
qwen3:8b (default)5.2GB8GB VRAMThe starting point; fine at 1-2 tool hops
qwen3:14b9.3GB16GB VRAMOur pick for real multi-step agents
qwen3:30b19GB24GB VRAMMoE; strong tool use if you have the card
qwen3:32b20GB24GB VRAMDense flagship short of the 235b

The docs' own example model is qwen3, which resolves to the 8b default tag. Our full qwen3 setup guide covers quantization variants and thinking mode; for a wider survey of which local models can actually call tools without face-planting, see best Ollama models for agents.

One behavioral note: qwen3 is a thinking model, so expect it to spend tokens reasoning before it acts. For agents this is usually a feature — tool-call accuracy is what you are buying — but it adds latency you will notice on a small GPU.


Is Structured Output Actually Enforced?

Answer first: with output_type=NativeOutput(YourModel) on self-hosted Ollama v0.5.0+, the model is constrained to emit JSON matching your schema — per the Pydantic AI docs this is real schema-valid generation via json_schema, not a polite request in the prompt. Ollama Cloud does not enforce it, and Pydantic AI knows to disable native mode there automatically.

This is the marquee feature of the pairing, so let us be precise about what is guaranteed and by whom.

Pydantic AI has three output modes (per the official output docs):

ModeHow it worksReliability on local models
ToolOutput (default)Your schema becomes a special output tool the model must callHigh — works with virtually any tool-capable model
NativeOutputThe serving layer forces output to match the JSON schemaHighest shape guarantee — where supported
PromptedOutputSchema pasted into the instructions; model complies voluntarilyLowest; last resort for tool-less models

The docs describe NativeOutput as using the model's native structured-outputs feature, "where the model is forced to only output text matching the provided JSON schema." On the Ollama side, that feature is the structured outputs Ollama shipped in v0.5.0 (announced December 6, 2024): pass a JSON schema in the format parameter and Ollama constrains the model's output to it. Pydantic AI's Ollama page confirms the pairing explicitly — self-hosted Ollama v0.5.0+ supports NativeOutput with schema-valid generation via json_schema.

In code:

from pydantic import BaseModel
from pydantic_ai import Agent, NativeOutput
from pydantic_ai.models.ollama import OllamaModel
from pydantic_ai.providers.ollama import OllamaProvider


class CityInfo(BaseModel):
    city: str
    country: str
    population: int


model = OllamaModel(
    'qwen3:8b',
    provider=OllamaProvider(base_url='http://localhost:11434/v1'),
)
agent = Agent(model, output_type=NativeOutput(CityInfo))

result = agent.run_sync('Tell me about Tokyo.')
print(result.output)             # CityInfo(city='Tokyo', country='Japan', population=...)
print(result.output.population)  # an actual int — parsed and validated

No json.loads, no retry-on-parse-error loop, no "please respond ONLY with JSON" incantation in the prompt. The object either validates or the run errors.

Three honest caveats:

  1. Schema-valid is not fact-valid. Enforcement guarantees the shape. The population figure is still whatever the model believes; a grammar cannot make it true.
  2. Ollama Cloud is different. Per the docs, Ollama's cloud endpoint (https://ollama.com/v1) does not enforce json_schema — schemas are silently ignored there, so Pydantic AI raises a UserError if you request NativeOutput with a cloud model; use the default ToolOutput or PromptedOutput instead. This page is about local anyway, where the guarantee holds.
  3. When an agent also has function tools, we default to ToolOutput. It is Pydantic AI's default for a reason — one mechanism (tool calls) for both tools and output keeps small local models on familiar ground. Reach for NativeOutput on pure extraction jobs where the hard shape guarantee is the point.

Reading articles is good. Building is better.

Free account = 20+ free chapters across 25 courses, with a per-chapter AI tutor. No card. Cancel anytime if you ever upgrade.

How Do You Give the Agent Tools?

Answer first: decorate plain Python functions with @agent.tool_plain (or @agent.tool when they need RunContext deps); type hints plus the docstring become the tool schema automatically, and the typed result comes back through the same validated pipeline.

A compact but real example — a release-notes triage agent that reads your git log and returns structured data your CI can act on:

import subprocess
from pydantic import BaseModel
from pydantic_ai import Agent
from pydantic_ai.models.ollama import OllamaModel
from pydantic_ai.providers.ollama import OllamaProvider


class ReleaseSummary(BaseModel):
    headline: str
    breaking_changes: list[str]
    needs_migration_guide: bool


model = OllamaModel(
    'qwen3:14b',
    provider=OllamaProvider(base_url='http://localhost:11434/v1'),
)
agent = Agent(
    model,
    output_type=ReleaseSummary,   # default ToolOutput mode — plays nicely with tools
    instructions='Summarize the release from the commit log. Be terse.',
)


@agent.tool_plain
def git_log(n: int = 30) -> str:
    """Return the last n commit subject lines."""
    out = subprocess.run(
        ['git', 'log', f'-{n}', '--pretty=%s'],
        capture_output=True, text=True, check=True,
    )
    return out.stdout


result = agent.run_sync('Draft the summary for the upcoming release.')
print(result.output.breaking_changes)      # list[str], guaranteed

The model decides when to call git_log, Pydantic AI executes it, feeds the result back, and keeps going until the model produces a valid ReleaseSummary. When a tool needs shared state or credentials, use @agent.tool with a RunContext first parameter and pass deps= at run time — same pattern, dependency-injected. Tools can also be passed as a plain list via Agent(tools=[...]) if you prefer functions defined elsewhere.

What to expect from local models here: reliability falls off as the tool chain lengthens, because every hop is another chance to emit a malformed call or the wrong argument, and the errors compound. An 8b model is fine for one or two hops; long autonomous chains are where stepping up to qwen3:14b earns its VRAM. Either way, design agents so a single run needs few hops — fewer, bigger tools beat many tiny ones on local models.


How Do You Connect an MCP Server?

Answer first: MCPToolset('http://localhost:8000/mcp') (or a path to a local server script) passed via toolsets=[...] gives your local agent every tool that MCP server exposes — three lines, lifecycle managed automatically.

The Model Context Protocol is how the ecosystem ships reusable tool servers — filesystem access, browsers, databases — instead of everyone re-writing the same functions (MCP explained here). Pydantic AI's client side is MCPToolset:

from pydantic_ai import Agent
from pydantic_ai.mcp import MCPToolset
from pydantic_ai.models.ollama import OllamaModel
from pydantic_ai.providers.ollama import OllamaProvider

model = OllamaModel(
    'qwen3:14b',
    provider=OllamaProvider(base_url='http://localhost:11434/v1'),
)

toolset = MCPToolset('http://localhost:8000/mcp')   # any MCP server URL
agent = Agent(model, toolsets=[toolset])


async def main():
    result = await agent.run('What files changed in the last commit?')
    print(result.output)

Per the docs, MCPToolset accepts a Streamable HTTP or SSE URL, a path to a local Python or Node.js server script (stdio), a FastMCP transport object, or an in-process FastMCP server. You can manage connections with async with agent:, but if you do not, the toolset is opened and closed automatically as needed — one less footgun than the earlier API generations had.

Two practical notes. First, this is the section where old tutorials will burn you: pre-2.x examples use MCPServerStdio/MCPServerSSE and agent.run_mcp_servers() — that era's API. If you are following a 2025 blog post and imports fail, this is why; the current class is MCPToolset. Second, MCP tools arrive at the model as ordinary function tools, so everything said above about local tool-calling quality applies unchanged — a server exposing 40 tools will drown an 8b model in choices. Prefer focused servers, or filter what you expose. Our Ollama MCP integration guide covers the server side of this same stack.


Honest Limitations

Answer first: the framework is solid; the ceiling is the local model. Budget for flaky long tool chains below 14b, remember schema enforcement stops at shape, and pin your versions — this project has a history of API renames.

  • Small models fumble long chains. The single biggest gap between a GPT-class demo and your local run. One or two tool hops on qwen3:8b: fine. Long autonomous loops: use qwen3:14b+ or restructure the task. This is a model limit, not a Pydantic AI limit — the framework's retry-on-validation-failure loop actually papers over a lot of small-model sloppiness.
  • NativeOutput guarantees shape, not truth — and it is enforced on self-hosted Ollama only, not Ollama Cloud. Validation passing tells you the JSON parsed, not that the answer is right.
  • API churn risk. Pydantic AI went through real renames on its way to 2.x (the MCP client API most visibly). Docs are excellent and current, but pin pydantic-ai in production and read release notes before jumping majors. The flip side: the 2.x surface has been stable through 2026 and the project is run by the Pydantic team, which maintains one of the most-depended-on packages in Python — abandonment risk is about as low as it gets.
  • Thinking models trade latency for accuracy. qwen3's reasoning phase means slower first tokens than a non-thinking model of the same size. For agents we accept the trade; for chat UX you might not.
  • No multi-agent orchestration opinions. Pydantic AI gives you agents, tools, toolsets — composition is your job. If you want an opinionated crew topology out of the box, that is CrewAI's lane.

Verdict

Pydantic AI + Ollama is currently our recommended stack for local agents that feed structured data into real programs. The type-safety story is not marketing — schema-enforced generation on self-hosted Ollama plus Pydantic validation on the way out means the classic agent failure mode (garbled JSON at 2am) largely disappears. Setup is genuinely two commands, the official docs treat Ollama as a first-class target, and MCP support is three lines.

The recipe once more: ollama pull qwen3:8b to start, qwen3:14b on a 16GB card the moment your agent needs more than two tool hops, pip install "pydantic-ai-slim[openai]", default ToolOutput for tool-using agents, NativeOutput for hard-shape extraction. Total cost: $0 and some VRAM you already own.


Sources


FAQ

🎯
AI Learning Path

Ollama’s running. Here’s what to build with it.

Go from “ollama run” to RAG apps, agents, and fine-tuned models — structured and hands-on. First chapter free.

Or own it for life — Lifetime $149 $599, pay once
Once your hardware is sorted

Stop piecing Ollama together from blog posts

Ollama Mastery is 15 chapters end to end — install, model choice, Modelfiles, GPU offload, the API, and the 20 errors that actually happen. Plus 24 more courses.

$149 once unlocks everything, forever — about $0.27/chapter for life. Prefer to spread it out? Pro is $79/year (saves 27%) or $8.99/month.
Secure checkout by Lemon Squeezy — your card never touches this siteInstant access the moment you payFirst chapter of every course is free — try before you buy

Liked this? 20 full AI courses are waiting.

From fundamentals to RAG, agents, MCP servers, voice AI, and production deployment with real GitHub repos. First chapter free, every course.

Reading now
Join the discussion

LocalAimaster Research Team

Creator of Local AI Master. I've built datasets with over 77,000 examples and trained AI models from scratch. Now I help people achieve AI independence through local AI mastery.

Build Real AI on Your Machine

RAG, agents, NLP, vision, and MLOps - chapters across 25 courses that take you from reading about AI to building AI.

Want structured AI education?

25 courses, 519+ chapters, from $9. Understand AI, don't just use it.

AI Learning Path
More on Ollama
See the full Best Ollama Models 2026 guide.

Comments (0)

No comments yet. Be the first to share your thoughts!

Does Pydantic AI work with Ollama?

Yes, officially. Pydantic AI ships a dedicated OllamaModel and OllamaProvider (import from pydantic_ai.models.ollama and pydantic_ai.providers.ollama) that talk to Ollama's OpenAI-compatible endpoint at http://localhost:11434/v1. Install with pip install "pydantic-ai-slim[openai]" — the openai extra provides the transport the Ollama provider rides on. No API key, no cloud account, no per-token cost.

Which local model is best for Pydantic AI agents?

Start with qwen3:8b — it is the model family Pydantic's own Ollama docs use in their example, it has both tool-calling and thinking capabilities per its Ollama library page, and at a 5.2GB download it fits on an 8GB GPU. If you have 12-16GB of VRAM, qwen3:14b (9.3GB) is the safer choice for multi-step tool use, because tool-call reliability is the thing that degrades first as a model gets smaller. The qwen3 family has 33.4M+ downloads on the Ollama library as of August 2026.

Does structured output actually guarantee valid JSON with a local model?

With self-hosted Ollama, yes — at the shape level. Per the Pydantic AI docs, self-hosted Ollama v0.5.0+ supports NativeOutput with schema-valid generation via json_schema: Ollama constrains the model's output to the JSON schema you provide, so what comes back parses and validates. Two caveats: Ollama Cloud does not enforce json_schema (Pydantic AI raises a UserError if you request NativeOutput on a cloud model — use the default ToolOutput or PromptedOutput there), and schema-valid is not the same as factually correct. The shape is guaranteed; the content is still the model's best effort.

Can Pydantic AI use MCP servers with a local Ollama model?

Yes. MCPToolset (from pydantic_ai.mcp) accepts an MCP server URL, a path to a local Python or Node.js server script, or a FastMCP transport, and you pass it to the Agent via toolsets=[...]. Connection lifecycle is handled automatically. The one requirement is a local model that handles tool calling well — MCP tools are surfaced to the model as ordinary function tools, so a weak tool-caller will fumble MCP exactly as it fumbles local tools. qwen3:8b and up handle it.

Pydantic AI vs LangChain vs CrewAI — which for local agents?

Pydantic AI when you want typed, validated output and a small API surface — it is the only one of the three where "the agent returns a Pydantic model instance or raises" is the core design. LangChain when you need its huge integration catalog. CrewAI when the multi-agent role-playing pattern fits your problem. All three run on Ollama. Pydantic AI (~19k GitHub stars, MIT, from the team behind Pydantic itself) is the youngest of the three and the narrowest in scope, which is the point: it is built for the case where agent output feeds structured data into real code.

Ready to Go Beyond Tutorials?

20 structured courses with hands-on chapters - build RAG chatbots, AI agents, and ML pipelines on your own hardware.

Bonus kit

AI Agent Starter Kit

Skip the boilerplate: 3 ready local agents (Research, Code Review, Data Analysis) with native tool calling + MCP support — add your own tools in minutes. Included with paid plans, or free after subscribing to both Local AI Master and Little AI Master on YouTube.

See Plans →

Was this helpful?

📅 Published: August 30, 2026🔄 Last Updated: August 30, 2026✓ Manually Reviewed
LM

Written by the Local AI Master Team

The team behind Local AI Master

We build Local AI Master around practical, testable local AI workflows: model selection, hardware planning, RAG systems, agents, and MLOps. The goal is to turn scattered tutorials into a structured learning path you can follow on your own hardware.

✓ Local AI Curriculum✓ Hands-On Projects✓ Open Source Contributor
📚
Free · no account required

Grab the AI Starter Kit — career roadmap, cheat sheet, setup guide

No spam. Unsubscribe with one click.

🎯
AI Learning Path

Ollama’s running. Here’s what to build with it.

Go from “ollama run” to RAG apps, agents, and fine-tuned models — structured and hands-on. First chapter free.

Or own it for life — Lifetime $149 $599, pay once
Free Tools & Calculators