Migrating an Agent-CLI Harness to Pydantic AI or OpenAI Agents SDK

Which Python framework should you pick when migrating an existing interactive agent-CLI harness (skills, hooks, AGENTS.md) to a framework? A decision guide with the per-artifact mapping for both SDKs.

Research date: Aug 4, 2026. Every factual claim is cited inline to an official source (GitHub READMEs or official docs). This article answers one question: if you already run an interactive agent-CLI harness — skills, hooks, AGENTS.md — and you want to move it into a Python agent framework, which SDK should you pick, Pydantic AI or OpenAI Agents SDK? Companion note: shareable-agent-harness.md documents the four CLI harnesses and why skills/hooks/context files are not a portable ABI.


TL;DR

For migrating an existing agent-CLI harness, the deciding factor is how much of the harness must physically execute files in a workspace:

  • Choose Pydantic AI when the harness is instruction-shaped — SKILL.md instruction loading, AGENTS.md/CLAUDE.md auto-loading, and fine-grained lifecycle hooks — because all three are first-class capabilities that work on any model with no sandbox runtime. This is the lower-friction, more faithful migration of a typical CLI harness.
  • Choose OpenAI Agents SDK when the harness must execute — skills with bundled scripts/resources, or an isolated filesystem workspace — because its sandbox Skills capability materializes skill files into a real sandbox filesystem. This only works inside the beta SandboxAgent layer.

Neither SDK implements the CLI-native hook contracts (Claude Code JSON/command hooks, Gemini CLI JSON stdin/stdout hooks, OpenCode plugin hooks). A thin adapter remains either way, exactly as the companion note concludes for cross-CLI sharing.


1. What you are migrating

An interactive agent-CLI harness (Claude Code, Codex CLI, OpenCode, Gemini CLI) consists of artifacts the CLI reads to steer the agent:

ArtifactWhat it isExamples of where it lives
SkillsSKILL.md packages: name, description, Markdown instructions, optional bundled references/, assets/, scripts/.claude/skills/, .agents/skills/, .opencode/skills/, Gemini CLI extensions
HooksDeterministic event callbacks (session start/end, before/after tool, compaction) with client-specific contractsClaude Code JSON/command hooks, Gemini CLI JSON-over-stdio, OpenCode plugins
Context filesStanding repository instructions read at session startAGENTS.md, CLAUDE.md
Tools / MCPFunction tools and MCP servers the agent can callMCP server configs

The migration question is: for each artifact, what does the target SDK consume as-is, what must be rewritten, and what is lost? The per-artifact mapping below is the whole analysis.


2. AGENTS.md / repository context

