LangChain and LangGraph 1.0 in Practice
LangChain 1.0 and LangGraph 1.0 shipped on 22 October 2025 with a no-breaking-changes commitment until 2.0. We examine create_agent and its middleware hooks, checkpointer-backed persistence, human-in-the-loop interrupts, and the mechanics of migrating legacy chains to langchain-classic — including what the stable APIs do not solve.
The Cost of a Moving Target
LangChain earned a reputation for instability. Between 2023 and 2025, teams migrated from chains to LCEL runnables to prebuilt agents, and each round of deprecations cost engineering time without changing system behavior. For production systems, API churn was the strongest argument against the framework — and a common reason to build agent loops by hand.
On 22 October 2025, LangChain released version 1.0 of both langchain and langgraph, in Python and TypeScript, with an explicit commitment: no breaking changes until 2.0. This article examines what the releases contain, how the new primitives behave in practice, and what a migration from 0.x actually involves.
What Shipped on October 22
LangChain 1.0 is a rebuild around one abstraction. create_agent implements the standard tool-calling loop and runs on the LangGraph runtime; it replaces create_react_agent, which is now deprecated in langgraph.prebuilt. The package surface shrinks to agent building blocks. Python 3.9 support is dropped after its October 2025 end of life; 1.0 requires Python 3.10 or newer.
LangGraph 1.0 is the quieter release. Its APIs for durable execution, streaming, and state management were already in production use at companies such as Uber, LinkedIn, and Klarna; the 1.0 label stabilizes them with almost no breaking changes. A second LangChain addition is standard content blocks: a provider-agnostic content_blocks property that normalizes reasoning traces, citations, and tool calls across model providers.
create_agent and the Middleware Contract
create_agent runs model calls and tool calls in a loop until the model stops requesting tools. Customization does not happen by subclassing but through middleware: objects that implement up to six hooks around the loop. Node-style hooks return state updates; wrap-style hooks control the call itself and can short-circuit, retry, or swap models per request.
LangChain ships prebuilt middleware for summarization at a token threshold, PII redaction, call limits, and human-in-the-loop approval. Composition follows web-server semantics: before_* hooks run first to last, after_* hooks in reverse order, and wrap_* hooks nest. This is the part of 1.0 that changes daily work most — behavior that previously required forking the agent graph is now a declared component.
| Hook | Runs | Typical use |
|---|---|---|
| before_agent | Once when the agent starts | Load memory, validate input |
| before_model | Before each model call | Trim history, redact PII |
| wrap_model_call | Around each model call | Retries, caching, model switching |
| wrap_tool_call | Around each tool call | Intercept results, gate execution |
| after_model | After each model response | Guardrails, human approval |
| after_agent | Once when the agent completes | Persist results, cleanup |
Checkpointers Make State Durable
A checkpointer persists graph state after every super-step, keyed by a thread_id passed in the run configuration. That single mechanism enables conversation continuity, fault-tolerant resumption after crashes, time-travel debugging, and interrupts. InMemorySaver is for development only; SqliteSaver and PostgresSaver survive process restarts and are the production options.
Two limits are worth stating. A checkpointer is thread-scoped short-term state, not a memory system; knowledge shared across threads requires the separate store interface. And checkpointing does not deduplicate side effects: on resume, a node re-executes from its beginning, so external calls must be idempotent or isolated.
Interrupts for Human Approval
The interrupt() function pauses a graph at an arbitrary point inside a node. The runtime saves state through the checkpointer, surfaces a JSON-serializable payload to the caller under __interrupt__, and waits indefinitely. Resuming means invoking the graph again with Command(resume=value) and the same thread_id; the value becomes the return value of interrupt().
In create_agent, HumanInTheLoopMiddleware packages this pattern: it declares which tools require approval and which decisions are allowed — approve, edit, or reject — before a tool call executes. One caveat carries over from the runtime: the interrupted node restarts from its beginning on resume, so any code before the interrupt() call runs twice. Place side effects after the approval point.
Migrating off Legacy Chains
In 1.0, imports of LLMChain, ConversationChain, the retriever modules, the indexing API, and the hub fail. They moved to langchain-classic, installable alongside 1.0; changing the import prefix to langchain_classic restores the old behavior. This step is mechanical and buys time. It is not modernization — langchain-classic carries the deprecated code as-is.
The forward path replaces chain classes with runnable composition — prompt | model | parser — or with create_agent where tool use is involved. LLMChain has been deprecated since version 0.1.17, so the replacement APIs are documented and stable. The 0.3 line stays in maintenance mode with security patches and critical bug fixes until December 2026; that is the realistic migration window.
Prebuilt agents migrate separately. create_react_agent still works but is deprecated; the replacement is create_agent from langchain.agents. The mapping is close: the prompt parameter becomes system_prompt, and pre- and post-model hooks become middleware. Tool error handling moves into wrap_tool_call middleware. Plan a day per agent for the rename plus a regression run — not more, in our experience.
What 1.0 Does Not Solve
API stability is a contract about signatures, not about behavior. Agents remain nondeterministic; pinning the framework does not pin model output. Evaluation suites, tracing, and regression tests stay mandatory. The stability promise also covers only langchain and langgraph — provider packages such as langchain-openai and langchain-anthropic version independently and follow their providers' API changes.
Middleware raises the ceiling and demands discipline. Six hooks across several stacked middleware produce interleavings that must be reasoned about explicitly; ordering bugs are silent. Checkpointed state is versioned data of your application: when your state schema evolves, migrating persisted threads is your responsibility, not the framework's.
Outlook from November 2025
We at Blue IT Systems read the 1.0 releases as the start of consolidation. With stable interfaces, middleware becomes a unit of reuse; we expect an ecosystem of third-party middleware packages — guardrails, cost controls, audit logging — within months. Durable execution and interrupt-based approval will become table stakes for every agent framework, not differentiators.
The open question is how much framework remains as models absorb more of the loop. If planning and tool selection move into the models themselves, frameworks contract toward runtime concerns: persistence, approval, observability. That is where LangGraph placed its bet. Whether the create_agent abstraction survives unchanged until 2.0 will be the real test of the promise made on 22 October.
Sources
- LangChain and LangGraph Agent Frameworks Reach v1.0 (LangChain Blog, 22 Oct 2025)
- Agent Middleware (LangChain Blog, 8 Sep 2025)
- LangChain 1.0 now generally available (LangChain Changelog, 22 Oct 2025)
- LangChain v1 Migration Guide (LangChain Docs, accessed 17 Nov 2025)
- LangChain raises $125M to build the platform for agent engineering (LangChain Blog, 20 Oct 2025)
