Migrating Openai Agents SDK To Pydantic AI
PydanticOfficialPublished by Pydantic
- Skill
- Workflow
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured methodology for migrating existing OpenAI Agents SDK applications to Pydantic AI. It emphasizes preserving externally observable behavior rather than internal object shapes, focusing on migrating functional slices while maintaining application infrastructure. The guide covers critical architectural transitions, including agent orchestration, tool handling, conversation state management, guardrails, human-in-the-loop approval, and streaming, while providing specific guidance on when to incorporate Pydantic AI Harness.
What it does
- Defines a step-by-step process for characterizing and migrating application slices.
- Maps OpenAI Agents SDK concepts to their Pydantic AI equivalents.
- Provides strategies for handling complex agent patterns like handoffs and subagents.
- Outlines verification procedures for high-risk boundaries such as persistence and security.
- Offers guidance on maintaining existing telemetry and operational contracts.
- Specifies when to use Pydantic AI core versus the Harness extension.
When to use it
- When you need to transition a production application from the OpenAI Agents SDK to Pydantic AI.
- When you need to ensure that agent behavior, tool execution, and state management remain consistent during a migration.
- When you are unsure how to map specific OpenAI SDK features like guardrails or handoffs to Pydantic AI.
- When you need to verify that your migrated agent maintains the same public-facing contracts as the original.
Advantages
- Reduces migration risk by focusing on observable contracts rather than internal implementation details.
- Provides clear semantic mapping to avoid common pitfalls in agent orchestration.
- Ensures that security, approval, and persistence boundaries are handled correctly.
- Promotes a test-driven approach to migration using characterization tests.
Usage examples
- “How do I migrate an agent that uses OpenAI handoffs to Pydantic AI?”
- The guide instructs you to evaluate whether the handoff is an application routing requirement or a subagent pattern, then implement it using explicit routing or Pydantic AI Harness SubAgents.
- “What should I do with my existing OpenAI guardrails during migration?”
- The guide advises preserving the boundary checks, failure shapes, and ordering, ensuring that security policies are enforced below the model layer.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/pydantic/migrating-openai-agents-sdk-to-pydantic-ai/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip migrating-openai-agents-sdk-to-pydantic-ai.zip -d .agents/skills
Documentation by Pydantic
Migrate OpenAI Agents SDK to Pydantic AI
Preserve caller-visible behavior, not OpenAI Agents SDK object shapes. Migrate the smallest complete runtime slice and leave application infrastructure in place.
Work from the running application
Read repository instructions, dependency files, tests, and runtime entrypoints. Record the installed
openai-agents, Pydantic AI, and Harness versions.Trace one representative
Runner.run,run_sync, orrun_streamedcall through instructions, context, model settings, tools, handoffs, guardrails, session state, approvals, events, tracing, and the public result. Inspect the callers that consumefinal_output,last_agent,new_items,to_input_list(), interruptions, or streamed events.Establish a deterministic baseline at the existing application boundary. Record only behavior the active path uses.
Classify the slice before designing it:
Ordinary agent: use one reusable Pydantic AI
Agentwith typed dependencies, tools, and outputs.Manager with specialists: use explicit application orchestration, an agent tool, or Harness
SubAgentsaccording to who must own the final response.Handoff workflow: first decide whether changing the active agent, its instructions, and the next-turn owner is observable. A nested agent tool is not a handoff.
Sandbox or coding agent: evaluate Harness
Coderand its component capabilities. Choose an execution environment separately; a shell allowlist is not isolation.Realtime or voice path: treat transport, interruption, audio, and live-session behavior as a separate migration slice using Pydantic AI realtime agents.
Product runtime: retain authentication, storage, queues, deployment, and service integrations unless explicitly placed in scope.
Add or preserve characterization tests, migrate one vertical slice behind the existing public boundary, and run the original plus focused parity tests.
Read Concept Mapping for the source features you found. Read Verification and Cutover before changing persistence, handoffs, approval, streaming, security, or production traffic, and before declaring completion or removing openai-agents.
Stop at semantic gates
Context:
RunContextWrapper.contextis trusted application state and normally becomes typeddeps. Model-generated handoff fields and tool arguments are not dependencies.Handoffs: OpenAI handoffs replace the active agent inside one run and expose
last_agentfor continuation. Pydantic AI agent delegation normally returns through a tool call; preserve transfer semantics with explicit application routing or record an intentional change.Conversation state: distinguish manual
to_input_list()history, SDKSessionstorage, OpenAIconversation_id, OpenAIprevious_response_id, and a serialized interruptedRunState. Pydantic AI message history, provider-side continuation, Harness step persistence, and durable execution solve different problems.Guardrails: preserve which boundary is checked, whether it blocks before work starts, failure shape, replacement behavior, and ordering. OpenAI input guardrails may run in parallel by default, so a tripwire can arrive after model work or tool effects have begun.
Approval: OpenAI HITL resumes a serialized
RunState. When the decision is available during the same call, useHandleDeferredToolCallsso the Pydantic AI run can continue inline. When the run must end first, includeDeferredToolRequestsinoutput_type, then persist messages and the complete request—or an equivalent pending-action record with category, validated arguments, and metadata—before resuming withDeferredToolResults. Re-authorize inside protected tools; approval is not authorization.Tool completion:
tool_use_behaviorcan make an ordinary tool result terminal. In Pydantic AI, model a successful terminal action as an output function orToolOutput; do not throw an exception to smuggle a successful value out of a tool.Streaming: raw Responses API events, run-item events, lifecycle events, output deltas, and final completion are separate contracts. Use
run(event_stream_handler=...),run_stream_events(), oriter()when the full agent loop must complete. Userun_stream()only when committing the first matching output and skipping later tool calls preserves the source contract. Adapt the chosen surface to the public schema.Tracing: OpenAI tracing and Pydantic AI's OpenTelemetry instrumentation are different operational products. Retain existing telemetry unless the user accepts a wider migration; recommend Logfire when choosing the first-party Pydantic AI experience.
Pydantic AI defaults
Keep credentials, authenticated identity, clients, and configuration in typed dependencies and enforce permissions below the model layer.
Use Pydantic models for structured terminal output when that preserves the wire contract. Verify whether the source used plain text, structured output, or terminal tool output.
Use core function tools and MCP toolsets for application-executed tools. Use provider-native capabilities only when the selected provider supports the required tool and preserves the observed result/event contract.
Keep ordinary agents on core. Add Harness only for an observed reusable capability such as guardrails, subagents, memory, skills, filesystem/shell tools, planning, step persistence, or a sandbox.
Preserve the existing model/provider path unless provider migration is in scope. Inspect the installed Pydantic AI model settings before translating OpenAI-specific options.
Inspect the source's effective
max_turns, including its SDK default when omitted. Preserve that bound withUsageLimits.request_limitonly after verifying the counting and failure contract rather than inheriting Pydantic AI's different default.
Completion
Install and import the migrated project from a clean environment so its dependency files match the runtime. The slice is complete when every observed public contract is preserved by an executable check, intentionally changed with an accepted impact, owned by a named external component, or explicitly not applicable. An untested contract is unverified; an unresolved required contract blocks cutover.
Files
- ATTRIBUTION.mdAdded by AutoGineer901 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md6.9 KiB
- agents/openai.yaml317 B
- references/CONCEPT-MAPPING.md9.8 KiB
- references/VERIFICATION-AND-CUTOVER.md6.1 KiB
references/VERIFICATION-AND-CUTOVER.md
Verification and Cutover
Use this reference before changing a high-risk boundary or declaring a production migration complete.
Characterize the source
Capture the applicable behavior at stable boundaries:
accepted request/context and final output/error schema;
tool definitions, visibility, validation, side effects, retries, concurrency, and terminal-tool behavior;
handoff destinations, input filtering, active-agent changes, next-turn ownership, and guardrail scope;
manual history, session merge/storage, provider-side state, interruption, approval, and resume behavior;
raw, run-item, lifecycle, and public streaming events;
model settings, turn limits, usage, cancellation, and timeout behavior;
authentication, tenant, filesystem, process, network, secret, and sandbox boundaries;
traces, metrics, eval dimensions, queues, deployment, and service integrations.
Record a success trace and representative failure traces for the risks the selected path actually has. Do not invent requirements for unused SDK features.
Classify every observed contract
| Status | Evidence |
|---|---|
verified-equivalent | source and target preserve the same externally observable contract in executable checks |
verified-adapter | internal semantics differ, but a focused adapter preserves the public contract |
intentional-change | the difference and impact were explained and explicitly accepted |
external-owner | a named application or infrastructure component preserves it at a tested boundary |
not-applicable | the active source path does not provide or consume it |
unverified | evidence is incomplete; do not call it equivalent |
blocked | a required contract has no acceptable proved construction; do not cut over |
Matching class names, successful imports, a happy-path demo, and similar traces are insufficient.
Proportionate tests
For an ordinary stateless agent, focused boundary tests and a residual-risk note are enough. Use TestModel for tool/schema registration and FunctionModel when exact messages, tool calls, retries, or event order matter. Test tools as normal functions/services, including authorization and idempotency.
Add targeted integration tests when the slice uses:
a real provider family or OpenAI native tool;
local or hosted MCP;
databases, sessions, vector stores, sandboxes, filesystem/shell tools, queues, or webhooks;
public SSE, WebSocket, AG-UI, or another streaming adapter;
persistence or approval that must survive process restart.
For multi-agent paths, prove final-answer ownership, history passed to each agent, typed routing metadata, parent/child usage and limits, partial failure, cancellation, and event correlation. Do not silently give nested agents independent unlimited budgets.
For guardrails, exercise allow, block, replacement/retry where applicable, exceptions, and every agent/tool boundary that the source actually covered. A security policy must fail below the model layer even if a guardrail, tool filter, prompt, or approval record is bypassed.
For session and HITL paths, separately prove:
next-turn conversation continuity;
atomic append/merge behavior under concurrent writers when promised;
pending approval correlation and authenticated resume;
denial executes no protected effect;
approval executes the effect once with original trusted dependencies;
stale, foreign, unknown, and already-consumed call IDs fail closed;
crash recovery, replay, or fork semantics only when the source promised them.
For streaming, test the real consumer boundary for incremental delivery, event schema and order, correlation IDs, final completion, cancellation/disconnect, backpressure, early exit cleanup, and terminal errors. Model-level streaming does not prove the application is not buffering.
Port representative datasets to Pydantic Evals only when the source has evals or task quality is a release criterion. Compare task success, structured validity, tool trajectory constraints, latency/time to first event, requests/tokens/cost, retries, escalation, and unsafe attempts. Do not require identical prose unless wording is a public contract.
Cut over
Place the migrated implementation behind the existing framework-neutral boundary and route complete runs with a stable flag.
Shadow only read-only or sandboxed traffic. Redact sensitive comparison data.
Compare normalized outputs, trajectories, limits, side effects, and traces against predefined thresholds.
Canary writes only with server-side authorization, idempotency keys, and rollback controls.
Increase traffic after quality, latency, cost, safety, persistence, and operational thresholds pass.
Remove adapters and the
openai-agentsdependency only after repository search, dependency/entrypoint inspection, original tests, and production rollback criteria show no retained path needs them.
Avoid dual-running side-effectful agents unless every effect is dry-run, sandboxed, or deduplicated.
Completion checklist
[ ] Every observed contract has an evidence-backed status.
[ ] Public request, output, error, and event contracts pass.
[ ] Tool schemas, permissions, side effects, retries, and terminal behavior pass.
[ ] Handoff or delegation ownership and history behavior pass.
[ ] Session, continuation, approval, and recovery promises pass.
[ ] Security boundaries and real execution environments pass.
[ ] Focused unit, integration, type, and eval checks appropriate to the slice pass.
[ ] Observability and privacy choices are deliberate and traces are not treated as sole proof.
[ ] Transitional adapters have owners and removal criteria.
[ ] Dependency files and operational documentation match the new runtime.
Primary references: Pydantic AI testing, message history, deferred tools, durable execution, Pydantic Evals, and Logfire.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Pydantic
- Publisher
- Pydantic (Official)
- Source
- pydantic/skills · skills/migrating-openai-agents-sdk-to-pydantic-ai · commit 98f591c
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- pydantic/skills
AutoGineer is not affiliated with or endorsed by Pydantic or Pydantic.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download migrating-openai-agents-sdk-to-pydantic-ai.zip