npx skills add ...
npx skills add pydantic/skills --skill migrating-openai-agents-sdk-to-pydantic-ai
Migrate Python OpenAI Agents SDK applications to Pydantic AI and, when warranted, Pydantic AI Harness. Use for `agents.Agent`, `Runner`, function tools, handoffs, guardrails, sessions, human approval, streaming, or `SandboxAgent`. Do not use for applications built directly on the OpenAI Responses API without the Agents SDK runtime.
npx skills add pydantic/skills --skill migrating-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.
openai-agents, Pydantic AI, and Harness versions.Runner.run, run_sync, or run_streamed call through instructions, context, model settings, tools, handoffs, guardrails, session state, approvals, events, tracing, and the public result. Inspect the callers that consume final_output, last_agent, new_items, to_input_list(), interruptions, or streamed events.Agent with typed dependencies, tools, and outputs.SubAgents according to who must own the final response.Coder and its component capabilities. Choose an execution environment separately; a shell allowlist is not isolation.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.
RunContextWrapper.context is trusted application state and normally becomes typed deps. Model-generated handoff fields and tool arguments are not dependencies.last_agent for continuation. Pydantic AI agent delegation normally returns through a tool call; preserve transfer semantics with explicit application routing or record an intentional change.to_input_list() history, SDK Session storage, OpenAI conversation_id, OpenAI previous_response_id, and a serialized interrupted RunState. Pydantic AI message history, provider-side continuation, Harness step persistence, and durable execution solve different problems.RunState. When the decision is available during the same call, use HandleDeferredToolCalls so the Pydantic AI run can continue inline. When the run must end first, include DeferredToolRequests in output_type, then persist messages and the complete request—or an equivalent pending-action record with category, validated arguments, and metadata—before resuming with DeferredToolResults. Re-authorize inside protected tools; approval is not authorization.tool_use_behavior can make an ordinary tool result terminal. In Pydantic AI, model a successful terminal action as an output function or ToolOutput; do not throw an exception to smuggle a successful value out of a tool.run(event_stream_handler=...), run_stream_events(), or iter() when the full agent loop must complete. Use run_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.max_turns, including its SDK default when omitted. Preserve that bound with UsageLimits.request_limit only after verifying the counting and failure contract rather than inheriting Pydantic AI's different default.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.