Migrating Langchain 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 porting existing AI applications from the LangChain ecosystem to Pydantic AI. It emphasizes preserving application behavior over matching framework structures, advocating for a slice-based migration approach. The guide covers mapping core agent loops, handling complex state and persistence, and translating Deep Agents harness features into Pydantic AI primitives. It includes specific guidance on managing semantic gaps, verifying observability, and ensuring production readiness through characterization tests.
What it does
- Provides a step-by-step procedure for identifying and migrating functional slices of an application.
- Maps LangChain/LangGraph concepts to Pydantic AI primitives.
- Offers strategies for translating Deep Agents harness features like filesystem tools, subagents, and memory.
- Defines best practices for handling dependencies, typed invariants, and observability.
- Includes guidance on managing semantic differences and verifying parity through testing.
- Outlines the process for production cutover and verification.
When to use it
- When you need to migrate an existing LangChain or LangGraph application to Pydantic AI.
- When your application uses Deep Agents and requires a transition to Pydantic AI Harness.
- When you need to ensure behavioral parity during a framework migration.
- When you need to resolve semantic differences between LangChain and Pydantic AI implementations.
Advantages
- Focuses on behavioral preservation rather than superficial code matching.
- Provides a clear, risk-aware path for complex agentic systems.
- Includes specific mapping references for core loops and harness features.
- Encourages the use of typed dependencies for better reliability.
- Promotes a test-driven approach to ensure migration accuracy.
Usage examples
- “How do I migrate a simple LangChain agent to Pydantic AI?”
- The agent will guide you to identify the agent's tools and system prompt, then show you how to define a Pydantic AI Agent with typed dependencies and instructions, replacing the LangChain constructor.
- “How should I handle Deep Agents subagents in Pydantic AI?”
- The agent will explain how to map the subagent's filesystem, skills, and memory middleware to Pydantic AI Harness capabilities or custom application services.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/pydantic/migrating-langchain-to-pydantic-ai/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip migrating-langchain-to-pydantic-ai.zip -d .agents/skills
Documentation by Pydantic
Migrate LangChain, LangGraph, and Deep Agents to Pydantic AI
Preserve behavior, not framework shape. Migrate the smallest behaviorally complete slice and leave application infrastructure outside that slice unchanged. LangChain, LangGraph, and Deep Agents are one source ecosystem; Pydantic AI, pydantic_graph, and Pydantic AI Harness are the matching target ecosystem, and this skill maps across all of it.
Work from the running application
Read repository instructions, dependency files, tests, and the actual runtime entrypoints. Identify the installed LangChain, LangGraph, Deep Agents, Pydantic AI, and Harness versions.
Trace one representative request through prompts, retrieval, model and tool calls, state, persistence, interrupts, emitted events, tracing/metrics callbacks, and the public result. Inspect every caller and sibling endpoint that consumes the migrated component; a narrow implementation slice can still have several public contracts. Include keyword parameter names and the sync, async, callback, and streaming forms callers actually use. Record only contracts those paths actually use.
Run the cheapest useful baseline. When the migration surface is broad or unclear, search dependency files and source for
langchain,langgraph,langsmith, anddeepagents, then confirm findings against imports, factories, and call sites. Resolve wherecreate_deep_agentcomes from: the upstream package and a vendored copy that reproduces its contracts both count as Deep Agents.Classify the slice before choosing a target:
Chain or LCEL pipeline: keep deterministic retrieval and transformation in plain Python; use a Pydantic AI agent only where a model/tool loop adds value.
LangChain agent: normally use one reusable
pydantic_ai.Agentwith typed dependencies, tools, and outputs.Direct LangGraph workflow: use plain async Python for simple fixed control flow, or
pydantic_graphwhen explicit typed nodes and branching remain useful. Treat persistence as a separate design decision.Deep Agents harness:
create_deep_agentbundles file tools, shell execution, subagent delegation, summarization, skills, memory, permissions, prompt caching, and approval middleware on top of the LangChain agent loop, and a harness profile can add or hide more. Migrate the loop with the LangChain mappings, then map each bundled feature the slice actually uses to a Harness capability, a core primitive, or an application service with Deep Agents Mapping. Inventory implicit defaults the application code never mentions.Product runtime: retain queues, configured database backends, sandboxes, auth, schedulers, webhooks, tracing, and transport adapters unless the user placed them in scope. Extend an existing application seam before creating a parallel persistence or provider subsystem.
Add or preserve deterministic characterization tests, then migrate one vertical slice behind the existing public boundary.
Run the original tests and focused parity tests. Classify each observed contract by its evidence; never describe the migration as one-to-one merely because the happy path or trace shape looks similar.
Read Concept Mapping for the detected source features. Read Deep Agents Mapping whenever deepagents is in the slice. Read Semantic Gaps only for state, middleware, retries, approval, concurrency, streaming, or other behavior where similar-looking APIs may differ. Use Workaround Recipes after a concrete gap is identified, not as a mandatory checklist. Read Logfire Verification when adding observability, comparing source and target runs, or debugging a semantic difference. Read Verification and Cutover before a production cutover.
Explain semantic differences
When an observed source contract has no direct equivalent, explain it to the user before making a consequential design choice. State the source behavior, how the proposed Pydantic AI design differs, the user-visible or operational impact, and the available choices. Recommend one option and name its residual risk. Keep this proportional: do not turn ordinary import or naming changes into semantic warnings.
Do not stop at "unsupported." When nothing maps directly, recommend an existing core or Harness composition, a narrow adapter or application service, a new capability built from public primitives, or a core change, in that order of preference. Ask before choosing only when the options materially change behavior, architecture, public API, or scope.
Match rigor to risk
For a stateless chain or ordinary agent port, focused characterization tests and a short residual-risk note are enough. Do not require a semantic-gap register or durability exercise for behavior the source does not have.
For middleware, structured output transport, retrieval, tool retries, or streaming, probe the affected contract against the installed versions.
For checkpointed graphs, interrupts, approvals, durable execution, concurrent fan-out, or external side effects, create a migration ledger. Separate dependencies, messages, workflow state, checkpoint state, and long-term memory. Fit those owners into the repository's existing backend-selection and service interfaces where possible. Test restart, replay, correlation, authorization, and idempotency only to the extent the source promises them.
A
deepagentsdependency alone changes nothing. When the active slice callscreate_deep_agentor depends on its planning, filesystem, sandbox, skills, memory, subagent, permission, or deployment contracts, those are in-scope features with Harness or application owners, not a reason to stop. Files, sandboxes, permissions, subagents, and background work carry the same ledger and restart obligations as checkpointed graphs.
Pydantic AI defaults
Put authenticated identity, service clients, and configuration in typed dependencies, never model-chosen tool arguments.
Strengthen observed unstable seams, not the whole application: parameterize the agent's dependency and output types, and validate terminal choices, persisted workflow records, and framework adapters. Preserve stable public wire shapes and do not invent types for paths outside the migrated slice.
Preserve public request, response, error, and event shapes with a small adapter while callers migrate.
Keep retrieval, storage, provider, and transport integrations in place when they are outside the requested slice. Transitional LangChain integrations are acceptable when named and bounded.
Use Pydantic models for terminal structured output when that preserves the contract; retain an existing parser when changing the wire contract would expand the migration.
Do not force an
Agentonto deterministic LCEL orpydantic_graphonto everyStateGraph.Inspect the installed Pydantic AI API before choosing model classes, provider transports, hooks, streaming methods, or durable integrations.
Add
pydantic-ai-harnessonly for observed harness behavior: planning, workspace files, shell or sandboxed execution, Agent Skills, memory notebooks, repository context, model-directed subagents, model-agnostic compaction, tool-output limits, guardrails, spend limits, or step persistence. Add capabilities one at a time, import each from its owning public submodule, treatpydantic_ai_harness.experimental.*as version-sensitive, and run an import-and-construction smoke test in the target environment. Harness composes onto the core agent loop; it is not a second runtime and does not replace application infrastructure.When adding Pydantic AI, prefer a currently supported stable release. Use the newest compatible release unless that would expand the migration through an unrelated major/runtime upgrade; explain and pin any exception. Resolve the whole project from a clean environment and run an import probe because an existing environment can hide incompatible transitive versions. Prefer
pydantic-ai-slimwith only the required provider and integration extras when the dependency surface is bounded, and use the full distribution when its broader integrations are actually needed. Do not pin an older release merely to match a remembered example.If the source already uses LangSmith, Langfuse, or another observability system, do not replace it silently. Explain that Logfire is the first-party Pydantic AI integration and normally provides the most direct agent, model, tool, retry, error, usage, and timing experience. Contrast that with the continuity of retaining the current system, including its dashboards, alerts, evaluations, retention, and export pipeline; recommend a choice and obtain agreement before switching. Offer Logfire at application startup when no tracing system exists or the user chooses it, make content capture an explicit privacy decision, and keep executable contract tests as the authority for parity.
Completion
The slice is complete when every observed contract is either preserved by an executable check, intentionally changed by an accepted decision, or explicitly not applicable. An untested contract is unverified, not equivalent; an unresolved requested contract is unfinished work, not completion evidence. Constrain the slice or ask the user to accept the deferral. Remove LangChain, LangGraph, or Deep Agents dependencies only after no retained path needs them.
Files
- ATTRIBUTION.mdAdded by AutoGineer885 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md9.9 KiB
- agents/openai.yaml394 B
- references/CONCEPT-MAPPING.md16.2 KiB
- references/DEEP-AGENTS-MAPPING.md24.5 KiB
- references/LOGFIRE-VERIFICATION.md10.2 KiB
- references/SEMANTIC-GAPS.md21.6 KiB
- references/VERIFICATION-AND-CUTOVER.md12.3 KiB
- references/WORKAROUND-RECIPES.md18.0 KiB
references/VERIFICATION-AND-CUTOVER.md
Verification and Cutover
Use this reference before editing a production agent or declaring a migration complete.
Contents
Characterize the old system
Classify every claim
Build the test pyramid
Verify operational semantics
Cut over safely
Completion checklist
Characterize the old system
Capture the applicable behavior at stable boundaries; do not invent requirements for features the source path does not use:
accepted request and context schema;
final output and error schema;
tool names, descriptions, argument schemas, visibility, and side effects;
dynamic prompt/tool/model selection;
middleware/hook order;
state fields and reducer behavior;
message, checkpoint, store, thread, interrupt, and replay semantics;
stream modes and client-visible events;
usage, iteration, concurrency, timeout, and retry limits;
auth, tenant, filesystem, shell, network, and secret boundaries;
harness defaults the slice depends on: profile-resolved prompt, planning, backends, permissions, skills, memory, subagent stacks, and sandboxes;
traces, metrics, and eval dimensions;
deployment, queue, scheduler, and webhook contracts.
Record at least one success trace and representative failure traces for the risks the selected path actually has.
Classify every claim
Apply a status to each observed contract, not to the migration as a whole:
| Status | Required evidence |
|---|---|
verified-equivalent | Source and target preserve the same externally observable contract in executable checks against the target project's versions and boundaries. |
verified-adapter | Internal semantics differ, but an adapter preserves the public contract in executable checks. |
intentional-change | The difference and impact were explained and explicitly accepted by the user or owner. |
external-owner | A named application or infrastructure component preserves the contract, with evidence at that boundary. |
not-applicable | The observed source path does not provide or consume this behavior. |
unverified | The behavior was not exercised, the evidence is incomplete, or only a candidate design exists. Do not call it equivalent. |
blocked | A required contract has no acceptable proved construction. Do not cut over that slice. |
Trace similarity, successful imports, matching class names, a happy-path demo, and an author-side spike are not sufficient for verified-equivalent. Link each verified status to its test or boundary assertion and report every unverified, intentional-change, and blocked item to the user.
Build the test pyramid
Deterministic unit tests
Test tools as ordinary functions/services, including authorization and idempotency.
Use
TestModelfor schema/tool registration checks.Use
FunctionModelwhen exact requests, tool calls, retry, or failure behavior matters.Assert
ModelRequestParametersor captured run messages when tool schema and instructions are part of the contract.Run the repository's static checker across the migrated slice. When output inference loses a real union, parameterize
Agent[DepsT, OutputT]explicitly rather than weakening the owned boundary toAny.Round-trip persisted model messages and typed workflow records through their production serializer, and prove malformed records fail validation.
For dynamic instructions, test at least two dependency values and prove the emitted instructions change while secrets and authenticated identity remain absent from model-visible content.
Test both approval decisions: denial must not execute the protected tool; an approved resume must execute it exactly once with the original authenticated dependencies and correlation ID.
Test graph/application transitions without a live model.
Integration tests
Exercise each real provider family used in production with a minimal recorded or low-cost case.
Test MCP/server lifecycle and transport failure.
Test database, vector store, sandbox, filesystem, shell, queue, and webhook adapters at their real boundary.
Test streaming consumers against the application-owned event schema.
Test persistence across a real process restart when restart survival is promised.
Evals
Port representative LangSmith or custom datasets to pydantic_evals without changing prompts or graders at the same time. Compare:
task success and output validity;
tool choice and trajectory constraints;
citation/evidence quality;
latency and time to first event;
model requests, tokens, and cost;
retry, failure, and escalation rates;
unsafe or unauthorized attempts.
Do not require identical prose unless wording is a public contract. Require identical structured fields, safety boundaries, and side effects where they are contracts.
Verify operational semantics
Persistence and recovery
When the source promises them, prove separately:
conversation continuation;
workflow-state restoration;
approval correlation and resume;
replay/fork behavior;
pending-write or idempotency behavior;
crash recovery during a model call, tool call, and external write.
Pydantic AI message history proves only conversation continuity. Use a durable execution integration or application workflow persistence when the old system promised graph state, pending writes, replay/fork, effect deduplication, or process-restart recovery.
Concurrency and limits
When the slice fans out, accepts concurrent requests for one thread, or shares limits, test caps, cancellation, timeout, rate-limit backoff, partial child failure, deterministic result aggregation, and duplicate work before persistence conflicts. Verify that parent and child agents do not silently receive separate unlimited budgets.
Security
Test the security boundaries the slice exposes. Examples include cross-tenant access, path traversal for filesystem tools, SSRF for URL-fetching tools, secret exposure, and approval bypass. For deferred approval, forge a foreign, unknown, or already-consumed tool-call ID and reject it at an authenticated server-side correlation boundary. Enforce failures below the model layer.
Harness features
When the source is a Deep Agents harness and the target adds Harness capabilities, test each capability at the contract the source promised:
Files and sandboxes: traversal, absolute paths, symlinks, media and binary data, output bounds, environment leakage, timeout, reconnect, egress, and cleanup failure. For permissions, test operation classes, first-match order, unmatched calls, allow, deny, interrupt, route-relative paths, and child overrides.
Skills and repository context: discovery layout, precedence, catalog names and descriptions, deferred loading, snapshot or rescan behavior, runtime writes, bundled resources and scripts, walk-up boundaries, and nested traversal.
Plans and memory: create or replace semantics, status transitions, persistence, concurrent writers, visibility on the next request, namespace isolation, retention, deletion, and whether the next run observes a write after a process restart.
Subagents: context isolation, explicit state transfer, model and tool selection, parent and child budgets, timeout, cancellation, partial failure, result shape, and streamed identity. For background children, add idempotent start, scoped list and check, task-ID authorization, update and cancel races, duplicate delivery, lost workers, and retry ceilings.
Interpreters and Code Mode: generated-code limits, state and reset scope, tool and subagent bridges, schema conversion, approval enforcement, OS access, timeouts, and resource-limit failures.
Context offload and compaction: thresholds, lossy versus lossless paths, store failure, model-visible receipts, read-back bounds, store lifetime, serialization, restoration of text and media, and tool-pair validity after compaction.
Exercise the complete Agent(..., capabilities=[...]) composition in the target interpreter once; a passing import is not a passing composition.
Streaming
Check the event behavior promised by the public stream: event order, relevant correlation IDs, partial text, final-result emission, and any documented reconnect, backpressure, or cancellation behavior. Prove incremental delivery with a real client; model-level time to first chunk does not detect application buffering. If synchronous request construction, retrieval, or tools can block the event loop, preserve any source worker/thread boundary or use a native async path. When responsiveness before the first chunk is an observed contract, test that unrelated event-loop work still advances; do not move thread-affine clients across threads blindly. run_stream may treat the first valid final output as terminal; use run(event_stream_handler=...), run_stream_events, or iter when all tool events must complete. Test early consumer exit, cleanup, and late producer errors.
Observability
If the source uses another observability system, explain the retain, temporary dual-export, and switch-to-Logfire choices before editing it. Recommend Logfire for its first-party Pydantic AI integration, but preserve the existing system unless the user accepts the wider operational migration. A switch includes dashboards, alerts, evaluations, trace ingestion, privacy/retention controls, credentials, and documentation—not only the runtime SDK. When the user chooses Logfire, configure it at application startup and make content capture an explicit privacy decision. An installed SDK or outer request/graph span does not prove that a nested Pydantic AI model call, tokens, errors, usage, or tool calls remain observable. Probe the active success and failure lifecycle at the model boundary, including parent correlation and existing application metrics. Compare normalized source and target facts rather than raw telemetry schemas. Sampling, missing instrumentation, and disabled content limit what a trace can substantiate. Follow Logfire-Assisted Migration Verification; traces complement rather than replace contract tests.
Cut over safely
Add a framework-neutral adapter and route whole runs by a stable flag.
Shadow read-only traffic first. Redact sensitive data in comparison logs.
Compare outputs, trajectories, limits, and traces automatically.
Canary low-risk write traffic with idempotency keys and rollback controls.
Increase traffic only after predefined quality, latency, cost, and safety thresholds hold.
Stop new LangChain and Deep Agents feature work in the migrated slice.
Remove
tool_from_langchain,LangChainToolset, message converters, and dual observability after the rollback window.Remove LangChain, LangGraph, and Deep Agents dependencies only after the strict inventory has no errors, a repository-wide text search is clean or explained, dependency and entrypoint graphs show no runtime use, notebooks/config/plugin registries have been checked, and the original runtime tests still pass.
Avoid dual-running side-effectful agents unless tools are in dry-run mode or every external write is deduplicated.
Completion checklist
[ ] Every observed contract has an evidence-backed status; a low-risk slice may use a concise residual-risk note instead of a ledger.
[ ] Public request, response, error, and event contracts pass.
[ ] Tool schemas, authorization, side effects, retries, and approval pass.
[ ] State, history, persistence, resume, and recovery promises pass.
[ ] Streaming and cancellation pass with real clients.
[ ] Unit, integration, and eval thresholds pass.
[ ] When Logfire is enabled, its privacy settings are deliberate and traces correlate the applicable app, agent, model, tool, and subagent boundaries without being treated as sole parity proof.
[ ] No hidden LangChain callbacks, globals, messages,
RunnableConfig, Deep Agents backend, or profile assumptions remain.[ ] Transitional bridges have been removed or have owners and removal dates.
[ ] Dependency files and operational documentation match the new runtime.
Primary references: Pydantic AI testing, Pydantic Evals, Logfire integration, and durable execution.
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-langchain-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.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download migrating-langchain-to-pydantic-ai.zip