Pydantic AI — native, closest to a drop-in. The Repo Context capability in pydantic-ai-harness “auto-loads repo context — CLAUDE.md/AGENTS.md and repository structure — so the agent starts a run already oriented in the project.” (https://pydantic.dev/docs/ai/harness/) Your existing AGENTS.md/CLAUDE.md files keep working as-is; the framework injects them automatically.

OpenAI Agents SDK — none native, bring your own. The runtime does not read AGENTS.md. To preserve the behavior you must (a) stage the repo into the sandbox via a Manifest entry (GitRepo or LocalDir) and (b) restate standing rules in the agent’s instructions (appended after the SDK sandbox base prompt) or replace the base prompt via base_instructions. (https://openai.github.io/openai-agents-python/sandbox/guide/)

Migration cost: Pydantic AI — near zero, keep the files. OpenAI — a rewrite of the rules into Python instructions, plus a Manifest for the workspace.


3. Skills (SKILL.md)

Both read the portable Agent Skills SKILL.md format; the difference is depth.

Pydantic AI — Skills capability, instructions only. Add pydantic-ai-harness[skills], point Skills('.agents/skills') at your existing skill library. At construction it scans immediate child directories, validates each SKILL.md, and creates one deferred capability per skill: the model sees name + description, then calls load_capability for the body. include/exclude filter the catalog. (https://pydantic.dev/docs/ai/harness/skills/)

Two migration caveats:

  • Bundled files are not loaded. references/, assets/, and scripts/ are not read or executed, and behavioral frontmatter fields (hooks, tools, shell, model, …) are accepted but not implemented (a UserWarning is emitted).
  • No auto-discovery. Skills does not search .agents, .claude, or your home directory — you must pass each library path explicitly.

OpenAI Agents SDK — sandbox Skills capability, filesystem-grounded. On SandboxAgent (beta), Skills “indexes and materializes skills into the sandbox for you” — skill files physically land in the workspace at skills_path (default .agents). Sources: lazy_from=LocalDirLazySkillSource(...) (large local dirs, model loads on demand), from_=LocalDir(...) (stage up front), or from_=GitRepo(repo=..., ref=...). Because files exist in the sandbox, bundled scripts/ and assets/ are usable by the filesystem and shell capabilities. (https://openai.github.io/openai-agents-python/sandbox/guide/)

Migration cost:

Skills aspectPydantic AIOpenAI Agents SDK
SKILL.md instructionsReused as-is (deferred capability)Reused as-is (materialized into sandbox)
Bundled scripts/assetsLost — not loadedAvailable in the sandbox workspace
Behavioral fields (hooks/tools/shell)Ignored (warning)N/A — skills are files, not interpreted
Runtime requirementNone (any model, no sandbox)SandboxAgent + a sandbox client (beta)

If your skills are pure instruction packages, Pydantic AI is the faithful migration. If your skills embed scripts your agents must run, only the OpenAI sandbox approach preserves them.


4. Hooks

Pydantic AI — a full lifecycle event bus. The Hooks capability registers callbacks via @hooks.on.<event> decorators (or constructor kwargs), with per-hook timeout, tool-name filtering on tool hooks, middleware-style wrap_* hooks, and raise-to-propagate / return-to-recover error hooks. (https://ai.pydantic.dev/hooks)

The CLI hook events map onto Pydantic events:

CLI harness hookPydantic AI event
Session start / before promptbefore_run
Session endafter_run
Before / after toolbefore_tool_execute / after_tool_execute
Tool argument validationbefore_tool_validate / after_tool_validate
Context compactionCompaction capability (harness) or prepare_tools
Streamed outputrun_event_stream / per-event event

OpenAI Agents SDK — a minimal observer API. Subclass RunHooks (run-wide, set on the runner) or AgentHooks (per-agent, set via agent.hooks) and override on_llm_start/on_llm_end, on_agent_start/on_agent_end, on_handoff, on_tool_start/on_tool_end. (https://openai.github.io/openai-agents-python/ref/lifecycle/)

Migration cost: Both require writing an adapter from your CLI’s hook contract (Claude JSON/command hooks, Gemini JSON-over-stdio, OpenCode plugin hooks) to the SDK’s Python callbacks — that contract is not portable, per the companion note. But Pydantic AI gives you the granularity to express most CLI behaviors (validation, middleware, retry/failure semantics, tool filtering) without fighting the API; OpenAI’s hooks are sufficient for observability-style interception only.


5. What is not in scope / secondary considerations

These matter for the migration decision but are not the deciding factors for the harness question:

  • Tools and MCP: both consume function tools and MCP servers (Pydantic MCP capability; OpenAI MCP server tools). Portable, no major cost.
  • Memory / sessions: OpenAI has ready-made session backends (SQLAlchemy, SQLite, Redis, MongoDB, encrypted). Pydantic offers comparable building blocks via harness capabilities (Step Persistence, Memory) that you assemble.
  • Model support: if the harness must stay provider-agnostic (as the CLIs are), Pydantic AI’s native multi-provider support is a real advantage over OpenAI’s adapter-based third-party models. (https://ai.pydantic.dev/models/overview)
  • Type safety: Pydantic AI’s Agent[Deps, Output] generics carry types through the run; OpenAI’s tool schemas are Pydantic-based but the agent is not generic in the same way.

6. Decision

Answer in order:

  1. Does the harness depend on executing skill scripts or assets in a real filesystem?
    • Yes → OpenAI Agents SDK (SandboxAgent + sandbox Skills), accepting the beta sandbox layer as the dependency.
    • No → continue.
  2. Do you need AGENTS.md/CLAUDE.md auto-loading and fine-grained hooks?
    • Yes → Pydantic AI (Repo Context + Hooks + Skills capabilities), which preserves both with no sandbox.
  3. Tie-breakers: provider-agnostic models and richer hook control favor Pydantic AI; pre-built session backends, an OpenAI-first stack, and workspace isolation favor OpenAI Agents SDK.

Either way, budget for a hook adapter: neither SDK speaks Claude Code, Gemini CLI, or OpenCode hook contracts, so that shim is the one piece of the harness that always needs rewriting.


References

Companions