langchain-upgrade-migration

Migrate a LangChain 0.3.x Python codebase to LangChain 1.0 / LangGraph 1.0 without breaking production — named breaking changes, codemod patterns, and a phased rollout. Use when upgrading LangChain or LangGraph from 0.2 or 0.3 to 1.0, when hitting ImportError after an upgrade, or when preparing a migration PR. Trigger with "langchain 1.0 migration", "langchain upgrade", "LLMChain removed", "initialize_agent removed", "ConversationBufferMemory removed", "astream_log deprecated", "langchain-anthropic 1.0".

claude-codecodex
5 Tools
langchain-py-pack Plugin
saas packs Category

Allowed Tools

ReadWriteEditGrepBash(python:*)

Provided by Plugin

langchain-py-pack

Claude Code skill pack for LangChain 1.0 + LangGraph 1.0 (Python) - 34 skills covering chains, agents, RAG, middleware, checkpointing, HITL, streaming, and production patterns

saas packs v2.0.0
View Plugin

Installation

This skill is included in the langchain-py-pack plugin:

/plugin install langchain-py-pack@claude-code-plugins-plus

Click to copy

Instructions

LangChain 1.0 Upgrade Migration (Python)

Overview

The first deploy after pip install -U langchain crashes on import with:


ImportError: cannot import name 'ChatOpenAI' from 'langchain.chat_models'

Fix the import, restart, and the next error lands:


ImportError: cannot import name 'LLMChain' from 'langchain.chains'
AttributeError: module 'langchain.agents' has no attribute 'initialize_agent'
AttributeError: 'ConversationBufferMemory' object has no attribute 'save_context'

LangChain 1.0 removed four entire public-API surfaces in one release:

  • Provider imports under langchain.chat_models / langchain.llms (pain code P38).
  • The LLMChain family under langchain.chains (P39).
  • ConversationBufferMemory and siblings under langchain.memory (P40).
  • initialize_agent under langchain.agents (P41).

Anything that inspected intermediate_steps also breaks because the tuple shape changed from (AgentAction, observation) to (ToolCall, observation) (P42).

This skill walks a reversible, phased migration:

  1. A pre-flight grep audit.
  2. A pinned package upgrade (including the langchain-anthropic 1.0 peer-pin against anthropic >= 0.40, P66).
  3. Codemod patterns for the seven removed APIs.
  4. A rollout playbook with shadow traffic and a sub-five-minute rollback.

It covers 7 named breaking changes and typically touches 10–100 files in a mid-sized service.

The fix for the error above:


# BEFORE (0.3)
from langchain.chat_models import ChatOpenAI

# AFTER (1.0)
from langchain_openai import ChatOpenAI

See codemod-patterns.md for the other six patterns.

Prerequisites

  • Python 3.10+ (LangChain 1.0 dropped 3.8/3.9).
  • A working test suite for the service being migrated (the playbook runs pytest -W error::DeprecationWarning at every phase).
  • Git on a clean working tree — the migration uses per-module commits so rollback is per-commit.
  • Access to staging traffic or a request-mirror. Phase 4 of the playbook needs real-shape traffic.
  • If conversations are persisted (Redis / Postgres / DynamoDB), a snapshot of the chat-history store before Phase 2. The LangGraph checkpointer uses a new schema and a naive rollback is data-lossy.

Instructions

Step 1 — Pre-flight grep audit

Inventory every 0.3 usage before touching a requirements.txt. Each grep below maps to one pain code and one codemod pattern.


grep -rn "from langchain\.chat_models\|from langchain\.llms" --include="*.py" .          # P38
grep -rn "from langchain\.chains\b\|\bLLMChain\b\|\bRetrievalQA\b" --include="*.py" .    # P39
grep -rn "from langchain\.memory\|ConversationBufferMemory" --include="*.py" .           # P40
grep -rn "initialize_agent\|AgentType\." --include="*.py" .                              # P41
grep -rn "\.tool_input\b\|intermediate_steps" --include="*.py" .                         # P42
grep -rn "astream_log\b" --include="*.py" .                                              # P67

Pipe the full set into langchain-0.3-hits.txt — that file is the migration work list. The migration-detection.md reference has the one-shot bundled block and a line-count triage table.

Step 2 — Pin and upgrade packages together

LangChain 1.0 spans six coordinated packages. A partial upgrade (e.g. pip install -U langchain-anthropic without bumping anthropic) triggers AttributeError at import time (P66). Update all six in the same commit:


langchain>=1.0,<2
langchain-core>=0.3,<0.4
langchain-openai>=1.0
langchain-anthropic>=1.0
langgraph>=1.0,<2
anthropic>=0.40,<1

Apply:


pip install -U \
  "langchain>=1.0,<2" \
  "langchain-core>=0.3,<0.4" \
  "langchain-openai>=1.0" \
  "langchain-anthropic>=1.0" \
  "langgraph>=1.0,<2" \
  "anthropic>=0.40,<1"

Then snapshot the prior state for the rollback: pip freeze > requirements.lock.pre-1.0.txt.

Step 3 — Codemod the four removed APIs

Work through the hits from Step 1 in this order (lowest blast radius first):

  1. Provider imports (P38) — mechanical find/replace. from langchain.chatmodels import ChatOpenAIfrom langchainopenai import ChatOpenAI. Same pattern for ChatAnthropic, OpenAIEmbeddings, Chroma, etc.
  2. LLMChain → LCEL (P39) — replace chain = LLMChain(llm=llm, prompt=prompt) with chain = prompt | llm | StrOutputParser(). Caller changes from chain.run(x=1) to chain.invoke({"x": 1}). If the caller treated the result as a dict, unwrap — invoke returns the string directly.
  3. initializeagentcreatereactagent (P41) — swap the import to from langgraph.prebuilt import createreactagent. Tools written with Tool(name=..., func=...) still work; prefer the @tool decorator from langchaincore.tools. Agent input becomes {"messages": [("user", "...")]}; the final reply is result["messages"][-1].content.
  4. ConversationBufferMemory → LangGraph checkpointer (P40) — swap the memory object for MemorySaver() (dev) or SqliteSaver.fromconnstring(...) (prod). Compile the graph/agent with checkpointer=saver, then pass config={"configurable": {"threadid": "..."}} on every invoke. The threadid is the conversation primary key.

Full before/after snippets for all four are in codemod-patterns.md.

Step 4 — Update streaming callers (P67)

astreamlog still works in 1.0 but is soft-deprecated. The replacement is astreamevents(version="v2"):


# BEFORE
async for patch in chain.astream_log({"input": "hi"}):
    for op in patch.ops:
        if op["op"] == "add" and op["path"].endswith("/streamed_output/-"):
            print(op["value"], end="")

# AFTER
async for event in chain.astream_events({"input": "hi"}, version="v2"):
    if event["event"] == "on_chat_model_stream":
        print(event["data"]["chunk"].content, end="")

Event names in v2: onchainstart, onchainend, onchatmodelstart, onchatmodelstream, onchatmodelend, ontoolstart, ontool_end. The payload under data is typed — chunk is an AIMessageChunk, not a raw string.

Step 5 — Fix intermediate_steps consumers (P42)

If any code iterates result["intermediatesteps"] and reads .tool / .toolinput, it breaks silently in 1.0 — the tuples now hold ToolCall dicts, not AgentAction objects. The 1.0 equivalent reads from graph state:


# BEFORE
for action, observation in result["intermediate_steps"]:
    log(action.tool, action.tool_input, observation)

# AFTER
for msg in result["messages"]:
    for tc in getattr(msg, "tool_calls", []) or []:
        log(tc["name"], tc["args"])   # .tool -> "name", .tool_input -> "args"

ToolCall dict keys are name, args, id. There is no tool or tool_input accessor anywhere in 1.0.

