NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #477 most downloaded on PyPI
Library with high-level APIs for creating and executing LangGraph agents and tools.
Last release 4 months ago
12 May 2026
Ships fairly regularly
a new release about every 2 weeks
Some releases are documented
notes for 21 of 36 stable releases
1 version withdrawn
withdrawn after publishing
2 years old
44 releases · first in 2025
One column per month.
…under the hood. However, this is deprecated and emits a LangGraphDeprecatedSinceV11 warning. It will be removed in v3.0 — migrate to result.value and…
Changes since 1.0.10
LangGraph 1.1 introduces version="v2" — a new opt-in streaming format that brings full type safety to stream(), astream(), invoke(), and ainvoke().
v1 (default, unchanged): stream() yields bare tuples like (stream_mode, data) or just data. invoke() returns a plain dict. Interrupts are mixed into the output dict under "__interrupt__".
v2 (opt-in): stream() yields strongly-typed StreamPart dicts with type, ns, data, and (for values) interrupts fields. invoke() returns a GraphOutput object with .value and .interrupts attributes. When your state schema is a Pydantic model or dataclass, outputs are automatically coerced to the correct type.
invoke() / ainvoke() with version="v2"from langgraph.types import GraphOutput
result = graph.invoke({"input": "hello"}, version="v2")
# result is a GraphOutput, not a dict
assert isinstance(result, GraphOutput)
result.value # your output — dict, Pydantic model, or dataclass
result.interrupts # tuple[Interrupt, ...], empty if none occurred
With a non-"values" stream mode, invoke(..., stream_mode="updates", version="v2") returns list[StreamPart] instead of list[tuple].
stream() / astream() with version="v2"for part in graph.stream({"input": "hello"}, version="v2"):
if part["type"] == "values":
part["data"] # OutputT — full state
part["interrupts"] # tuple[Interrupt, ...]
elif part["type"] == "updates":
part["data"] # dict[str, Any]
elif part["type"] == "messages":
part["data"] # tuple[BaseMessage, dict]
elif part["type"] == "custom":
part["data"] # Any
elif part["type"] == "tasks":
part["data"] # TaskPayload | TaskResultPayload
elif part["type"] == "debug":
part["data"] # DebugPayload
Each stream mode has its own TypedDict — ValuesStreamPart, UpdatesStreamPart, MessagesStreamPart, CustomStreamPart, CheckpointStreamPart, TasksStreamPart, DebugStreamPart — all importable from langgraph.types. The union type StreamPart is a discriminated union on part["type"], enabling full type narrowing in editors and type checkers.
When your graph's state schema is a Pydantic model or dataclass, version="v2" automatically coerces outputs to the declared type:
from pydantic import BaseModel
class MyState(BaseModel):
answer: str
count: int
graph = StateGraph(MyState)
# ... build graph ...
compiled = graph.compile()
result = compiled.invoke({"answer": "", "count": 0}, version="v2")
assert isinstance(result.value, MyState) # not a dict!
version="v1" — existing code works without changes.GraphOutput supports old-style best-effort access to graph values and interrupts. Dict-style access (result["key"], "key" in result, result["__interrupt__"]) still works and delegates to result.value / result.interrupts under the hood. However, this is deprecated and emits a LangGraphDeprecatedSinceV11 warning. It will be removed in v3.0 — migrate to result.value and result.interrupts at your convenience.result = graph.invoke({"input": "hello"}, version="v2")
# Old style — still works, but deprecated
result["input"] # delegates to result.value["input"]
result["__interrupt__"] # delegates to result.interrupts
"input" in result # delegates to "input" in result.value
# New style — preferred
result.value["input"]
result.interrupts
version="v1" remains the default. All existing code continues to work.version="v2" to individual invoke()/stream() calls to get typed outputs.GraphOutput, StreamPart, and individual part types from langgraph.types for type-safe code.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
chore(deps-dev): bump the all-dependencies group across 1 directory with 3 updates
Changes since 1.0.10rc1
fix: sequential interrupt handling w/ functional API
Changes since 1.0.8
fix: pydantic messages double streaming
Changes since 1.0.7
Runtime and ToolRuntime class descriptions for clarity (#6689)thread_id (#6515)add_node overloads (#6514)fix: aiosqlite's breaking change
Changes since 1.0.6
uv lock --upgrade (#6671)fix: flip default on base cache
Changes since 1.0.5
release(langgraph): bump to 1.0.5
Changes since 1.0.4
chore: pop thread ID from configurable fields in remote graph
Changes since 1.0.3
feat(docs): warn that StateGraph is a builder class
Changes since 1.0.2
StateGraph is a builder class (#6417)PartialState rendering in MkDocs (#6416)invoke and ainvoke docstrings (#6415)stream and astream docstrings (#6414)StateGraph (#6308)pyproject.toml links (#6364)chore: bump prebuilt dep for lg
Changes since 0.6.11
python.langchain links with new docs.langchain (#6352)chore: Restrict "json" type deserialization
Changes since 1.0.0
release: langgraph + langgraph-prebuilt v1.0.0
Changes since 1.0.0rc1
Nothing published for this version
Nothing published for this version
Nothing published for this version
feat(langgraph): implement redis node level cache
Changes since 0.6.4
chore(langgraph): deprecate MessageGraph
Changes since 0.6.3
updated_channels to checkpoint (#5828)MessageGraph (#5843)fix(langgraph): fix up deprecation warnings
Changes since 0.6.2
AgentState (#5801)config param (#5798)invoke and ainvoke (#5771)fix(prebuilt): assign context_schema to config_schema with correct condition
Changes since 0.6.1
context_schema to config_schema with correct condition (#5746)fix(langgraph): use parent runtime when available
Changes since 0.6.0
These changes make it easier to maintain a higher quality public API and reduce the surface area for potential breaking changes.
We’re excited to announce the release of LangGraph v0.6.0, another significant step toward our v1.0 milestone. This release emphasizes providing a cleaner, more intuitive developer experience for building agentic workflows. Below we’ll cover the headline improvements and minor changes.
The biggest improvement in v0.6 is the introduction of the new Context API, which makes it easier to pass run-scoped context in an intuitive and type safe way.
This pattern replaces the previously recommended pattern of injecting run-scoped context into config['configurable'].
from langchain_core.runnables import RunnableConfig
from langgraph.graph import StateGraph
def node(state: State, config: RunnableConfig):
# verbose .get() access pattern for nested dicts
user_id = config.get("configurable", {}).get("user_id")
db_conn = config.get("configurable", {}).get("db_connection")
...
builder = StateGraph(state_schema=State, config_schema=Config)
# add nodes, edges, compile the graph...
# nested runtime context passed to config's configurable key
result = graph.invoke(
{'input': 'abc'},
config={'configurable': {'user_id': '123', 'db_connection': 'conn_mock'}}
)
from dataclasses import dataclass
from langgraph.graph import StateGraph
from langgraph.runtime import Runtime
@dataclass
class Context:
"""Context schema defined by the developer."""
user_id: str
db_connection: str
def node(state: State, runtime: Runtime[Context]):
# type safe access to context attributes
user_id = runtime.context.user_id
db_conn = runtime.context.db_connection
...
builder = StateGraph(state_schema=State, context_schema=Context)
# add nodes, edges, compile the graph...
# top level context arg is typed as Context for autocomplete and type checking
result = graph.invoke(
{'input': 'abc'},
context=Context(user_id='123', db_conn='conn_mock')
)
The Runtime class provides a single interface for accessing information like:
previous is also available: the previous return value for the given threadNow, instead of injecting all of the above as separate parameters to node functions,
developers can access them all through a single runtime parameter.
config_schema is deprecated in favor of context_schema, and will be removed in v2.0.0config_schemaget_config_jsonschema is deprecated in favor of get_context_jsonschema (though this is generally only used for graph introspection and not by most langgraph users)create_react_agent can now dynamically choose both the model and tools at runtime using a custom context object:
from langgraph.prebuilt import create_react_agent
@dataclass
class CustomContext:
provider: Literal["anthropic", "openai"]
tools: list[str]
def select_model(state, Runtime[Context]):
model = {
"openai": openai_model,
"anthropic": anthropic_model,
}[runtime.context.provider]
selected_tools = [
tool for tool in [weather, compass]
if tool.name in runtime.context.tools
]
return model.bind_tools(selected_tools)
agent = create_react_agent(
select_model,
# Initialize the agent with all known tools
tools=[weather, compass]
)
Then invoke the agent with your desired settings:
agent.invoke(
some_input,
context=CustomContext(provider="openai", tools=["compass"])
)
Now agents can flexibly adapt their behavior based on runtime context.
LangGraph v0.6 introduces a new durability ****argument that gives you fine-grained control over persistence behavior. This provides finer grained control than its predecessor, checkpoint_during.
This was predated
"exit" - Save checkpoint only when the graph exits
checkpoint_during=False"async" - Save checkpoint asynchronously while next step executes
checkpoint_during=True"sync" - Save checkpoint synchronously before next step
checkpoint_during is now deprecated in favor of the new durability argument. Backwards compatibility will be maintained until v2.0.0.
In an effort to make graph building easier for developers, we’ve enhanced the type safety of the LangGraph APIs.
LangGraph’s StateGraph and Pregel interfaces are now generic over a graph’s:
state_schemacontext_schemainput_schemaoutput_schemaThis means that:
invoke / stream is type checked against the relevant schemacontext available via the aforementioned Runtime class matches the context_schemaInterrupt InterfaceIn preparation for v1.0, we’ve made a few changes to the Interrupt interface.
Interrupts now have two attributes:
id - a unique identifier for the interruptvalue - the interrupt valueIn v0.6, we’ve removed the following attributes from the Interrupt class:
when - this was always "during" and offered no practical valueresumable - functionally, this is always Truens - this information is now stored in a condensed format in the id attributeinterrupt_id has been deprecated in favor of id, but is still usable for backward compatibilityGearing up for v1.0, we’ve solidified what’s public vs. private in the LangGraph API. We’ve also deprecated some old import paths that have supported backports for ~1 year.
These changes make it easier to maintain a higher quality public API and reduce the surface area for potential breaking changes.
The following table summarizes the changes:
| Old Import | New Import | Status |
|---|---|---|
from langgraph.pregel.types import ... |
from langgraph.types import ... |
⚠️ Deprecated - Will be removed in V2 |
from langgraph.constants import Send |
from langgraph.types import Send |
⚠️ Deprecated - Will be removed in V2 |
from langgraph.constants import Interrupt |
from langgraph.types import Interrupt |
⚠️ Deprecated - Will be removed in V2 |
from langgraph.channels import <ErrorClass> |
from langgraph.errors import <ErrorClass> |
❌ Removed - All errors now centralized in langgraph.errors |
from langgraph.constants import TAG_NOSTREAM_ALT |
from langgraph.constants import NOSTREAM |
❌ Removed - Deprecated constant removed |
LangGraph v0.6 represents our final major changes before the stable v1.0 release. We anticipate adhering strictly to SemVer post v1.0, leaning into a promise of stability and predictability.
LangGraph is an open source project, and we’d love to hear from you! We’ve rolled out a new LangChain forum for questions, feature requests, and discussions.
Please let us know what you think about the new Runtime API and other changes in v0.6, and if you have any difficulties with which we can help.
context API (#5566)Runtime interface re patch/overrides (#5546)constants.py -> _internal/_typing.py (#5518)config['configurable'] and config_schema) (#5243)node signatures vs input_schema for add_node (#5424)Interrupt interface for v1 (#5405)feat(sdk-py): sdk support for context API
Changes since 0.5.4
context API (#5566)Runtime interface re patch/overrides (#5546)constants.py -> _internal/_typing.py (#5518)config['configurable'] and config_schema) (#5243)node signatures vs input_schema for add_node (#5424)Interrupt interface for v1 (#5405)patch[langgraph]: Fix hint for invoke/stream to allow for Command and None
Changes since 0.5.1
invoke/stream to allow for Command and None (#5414)langgraph[fix]: remove deprecated pydantic logic + fix schema gen behavior for typed dicts
Changes since 0.5.0
The old names still work but raise a deprecation warning.
TL;DR – 0.5 is not a radical rewrite, but a scrub-down and tune-up of the LangGraph core.
APIs are a little stricter, you have more control over streaming, checkpoints are lighter, etc. 99 % of users can upgrade with nothing more than a pip install --upgrade langgraph==0.5.*.
The team’s next big milestone is a 1.0 release in a few months.
To get there we needed to:
0.5 is that housekeeping release.
state_schema is now mandatory.
“Untyped” graphs were never shown in the docs and produced surprising runtime errors. Requiring an explicit schema fixes that class of bugs and improves static analysis.
input/output → input_schema/output_schema
The old names still work but raise a deprecation warning.
graph = StateGraph(
state_schema=MyState,
input_schema=UserQuery,
output_schema=AssistantResponse,
)
New NodeBuilder utility
A simpler, declarative way to create nodes and attach them to channels. The old Channel.subscribe_to helper keeps working but will be removed in 1.0.
stream_mode="debug" is now an alias for the pair["tasks", "checkpoints"]. You can now turn them on individually:graph.stream(stream_mode="tasks") # only task-level updates
graph.stream(stream_mode="checkpoints") # only checkpoint deltas
This makes it cheaper to subscribe only to the information you need.
JsonPlusSerializer now handles NumPy arrays stored in your state (including Fortran-ordered ones) without falling back to pickle.state_schema required – add it if you were passing only input and output schemas instead (very rare).input / output renaming – rename to input_schema / output_schema.PregelNode and Runnable, drop the latter.Nothing else should require code changes.
pip install -U "langgraph>=0.5"
If you maintain a plugin / custom checkpointer, run your test suite once; the public interfaces are untouched.
We’re hard at work on LangGraph 1.0, chime in here with any comments, feedback or questions, we want to hear from everyone.
MessageGraph (#4875)"output usage in favor of output_schema (#5095)PregelNode's inheritance from Runnable (#5093)input and output in favor of input_schema and output_schema (#4983)pep 604 union syntax and pep 585 generic syntax (#4963)StateGraph(dict) (#4964)retry -> retry_policy (#4957)init and invoke/stream (#4932)state_schema in StateGraph.__init__ (#4897)MessageGraph (#4875)fix(langgraph): remove deprecated output usage in favor of output_schema
Changes since 0.4.8
output usage in favor of output_schema (#5095)PregelNode's inheritance from Runnable (#5093)input and output in favor of input_schema and output_schema (#4983)pep 604 union syntax and pep 585 generic syntax (#4963)StateGraph(dict) (#4964)retry -> retry_policy (#4957)init and invoke/stream (#4932)state_schema in StateGraph.__init__ (#4897)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →