migrating-openai-agents-sdk-to-pydantic-ai

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Migrate OpenAI Agents SDK to Pydantic AI

将 OpenAI Agents SDK 迁移到 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 SDK 的对象结构。迁移最小但完整的 runtime 切片,并保持应用基础设施不变。

Work from the running application

基于运行中的应用开展工作

  1. Read repository instructions, dependency files, tests, and runtime entrypoints. Record the installed
    openai-agents
    , Pydantic AI, and Harness versions.
  2. Trace one representative
    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.
  3. Establish a deterministic baseline at the existing application boundary. Record only behavior the active path uses.
  4. Classify the slice before designing it:
    • Ordinary agent: use one reusable Pydantic AI
      Agent
      with typed dependencies, tools, and outputs.
    • Manager with specialists: use explicit application orchestration, an agent tool, or Harness
      SubAgents
      according 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
      Coder
      and 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.
  5. 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
.
  1. 阅读仓库说明、依赖文件、测试和运行时入口点。记录已安装的
    openai-agents
    、Pydantic AI 和 Harness 版本。
  2. 追踪一次具有代表性的
    Runner.run
    、
    run_sync
    或
    run_streamed
    调用,贯穿 instructions、context、model settings、tools、handoffs、guardrails、session state、approvals、events、tracing 和 public result。检查消费
    final_output
    、
    last_agent
    、
    new_items
    、
    to_input_list()
    、interruptions 或 streamed events 的调用方。
  3. 在现有应用边界建立确定性基线。仅记录实际执行路径所使用的行为。
  4. 在设计之前对切片进行分类:
    • 普通 Agent: 使用一个可复用的 Pydantic AI
      Agent
      ,配合类型化 dependencies、tools 和 outputs。
    • Manager 与专家 Agent: 根据谁必须负责最终响应,选择显式的应用编排、agent tool 或 Harness
      SubAgents
      。
    • Handoff 工作流: 首先判断切换 active agent、其 instructions 和 next-turn owner 是否会被调用方观察到。嵌套的 agent tool 不是 handoff。
    • Sandbox 或 coding Agent: 评估 Harness
      Coder
      及其组件能力。另行选择执行环境;shell allowlist 不等同于隔离。
    • Realtime 或 voice 路径: 使用 Pydantic AI realtime agents,将 transport、interruption、audio 和 live-session 行为作为单独的迁移切片处理。
    • 产品 runtime: 保留 authentication、storage、queues、deployment 和 service integrations,除非明确将其纳入范围。
  5. 添加或保留特征化测试,在现有 public boundary 之后迁移一个垂直切片,并运行原有测试和聚焦的 parity 测试。
阅读 Concept Mapping,了解已找到的源功能。在修改 persistence、handoffs、approval、streaming、security 或 production traffic 之前,以及在宣布完成或移除
openai-agents
之前,阅读 Verification and Cutover。

Stop at semantic gates

在语义关卡处止步

  • Context:
    RunContextWrapper.context
    is trusted application state and normally becomes typed
    deps
    . Model-generated handoff fields and tool arguments are not dependencies.
  • Handoffs: OpenAI handoffs replace the active agent inside one run and expose
    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.
  • Conversation state: distinguish manual
    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.
  • 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, 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 completion:
    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.
  • 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()
    , 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.
  • 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.
  • Context:
    RunContextWrapper.context
    是受信任的应用状态,通常会转换为类型化的
    deps
    。由模型生成的 handoff 字段和 tool 参数不属于 dependencies。
  • Handoffs: OpenAI handoffs 会在一次 run 内替换 active agent,并通过
    last_agent
    暴露给 continuation。Pydantic AI agent delegation 通常通过 tool call 返回;要保留转移语义,应使用显式的应用路由,或将有意变更记录下来。
  • Conversation state: 应区分手动
    to_input_list()
    history、SDK
    Session
    storage、OpenAI
    conversation_id
    、OpenAI
    previous_response_id
    ,以及已序列化的 interrupted
    RunState
    。Pydantic AI message history、provider-side continuation、Harness step persistence 和 durable execution 解决的是不同问题。
  • Guardrails: 保留被检查的边界、是否在工作开始前阻断、失败形态、替换行为和执行顺序。OpenAI input guardrails 默认可能并行运行,因此 tripwire 触发时,模型工作或 tool 副作用可能已经开始。
  • Approval: OpenAI HITL 会恢复已序列化的
    RunState
    。当同一次调用期间即可获得决策时,使用
    HandleDeferredToolCalls
    ,使 Pydantic AI run 能够内联继续。若 run 必须先结束,则将
    DeferredToolRequests
    包含在
    output_type
    中,然后持久化 messages 和完整请求——或持久化等效的 pending-action record,其中包含 category、经验证的 arguments 和 metadata——再使用
    DeferredToolResults
    恢复。必须在受保护的 tools 内部重新授权;approval 不等于 authorization。
  • Tool completion:
    tool_use_behavior
    可以使普通 tool result 成为终止结果。在 Pydantic AI 中,应将成功的终止操作建模为 output function 或
    ToolOutput
    ;不要通过抛出异常将成功值从 tool 中传出。
  • Streaming: 原始 Responses API events、run-item events、lifecycle events、output deltas 和 final completion 是彼此独立的契约。当完整 agent loop 必须完成时,使用
    run(event_stream_handler=...)
    、
    run_stream_events()
    或
    iter()
    。仅当提交首个匹配 output 并跳过后续 tool calls 仍能保持源契约时,才使用
    run_stream()
    。将所选接口适配到 public schema。
  • Tracing: OpenAI tracing 和 Pydantic AI 的 OpenTelemetry instrumentation 是不同的运维产品。除非用户接受更大范围的迁移,否则应保留现有 telemetry;如果选择 Pydantic AI 第一方体验,推荐使用 Logfire。

Pydantic AI defaults

Pydantic AI 默认设置

  • 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 with
    UsageLimits.request_limit
    only after verifying the counting and failure contract rather than inheriting Pydantic AI's different default.
  • 将凭据、已认证身份、客户端和配置放入类型化 dependencies,并在 model layer 之下强制执行权限。
  • 当这样做能够保持 wire contract 时,使用 Pydantic models 生成结构化终止输出。确认源实现使用的是纯文本、结构化输出还是 terminal tool output。
  • 使用 core function tools 和 MCP toolsets 执行应用侧 tools。仅当所选 provider 支持所需 tool,并且能够保持已观察到的 result/event contract 时,才使用 provider-native capabilities。
  • 普通 agents 应保留在 core 上。仅在确实观察到可复用能力时才引入 Harness,例如 guardrails、subagents、memory、skills、filesystem/shell tools、planning、step persistence 或 sandbox。
  • 除非 provider migration 明确纳入范围,否则保留现有 model/provider 路径。转换 OpenAI-specific options 之前,先检查已安装的 Pydantic AI model settings。
  • 检查源实现生效的
    max_turns
    ,包括未显式设置时的 SDK 默认值。只有在验证计数方式和失败契约之后,才使用
    UsageLimits.request_limit
    保留该上限,而不是直接沿用 Pydantic AI 不同的默认值。

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.
从干净环境安装并导入迁移后的项目,确保依赖文件与 runtime 一致。只有当每个已观察到的 public contract 都满足以下条件之一时,该切片才算完成:由可执行检查证明行为得到保留;有意变更且影响已获接受;由指定的外部组件负责;或明确不适用。未经测试的 contract 属于未验证;任何尚未解决的必需 contract 都会阻止 cutover。