Generated banner for Migrating Langchain To Pydantic AI
Generated logo for Migrating Langchain To Pydantic AI

Migrating Langchain To Pydantic AI

PydanticOfficialPublished by Pydantic

  • Skill
  • Workflow
  • Software development
  • MIT
  • No issues found

From the author

Migrate Python LangChain, LangGraph, or Deep Agents applications to Pydantic AI and, when the source uses harness features, Pydantic AI Harness. Use for LangChain agents, chains, LCEL, direct LangGraph graphs, persistence, interrupts, streaming, and `create_deep_agent` projects with planning, filesystem or sandbox backends, skills, memory, subagents, permissions, approvals, or Deep Agents Code hosts.
— the description by Pydantic

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

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/pydantic/migrating-langchain-to-pydantic-ai/download
  2. Unzip 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

  1. Read repository instructions, dependency files, tests, and the actual runtime entrypoints. Identify the installed LangChain, LangGraph, Deep Agents, Pydantic AI, and Harness versions.

  2. 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.

  3. Run the cheapest useful baseline. When the migration surface is broad or unclear, search dependency files and source for langchain, langgraph, langsmith, and deepagents, then confirm findings against imports, factories, and call sites. Resolve where create_deep_agent comes from: the upstream package and a vendored copy that reproduces its contracts both count as Deep Agents.

  4. 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.Agent with typed dependencies, tools, and outputs.

    • Direct LangGraph workflow: use plain async Python for simple fixed control flow, or pydantic_graph when explicit typed nodes and branching remain useful. Treat persistence as a separate design decision.

    • Deep Agents harness: create_deep_agent bundles 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.

  5. Add or preserve deterministic characterization tests, then migrate one vertical slice behind the existing public boundary.

  6. 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 deepagents dependency alone changes nothing. When the active slice calls create_deep_agent or 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 Agent onto deterministic LCEL or pydantic_graph onto every StateGraph.

  • Inspect the installed Pydantic AI API before choosing model classes, provider transports, hooks, streaming methods, or durable integrations.

  • Add pydantic-ai-harness only 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, treat pydantic_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-slim with 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

references/LOGFIRE-VERIFICATION.md

Logfire-Assisted Migration Verification

Use Logfire to expose what the migrated Pydantic AI application actually did. Treat it as diagnostic and corroborating evidence, not as proof that two frameworks have identical semantics.

Contents

  • Choose with the user

  • Instrument deliberately

  • Compare source and target runs

  • Observe streaming at both boundaries

  • Protect sensitive content

  • Test without exporting

  • Know what traces cannot prove

Choose with the user

When the source already has observability, present the decision before changing it. Recommend Logfire as the first-party Pydantic AI experience, but do not treat that recommendation as authorization to replace an established system.

ChoiceWhen it fitsCost or residual
retain the existing systemcontinuity and a narrow agent-runtime migration matter mostprove that nested Pydantic AI model/tool lifecycles remain visible; an outer framework span is insufficient
add Logfire temporarily alongside itsanitized shadow comparison or migration debugging justifies dual telemetryduplicate export, privacy, sampling, cost, and trace-correlation concerns; set a removal condition
switch to Logfirethe user wants native Pydantic AI instrumentation and accepts an observability migrationmigrate or retire dashboards, alerts, evaluations, trace ingestion, retention/privacy controls, credentials, and operational documentation

Explain which option you recommend, why it fits the application, what will change for operators, and what remains unverified. If observability was not placed in scope, retain it and offer the recommendation rather than expanding the migration.

Instrument deliberately

Configure Logfire during application startup, before constructing or running agents, and install Pydantic AI instrumentation once:

import logfire

logfire.configure()
logfire.instrument_pydantic_ai(
    include_content=False,
    include_binary_content=False,
)

Name reusable agents so their runs are distinguishable. Instrument a specific agent instead of all agents when the application has a narrower trace or privacy boundary. Inspect the installed logfire and pydantic_ai versions before passing instrumentation settings: telemetry data-format versions evolve independently of the Pydantic AI package, and their event roles and attributes can differ.

The default instrumentation can expose agent runs, model requests, tool calls, retries, errors, token usage, and timing. Add small application spans around boundaries that Pydantic AI does not own, such as retrieval, persistence, queues, approval records, public streaming, and external writes. Reuse the application's request, thread, tenant, and idempotency correlation identifiers as safe attributes; do not put secrets in them.

Inventory the source model/tool callback lifecycle and application metrics before replacing it. Keeping a LangSmith, Langfuse, or other callback on an outer LangGraph node does not automatically instrument a nested Pydantic AI call. Preserve the existing model/tool observations through a tested adapter or make an explicit observability change; verify success, token, completion, and error paths plus parent correlation.

Do not add one span per token. Prefer a bounded set of spans and metrics: first event, terminal event, event counts, queue delay, cancellation, and failure.

Compare source and target runs

