โ† Back to Blog
AI EngineeringAgentsTools

Choosing an AI Agent Framework in 2026: Pydantic AI vs OpenAI Agents SDK vs Claude Agent SDK

Three SDKs now cover most agent projects. This guide explains what each one optimises for, shows the same small agent built in Pydantic AI, and gives you a decision table you can use before writing any code.

By Joinloopยท30 October 2026ยท8 min read
ShareLinkedInXReddit
๐Ÿงญ

Most agent tutorials start with a framework and never explain why it was picked. Six months later the team is fighting its abstractions: a provider switch needs a rewrite, the tracing does not show what the model actually saw, or a "simple" workflow needs a graph engine nobody understands. The framework decision is cheap to make and expensive to undo, so make it on purpose.

This post compares the three SDKs that come up most often for Python teams building agents: Pydantic AI, the OpenAI Agents SDK, and the Claude Agent SDK. It also gives you a decision table and a runnable example in Pydantic AI, so you can see the typed-output style for yourself.

The problem

An agent framework does three jobs:

  1. Calls the model and normalises the request and response across providers.
  2. Runs the loop: send messages, execute tool calls, feed results back, stop when done.
  3. Enforces the contract: validates outputs, limits tools, records what happened.

Every framework does all three, but each one leans toward a different job. The choice comes down to which job you care about most and how many model providers you need to support.

What each SDK optimises for

Pydantic AI is a provider-agnostic Python framework built around typed inputs and outputs. You declare an output_type as a Pydantic model, and the framework turns it into a tool schema, validates what comes back, and sends validation errors to the model for a retry. It supports many providers through a single Agent interface, and it ships Pydantic Evals for testing. It is the strongest choice when you want the same code to run against more than one vendor.

The OpenAI Agents SDK is a small Python library built close to OpenAI's API. Its differentiators are handoffs between agents, guardrails, and built-in tracing. OpenAI models are first-class; other providers work through an adapter layer such as LiteLLM. It is the natural pick when your stack is already OpenAI-first and you want handoffs and tracing without extra wiring.

The Claude Agent SDK is the agent loop behind Claude Code, exposed as a library. You get Anthropic's built-in tools, a permission model, and sub-agents out of the box. It runs Claude models on Anthropic, Bedrock, Vertex, and Foundry. It is the strongest choice when the agent is a coding or file-and-shell agent, because you inherit the tooling that already works. It does not ship an evals module, so you bring your own.

Vendor comparison pages are written by competitors, so treat the feature claims above as a starting point and check each project's current docs before you commit.

A minimal typed agent in Pydantic AI

Here is the smallest useful example: an agent that turns a support message into a structured ticket. The output is a validated Pydantic object, not a string you have to parse.

# pip install pydantic-ai
# export ANTHROPIC_API_KEY=...
from typing import Literal

from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext


class Ticket(BaseModel):
    category: Literal["billing", "bug", "feature_request", "other"]
    priority: int = Field(ge=1, le=5, description="1 = urgent, 5 = low")
    summary: str = Field(max_length=140)


agent = Agent(
    "anthropic:claude-sonnet-5-5",
    output_type=Ticket,
    instructions="Classify the customer message into a support ticket.",
)


@agent.tool
def customer_tier(ctx: RunContext[dict], customer_id: str) -> str:
    """Return the subscription tier for a customer. Use it when priority depends on plan."""
    return ctx.deps.get(customer_id, "free")


if __name__ == "__main__":
    result = agent.run_sync(
        "I was charged twice this month and I need it fixed today.",
    )
    ticket = result.output  # a validated Ticket instance
    print(ticket.model_dump_json(indent=2))

Three things to notice:

  • The output is the contract. If the model returns priority: 9 or an unknown category, Pydantic AI rejects it and asks for a corrected answer. Your code only ever sees a valid Ticket.
  • The tool docstring is part of the prompt. The model decides when to call customer_tier from that docstring. A vague docstring produces tools that are called at the wrong time.
  • RunContext carries dependencies. Pass a database handle or an HTTP client through deps instead of reaching for module globals. This also makes the agent easy to test with a fake dependency.

The ctx.deps in the example is a plain dict so the snippet stays self-contained. In a real service you would pass a typed object, and the deps type parameter on RunContext lets your editor check it.

Check the official docs for your installed version. The output_type and result.output names have changed across releases, and older tutorials still show result.data.

Comparison table

Question Pydantic AI OpenAI Agents SDK Claude Agent SDK
Primary strength Typed outputs, provider portability Handoffs, guardrails, tracing Ready-made coding and tool agent loop
Model providers Many, via one interface OpenAI first; others via adapter Claude on Anthropic, Bedrock, Vertex, Foundry
Structured output Pydantic models, validated with retries Typed outputs supported Typed tool inputs; output shaped by your prompt and tools
Multi-agent Sub-agents, delegation, graph engine Handoffs as a first-class concept Sub-agents
Built-in tools Bring your own Hosted tools (OpenAI-side) File, shell, and web tools from the Claude Code harness
Evals Pydantic Evals Included Bring your own
Best fit Multi-provider backend agents, extraction, workflows OpenAI-native agent workflows with handoffs Coding agents, file and shell automation

Use this as a first filter, not a verdict. The real decision is about where your model calls happen and who owns the loop.

How to decide in four questions

  1. How many providers must you support, now or within a year? If the answer is more than one, Pydantic AI or a thin custom loop wins. If it is one vendor and you accept that, a vendor SDK removes a layer.
  2. Is the agent mostly tool use over files, code, or a shell? The Claude Agent SDK gives you a tested harness for that. Building the equivalent yourself is weeks of permission and sandbox work.
  3. Do you need typed outputs more than orchestration? For extraction, classification, and routing, a typed output_type plus a plain function is often all you need. Reach for a graph or handoff system only when control flow is genuinely complex.
  4. What do you already test with? If your team has Pydantic models and pytest, Pydantic AI and Pydantic Evals feel native. If your observability is already on OpenAI's tracing, the Agents SDK keeps the traces in one place.

Common pitfalls

  • Choosing for the demo, not the second year. A framework that makes the first agent 20 minutes faster can make the tenth integration a month slower. Ask how it handles provider switches and retries before you ask how short the quickstart is.
  • Letting the framework own your prompts. Keep system prompts in version-controlled files and pass them in. If you cannot diff a prompt change, you cannot debug a regression.
  • Skipping the loop limit. Every framework lets the model call tools repeatedly. Set an explicit maximum number of steps and a budget per run, or one bad prompt can burn through your credits.
  • Trusting the output without a test. Validation proves the output has the right shape, not that the category is right. Write a small golden set of messages and check accuracy on every prompt or model change.
  • Mixing two orchestration layers. Running an agent framework inside a workflow engine, which then calls another agent framework, produces traces nobody can read. Pick one owner for the loop.
  • Locking in by accident. If you use a vendor-specific tool or hosted feature, isolate it behind your own interface so a later switch touches one file.

Next steps

  • Take one agent you already have and write its output as a Pydantic model. Even if you keep your current framework, the typed contract will catch bugs immediately.
  • Write a 20-case golden set for the agent's most important decision and run it against two providers. The result will tell you more about portability than any comparison page.
  • Read the official quickstart for whichever SDK you are leaning towards, then build the same tiny agent in it. Two hours of this beats two weeks of debating.

If you want to build production agents with a guided group, with code reviews and real evaluation, the Joinloop AI Engineering cohort is designed for exactly this. Bring the agent you are building and leave with a version you can ship.

ShareLinkedInXReddit

Want to build this yourself?

Join a live cohort and go from reading about AI to shipping it, with practitioners who do it daily.