Step 6 — Gate on deprecation-as-error tests

Turn DeprecationWarning into a test failure so any surviving 0.3 pattern surfaces before the rollout:


pytest -W error::DeprecationWarning

Do not promote to staging while this is red. Re-run the Step 1 greps — they should now return zero hits outside intentionally-pinned 0.3 test fixtures.

Step 7 — Phased rollout on production traffic

Deploy behind a feature flag (LANGCHAIN10_ENABLED), canary at 1%, and ramp to 100% over 2–4 hours with a 15-minute soak at each step. The rollback is always "flip the flag off" — not a redeploy. Full playbook (shadow traffic in staging, dual-write for persistent chat histories, per-phase exit criteria) is in phased-rollout-playbook.md.

Output

  • requirements.txt pinning all six 1.0 packages with the anthropic >= 0.40 peer-pin (P66).
  • requirements.lock.pre-1.0.txt in the repo root for five-minute rollback.
  • Per-module git commits referencing pain codes (e.g. refactor: migrate P39 LLMChain in billing-summariser to LCEL).
  • langchain-0.3-hits.txt work-list returning zero non-test hits on re-run.
  • pytest -W error::DeprecationWarning green on the migration branch.
  • Feature-flagged production cutover at 100%, flag removed after a full day of soak.

Error Handling

Error Cause Fix
ImportError: cannot import name 'ChatOpenAI' from 'langchain.chat_models' P38 — provider imports moved to partner packages from langchain_openai import ChatOpenAI
ImportError: cannot import name 'LLMChain' from 'langchain.chains' P39LLMChain removed Replace with LCEL: `prompt \ llm \ StrOutputParser()`
AttributeError: 'ConversationBufferMemory' object has no attribute 'save_context' P40 — memory classes removed from the public API Swap for LangGraph MemorySaver / SqliteSaver with a thread_id
AttributeError: module 'langchain.agents' has no attribute 'initialize_agent' P41 — legacy agent constructor removed from langgraph.prebuilt import createreactagent
AttributeError: 'ToolCall' object has no attribute 'tool' P42 — tuple shape changed, fields renamed Read tc["name"] and tc["args"] instead of .tool / .tool_input
AttributeError: module 'anthropic' has no attribute 'AsyncAnthropic' P66langchain-anthropic 1.0 needs anthropic >= 0.40 Pin anthropic>=0.40,<1 in the same commit as the langchain-anthropic bump
DeprecationWarning: astreamlog is deprecated; use astreamevents(version="v2") P67 — soft deprecation Switch to astream_events(version="v2") and update event-name handling

Examples

Example 1 — Minimal LLMChain to LCEL


# BEFORE (0.3)
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([("system", "Summarise in one line."), ("user", "{text}")])
chain = LLMChain(llm=llm, prompt=prompt)
print(chain.run(text="LangChain 1.0 removed LLMChain."))

# AFTER (1.0)
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([("system", "Summarise in one line."), ("user", "{text}")])
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"text": "LangChain 1.0 removed LLMChain."}))

Example 2 — Stateful agent with LangGraph checkpointer


# AFTER (1.0)
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver    # use SqliteSaver / PostgresSaver in prod

@tool
def add(a: int, b: int) -> int:
    """Add two integers."""
    return a + b

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
agent = create_react_agent(llm, [add], checkpointer=MemorySaver())

config = {"configurable": {"thread_id": "user-42"}}
r1 = agent.invoke({"messages": [("user", "What's 2 + 3?")]}, config=config)
r2 = agent.invoke({"messages": [("user", "And plus 10?")]}, config=config)   # remembers "5"
print(r2["messages"][-1].content)

Example 3 — Rollback pin

If Phase 5 of the rollout regresses and the feature flag is already off:


git checkout main
pip install -r requirements.lock.pre-1.0.txt
pytest                      # confirm green on the rollback pin
# deploy

Resources

Ready to use langchain-py-pack?