During a shadow or replay comparison:

  1. Run the same sanitized input, dependencies, model settings, and deterministic fixtures through the source and target behind the same application boundary.

  2. Send both traces to the same OpenTelemetry backend when practical. LangChain and LangGraph can export LangSmith OpenTelemetry traces to Logfire; set LANGSMITH_OTEL_ENABLED=true and LANGSMITH_TRACING=true before importing those frameworks. Set LANGSMITH_OTEL_ONLY=true only when intentionally sending exclusively through OpenTelemetry rather than also retaining LangSmith export. Keep source and target trace namespaces distinct.

  3. Normalize comparable facts instead of diffing raw spans. Compare model-request count, tool calls and their causal relationships, safe arguments and results, retries, errors, usage, latency, model-visible messages when allowed, and application boundary events. Use application sequence IDs or executable assertions—not raw span arrival order—when tool order is a contract.

  4. Investigate every unexplained difference. A trace that merely looks similar is not equivalence evidence.

  5. Link a validated claim to the executable test that establishes it and use the trace to explain the trajectory.

Do not dual-run side-effectful agents unless tools are dry-run, sandboxed, or protected by durable idempotency keys. Observing a single write does not prove exactly-once behavior.

Observe streaming at both boundaries

Keep these measurements separate:

  • Instrumented model-call boundary: Pydantic AI can record the time from issuing the streaming request until the wrapped response surfaces its first chunk. This includes transport and client-SDK behavior; it is not provider-internal timing.

  • Application boundary: measure when the API, SSE, or WebSocket consumer receives its first public event and its terminal event.

Model time to first chunk does not prove client time to first event. A service can buffer an entire agent run after the model begins streaming. Test the public client contract for:

  • exact event schema and order;

  • incremental delivery rather than post-run buffering;

  • tool, retry, partial-output, final-result, and terminal-error events that the source exposes;

  • correlation identifiers and usage placement;

  • disconnect and cancellation propagation;

  • backpressure and bounded buffering;

  • reconnect or resume behavior, when promised;

  • cleanup and late producer errors after an early consumer exit.

Choose the Pydantic AI streaming API from the required lifecycle. run_stream() may stop at the first matching final output. Use run(event_stream_handler=...), run_stream_events(), or iter() when the contract requires complete tool execution or lower-level event control. When handling raw events, assemble both initial part events and later deltas. A Logfire trace can reveal the resulting trajectory, but only a real client test proves delivery behavior.

Protect sensitive content

Pydantic AI instrumentation includes prompts, completions, tool arguments, and tool results by default. That data may contain personal, proprietary, credential, or tenant information.

  • Prefer InstrumentationSettings(include_content=False) when raw content is unnecessary or unsafe. Structural telemetry remains useful.

  • Do not assume generic scrubbing makes LLM content safe. Logfire deliberately does not apply generic regex scrubbing to free-form LLM message attributes because it would be both noisy and incomplete. Define organization-specific controls and retention rules before enabling content capture.

  • Avoid full HTTPX header/body capture as a default. It is a temporary diagnostic escalation that can expose provider authorization and raw payloads; Bedrock and other non-HTTPX transports need separate treatment.

  • Sanitize shadow inputs and comparison attributes. Keep authenticated identity and secrets out of model-visible content and trace attributes.

State the privacy choice and its consequence: with content disabled, traces cannot substantiate prompt, argument, or output equivalence.

Test without exporting

Use Logfire's in-memory test exporter or Pytest capfire fixture to assert a small stable set of spans and attributes without sending telemetry to a remote project. Test that important application spans correlate with the agent run and that failures/cancellation are observable. Avoid full raw-trace snapshots as the only assertion; telemetry schemas change and raw traces include incidental data.

For short-lived commands, workers, or tests, flush telemetry at shutdown rather than on every request. Sampling can omit spans. SDK tail sampling is process-local and can fragment a distributed trace; use collector-side tail sampling when the entire distributed trace must share a decision. Never use sampled production traces as exhaustive parity evidence.

Instrument every service participating in the tested path and verify trace-context propagation across HTTP, queues, workers, and detached tasks. An application-created background task can outlive its request span or lose its parent; retain a safe business correlation ID and do not treat a broken trace tree as proof that work did not happen. Likewise, cancellation can leave incomplete telemetry, so resource and side-effect assertions remain authoritative.

Know what traces cannot prove

Logfire can help demonstrate that an exercised run used the expected model, tools, retry path, observed token usage, and timing. It cannot by itself prove:

  • deterministic output equivalence from a nondeterministic model;

  • public streaming delivery, backpressure, reconnect, or cancellation;

  • checkpoint, fork, replay, or process-restart semantics;

  • authorization or tenant isolation;

  • exactly-once external side effects;

  • behavior that was not instrumented or was removed by sampling.

Use deterministic characterization tests, provider integration tests, real clients, persistence/restart probes, database and side-effect assertions, and security tests for those claims. Report missing telemetry as missing evidence, not a passing result.

Primary references: Pydantic AI with Logfire, Pydantic AI instrumentation settings, LangChain and LangGraph with Logfire, Pydantic AI streaming, Logfire scrubbing, Logfire sampling, and Logfire testing.

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 or Pydantic.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download migrating-langchain-to-pydantic-ai.zip