LangGraph
sdk==0.4.4 open-sourceLangGraph is a framework for building stateful, multi-actor applications using language models with cyclic computational graphs.
graph.add_node("my_node", my_node_fn, trace_policy=<policy>)
graph.add_node('my_node', my_node_fn, trace_policy=TracePolicy(...))
graph.add_node('my_node', my_node_fn, trace_policy=TracePolicy(...))
crons = await client.crons.search(metadata={"env": "production", "team": "infra"})
from langgraph.graph import StateGraph
builder = StateGraph(MyState)
builder.set_node_defaults(config={"model": "gpt-4o", "temperature": 0})
builder.add_node("extract", extract_node)
builder.add_node("summarize", summarize_node)
client.threads.update(thread_id, return_minimal=True)
history = await saver.get_writes_history(config)
# (Python) — stream_events v3
async for event in graph.astream_events(input, version='v3'):
print(event)
from langgraph.prebuilt import ToolNode
from langgraph.types import Command
from langchain_core.messages import ToolMessage
def my_tool(tool_call_id: str, query: str) -> list:
return [
ToolMessage(content="result", tool_call_id=tool_call_id),
Command(goto="follow_up_node"),
]
node = ToolNode([my_tool])
from langgraph.prebuilt import ToolNode
from langgraph.types import Command
from langchain_core.messages import ToolMessage
def my_tool(tool_call_id: str, query: str) -> list:
# Emit a state update command AND a tool result message
return [
Command(update={"retrieved": query}),
ToolMessage(content=f"Result for {query}", tool_call_id=tool_call_id),
]
node = ToolNode([my_tool])
from langgraph.prebuilt import ToolNode
from langgraph.types import Command
from langchain_core.messages import ToolMessage
def my_tool(tool_call_id: str, query: str) -> list:
# Return a Command to update state AND a ToolMessage for the model
return [
Command(update={"retrieved": query}),
ToolMessage(content=f"Searched for: {query}", tool_call_id=tool_call_id),
]
node = ToolNode([my_tool])
result = await client.runs.create(
thread_id=thread_id,
assistant_id=assistant_id,
input={"messages": [{"role": "user", "content": "hello"}]},
langsmith_tracing=False,
)
langgraph deploy revisions list
langgraph deploy logs <deployment-id>
langgraph deploy list
langgraph deploy delete <deployment-id>
result = graph.invoke({"input": "hello"}, version="v2")
result.value # your output state
result.interrupts # tuple[Interrupt, ...], empty if none
from langgraph.types import ValuesStreamPart, UpdatesStreamPart
for part in graph.stream({"input": "hello"}, version="v2"):
if part["type"] == "values":
state = part["data"] # OutputT — full typed state
interrupts = part["interrupts"]
elif part["type"] == "updates":
delta = part["data"] # dict[str, Any]
from pydantic import BaseModel
from langgraph.graph import StateGraph
class MyState(BaseModel):
answer: str
count: int
compiled = StateGraph(MyState).compile() # ... add nodes/edges first
result = compiled.invoke({"answer": "", "count": 0}, version="v2")
assert isinstance(result.value, MyState)
langgraph deploy
from langgraph_sdk import get_client, SKIP_LOAD_API_KEY
client = get_client(url="http://localhost:8123", api_key=SKIP_LOAD_API_KEY)
assistants = await client.assistants.search(name="my-assistant")
from langgraph.types import Overwrite
from typing import Annotated
from typing_extensions import TypedDict
class State(TypedDict):
messages: Annotated[list, Overwrite()] # latest assignment replaces, no reducer merging
graph.invoke(input, durability="ephemeral")
from dataclasses import dataclass
from langgraph.graph import StateGraph
from langgraph.runtime import Runtime
@dataclass
class Context:
user_id: str
db_connection: str
def node(state: State, runtime: Runtime[Context]):
user_id = runtime.context.user_id
db_conn = runtime.context.db_connection
...
builder = StateGraph(state_schema=State, context_schema=Context)
# add nodes, edges, compile...
result = graph.invoke(
{'input': 'abc'},
context=Context(user_id='123', db_connection='conn_mock')
)
from dataclasses import dataclass
from typing import Literal
from langgraph.prebuilt import create_react_agent
from langgraph.runtime import Runtime
@dataclass
class CustomContext:
provider: Literal['anthropic', 'openai']
tools: list[str]
def select_model(state, runtime: Runtime[CustomContext]):
model = {'openai': openai_model, 'anthropic': anthropic_model}[runtime.context.provider]
selected_tools = [t for t in [weather, compass] if t.name in runtime.context.tools]
return model.bind_tools(selected_tools)
agent = create_react_agent(select_model, tools=[weather, compass])
agent.invoke(some_input, context=CustomContext(provider='openai', tools=['compass']))
thread_state = await client.threads.get_state(thread_id)
interrupts = thread_state.interrupts
for event in graph.stream(input, stream_mode="tasks"):
print(event)
from langgraph.graph import StateGraph
graph = StateGraph(
state_schema=MyState,
input_schema=UserQuery,
output_schema=AssistantResponse,
)
async for chunk in graph.astream(inputs, stream_mode=["tasks", "checkpoints"]):
print(chunk)
from langgraph.store.sqlite import SqliteStore
store = SqliteStore("./my_app.db")
results = store.list_namespaces(max_depth=2)
from langgraph.prebuilt import create_react_agent
def my_post_model_hook(state):
# inspect or mutate state after each model call
print("Model output:", state["messages"][-1].content)
return state
agent = create_react_agent(
model=llm,
tools=[...],
post_model_hook=my_post_model_hook,
)
from langgraph.store.sqlite import SqliteStore
store = SqliteStore("agent_memory.db")
# list namespaces up to 2 levels deep
namespaces = store.list_namespaces(max_depth=2)
print(namespaces)
store = SqliteStore("./agent_state.db")
# ... populate store ...
store.clear() # deletes all entries when called without arguments
from langgraph.func import entrypoint, task
from langgraph.types import Command
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
@entrypoint(checkpointer=checkpointer)
def my_graph(state):
return state
# Update state for a specific thread mid-run
my_graph.update_state({"configurable": {"thread_id": "thread-1"}}, {"key": "new_value"})
from langgraph_sdk import get_client
client = get_client(url="http://localhost:8123", timeout=30)
checkpointer.delete_thread(thread_id)
async for chunk in client.runs.stream(
thread_id,
assistant_id,
input=input_data,
checkpoint_during=False,
):
print(chunk)
run = await client.runs.create(
thread_id,
assistant_id,
input=input_data,
checkpoint_during=True,
)
results = await client.assistants.search(sort_by="updated_at", sort_order="desc")
from langgraph.graph.ui import push_ui_message
# First emission creates the message
push_ui_message("my-component", {"status": "loading"}, message_id="msg-1")
# Subsequent call merges new props into the existing message
push_ui_message("my-component", {"status": "done", "result": "42"}, message_id="msg-1", merge=True)
graph.invoke(Command(resume={interrupt.interrupt_id: "approved"}), config)
snapshot = graph.get_state(config)
for interrupt in snapshot.interrupts:
print(interrupt.interrupt_id, interrupt.value)
from langgraph.checkpoint.memory import InMemorySaver
saver = InMemorySaver()
# synchronous
saver.delete_thread(thread_id="thread-abc123")
# async
await saver.adelete_thread(thread_id="thread-abc123")
from langgraph.pregel.draw import draw_graph
draw_graph(compiled_graph)
langgraph up --image my-custom-langgraph-image:latest
langgraph dev --tunnel
threads = await client.threads.search(
sort_by="updated_at",
sort_order="desc"
)
saver = PostgresSaver(conn)
saver.delete_thread(thread_id="thread-abc123")
saver = AsyncPostgresSaver(conn)
await saver.adelete_thread(thread_id="thread-abc123")
{
"_INTERNAL_docker_tag": "3.11-slim-bookworm"
}
from langgraph.constants import CONFIG_KEY_THREAD_ID
def my_node(state, config):
thread_id = config["configurable"].get(CONFIG_KEY_THREAD_ID)
print(f"Running on thread: {thread_id}")
return state
from langgraph.types import RetryPolicy
from langgraph.graph import StateGraph
rate_limit_policy = RetryPolicy(retry_on=RateLimitError, max_attempts=5, backoff_factor=2.0)
network_policy = RetryPolicy(retry_on=ConnectionError, max_attempts=2, backoff_factor=1.0)
graph = StateGraph(MyState)
graph.add_node("my_node", my_node_fn, retry=[rate_limit_policy, network_policy])
from langgraph.func import task
from langgraph.types import RetryPolicy
@task(retry=[RetryPolicy(retry_on=TimeoutError, max_attempts=3), RetryPolicy(retry_on=Exception, max_attempts=1)])
def fetch_data(url: str):
...
result = graph.invoke({"messages": messages}, config=config, checkpoint_during=False)
async for chunk in graph.astream({"messages": messages}, config=config, checkpoint_during=False):
process(chunk)
from langgraph.graph.ui import push_ui_message, delete_ui_message, ui_message_reducer
# Inside a graph node:
def my_node(state):
msg = push_ui_message("progress-card", {"status": "running", "step": 1})
# ... do work ...
delete_ui_message(msg["id"])
return state
from typing import Annotated
from langgraph.graph.ui import AnyUIMessage, ui_message_reducer
from typing_extensions import TypedDict
class GraphState(TypedDict):
ui: Annotated[list[AnyUIMessage], ui_message_reducer]
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import trim_messages
def pre_model_hook(state):
trimmed = trim_messages(state["messages"], max_tokens=4096, token_counter=len)
return {"llm_input_messages": trimmed}
agent = create_react_agent(
model=llm,
tools=tools,
pre_model_hook=pre_model_hook,
)
def summarizing_hook(state):
messages = state["messages"]
if len(messages) > 20:
summary = llm.invoke(f"Summarize this conversation: {messages[:-5]}")
return {"llm_input_messages": [summary] + messages[-5:]}
return {"llm_input_messages": messages}
agent = create_react_agent(
model=llm,
tools=tools,
pre_model_hook=summarizing_hook,
)
assistant = await client.assistants.create(
graph_id="my-graph",
description="Triages incoming support tickets and routes to the correct queue."
)
await client.assistants.update(
assistant_id="asst_abc123",
description="Revised: handles both support tickets and billing inquiries."
)
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
serde = JsonPlusSerializer()
type_tag, data = serde.dumps_typed(None) # returns ("null", b"")
value = serde.loads_typed((type_tag, data)) # returns None
from langgraph.graph.message import REMOVE_ALL_MESSAGES
from langchain_core.messages import RemoveMessage
# Pass this to your graph state update to discard all prior messages
state_update = {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)]}
from langgraph_cli.config import CheckpointerConfig, ThreadTTLConfig
checkpointer = CheckpointerConfig(
ttl=ThreadTTLConfig(
default_minutes=1440, # delete thread data older than 24 hours
sweep_interval_minutes=60,
strategy="delete",
)
)
langgraph dev --allow-blocking
from langgraph_sdk.auth import Auth
auth = Auth()
@auth.authenticate
async def authenticate(headers: dict) -> Auth.types.MinimalUserDict:
# ... token validation ...
return {"identity": "user-123", "role": "admin"}
@auth.on
async def handle(ctx, value):
user = ctx.user
role = user["role"] # __getitem__
if "role" in user: # __contains__
for key in user: # __iter__
print(key, user[key])
run = await client.runs.create(
thread_id="<thread_id>",
assistant_id="<assistant_id>",
headers={"X-Tenant-ID": "org-42", "X-Request-ID": "req-abc123"}
)
async for chunk in client.runs.stream(
thread_id="<thread_id>",
assistant_id="<assistant_id>",
headers={"Authorization": "Bearer <ephemeral_token>"}
):
print(chunk)
from langgraph.utils.runnable import RunnableCallable
def my_node(state, config):
# config is available here
return {"result": config["configurable"].get("user_id")}
node = RunnableCallable(my_node, func_accepts_config=True)
from langgraph.pregel.read import PregelNode
child_graph = build_child_graph() # returns a compiled Pregel
node = PregelNode(
channels=["input"],
triggers=["input"],
mapper=None,
subgraphs=[child_graph],
)
langgraph dev --studio_url https://studio.internal.example.com
thread = await client.threads.create(
supersteps=source_supersteps,
graph_id="my-graph",
metadata={"copied_from": source_thread_id}
)
from langgraph.types import StateUpdate
# graph is a compiled Pregel graph, config identifies the thread
updates = [
StateUpdate(values={"status": "reviewed"}, as_node="reviewer"),
StateUpdate(values={"score": 0.95}, as_node="scorer"),
]
graph.bulk_update_state(config, updates)
from langgraph.types import StateUpdate
updates = [
StateUpdate(values={"approved": True}, as_node="approver"),
StateUpdate(values={"notes": "LGTM"}, as_node="annotator"),
]
await graph.abulk_update_state(config, updates)
if channel.is_available():
value = channel.get()
await compiled_graph.aget_graph(xray=True)
from langgraph.checkpoint.serde.encrypted import EncryptedSerializer
# Key can also be supplied via LANGGRAPH_AES_KEY env var
serializer = EncryptedSerializer.from_pycryptodome_aes(key=b"your-32-byte-aes-key-here!!!!!")
# Pass the serializer to your checkpointer of choice
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver(serde=serializer)
from langgraph.checkpoint.serde.base import CipherProtocol
from langgraph.checkpoint.serde.encrypted import EncryptedSerializer
class MyKMSCipher(CipherProtocol):
def encrypt(self, plaintext: bytes) -> bytes:
... # call your KMS
def decrypt(self, ciphertext: bytes) -> bytes:
... # call your KMS
serializer = EncryptedSerializer(cipher=MyKMSCipher())
from langgraph.store.postgres import PostgresStore
store = PostgresStore.from_conn_string(
"postgresql://user:pass@localhost/mydb",
ttl={"default_ttl": 60, "sweep_interval_minutes": 0.5},
)
store.start_ttl_sweeper()
# ... use store in your LangGraph app ...
store.stop_ttl_sweeper()
from langgraph.store.postgres.aio import AsyncPostgresStore
async with AsyncPostgresStore.from_conn_string(
"postgresql://user:pass@localhost/mydb",
ttl={"default_ttl": 120},
) as store:
await store.start_ttl_sweeper()
# ... use store in your async LangGraph app ...
await store.stop_ttl_sweeper()
from langgraph.store.postgres import PostgresStore
store = PostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb")
deleted_count = store.sweep_ttl()
print(f"Swept {deleted_count} expired items")
from langgraph.store.base import TTLConfig
ttl_config = TTLConfig(
sweep_interval_minutes=30
)
ttl_config = TTLConfig(
sweep_interval_minutes=10
)
export LANGGRAPH_DEFAULT_RECURSION_LIMIT=100
async for chunk in client.runs.join_stream(thread_id, run_id, stream_mode=["values", "debug"]):
print(chunk)
for chunk in client.runs.join_stream(thread_id, run_id, stream_mode=["values"], cancel_on_disconnect=True):
print(chunk)
from langgraph.prebuilt import create_react_agent
def lookup_user(user_id: str) -> str:
"""Look up a user by ID."""
return f"User {user_id}: Alice"
agent = create_react_agent(model, tools=[lookup_user])
from langgraph.prebuilt import create_react_agent
from langgraph.prebuilt.chat_agent_executor import AgentStatePydantic
agent = create_react_agent(model, tools=[...], state_schema=AgentStatePydantic)
from langgraph.store.base import TTLConfig
# When constructing your store implementation
store = MyStore(
ttl_config=TTLConfig(
default_ttl=60, # minutes; applied to put/aput when no TTL is specified
refresh_on_read=True # extends TTL whenever an item is fetched
)
)
from langgraph.config import StoreConfig, TTLConfig
store_cfg = StoreConfig(
ttl=TTLConfig(
default_ttl=60, # minutes until a new item expires
refresh_on_read=True, # reset the clock whenever the item is read
)
)
from pydantic import BaseModel
from langgraph.graph.state import StateGraph
class MyInput(BaseModel):
query: str
max_results: int = 5
builder = StateGraph(MyInput)
# ... add nodes and edges ...
graph = builder.compile()
# Pydantic validation now runs automatically on invoke
result = graph.invoke({"query": "threat actors targeting finance", "max_results": 10})
from langgraph.graph.branch import Branch
branch = Branch.from_path(
path=my_router_fn,
path_map={"yes": "node_a", "no": "node_b"},
# input_schema is inferred automatically from my_router_fn's signature
)
graph.add_conditional_edges("entry", branch)
from langgraph.store.postgres.base import PLACEHOLDER
store.put(("namespace",), 42, {"value": "data"})
result = store.get(("namespace",), 42)
await client.store.put_item(namespace, key="session:user123", value={"token": "abc"}, ttl=30)
item = await client.store.get_item(namespace, key="session:user123", refresh_ttl=True)
{
"graphs": {
"my_agent": "./agent.py:graph"
},
"ui": {
"my_agent": "./ui/MyAgentComponent.tsx"
}
}
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful security analyst."),
("placeholder", "{messages}"),
])
llm = ChatOpenAI(model="gpt-4o")
# Pass the RunnableSequence (prompt | llm) directly as the model
agent = create_react_agent(model=prompt | llm, tools=[my_tool])
schema = graph.get_config_jsonschema()
print(schema)
from langgraph.utils.pydantic import is_supported_by_pydantic
from typing import TypedDict
class MyConfig(TypedDict):
temperature: float
max_tokens: int
if is_supported_by_pydantic(MyConfig):
print("Safe to use as a Pregel config type")
from langgraph.prebuilt.chat_agent_executor import AgentStateWithStructuredResponse
@auth.on.store
async def authorize_store(ctx, value):
# Allow access only if the namespace matches the authenticated user
if ctx.user.identity not in value.get("namespace", []):
raise Exception("Access denied")
http:
app: ./my_middleware_app.py:app
cors:
allow_origins:
- "https://my-frontend.example.com"
allow_methods:
- "GET"
- "POST"
disable_routes:
- assistants
- store
from langgraph.constants import CONFIG_KEY_RUNNER_SUBMIT
def my_submit(fn, *args, **kwargs):
print(f"Submitting task: {fn.__name__}")
return fn(*args, **kwargs)
graph.invoke(
{"messages": [{"role": "user", "content": "Hello"}]},
config={"configurable": {CONFIG_KEY_RUNNER_SUBMIT: my_submit}},
)
from langgraph.func import task, entrypoint
@task
def fetch_data(query: str) -> str:
return f"result for {query}"
@entrypoint()
def pipeline(query: str):
return fetch_data(query).result()
from langgraph.checkpoint.base import get_checkpoint_metadata
metadata = get_checkpoint_metadata(config)
# metadata contains only string/int/bool/float fields, private keys excluded
from langgraph.checkpoint.memory import InMemorySaver
saver = InMemorySaver()
# config["configurable"] non-private keys and config["metadata"] are now
# automatically merged into the stored checkpoint metadata by put()
config = {
"configurable": {
"thread_id": "thread-42",
"user_id": "alice",
"__private_key": "ignored", # filtered out
},
"metadata": {"session": "prod-run-1"},
}
# After graph.invoke(..., config=config), checkpoints stored by InMemorySaver
# will include thread_id, user_id, and session in their metadata.
graph.add_node("router", router_fn, destinations={"process": "to_process", "fallback": "to_fallback"})
graph.add_node("router", router_fn, destinations=("process", "fallback"))
from langgraph.store.base import IndexConfig
index_config = IndexConfig(
embed="openai:text-embedding-3-small",
dims=1536,
)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model=model,
tools=[search, calculator, lookup],
version="v2", # distributes tool calls via the Send API
)
result = agent.invoke({"messages": [{"role": "user", "content": "Compare prices and specs for X and Y"}]})
from langgraph.graph import StateGraph
builder = StateGraph(MyState)
# ... add nodes and edges ...
graph = builder.compile(name="research-agent")
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model=model,
tools=[search],
name="web-search-agent",
)
from langgraph.config import get_stream_writer
def my_node(state):
writer = get_stream_writer()
writer({"status": "starting scan", "targets": state["targets"]})
# ... do work ...
writer({"status": "complete", "findings": 42})
return state
from langgraph.config import get_store
def enrich_node(state):
store = get_store()
record = store.get("threat-intel", state["ioc"])
state["intel"] = record.value if record else {}
return state
from langgraph.prebuilt import ToolNode
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
tool_node = ToolNode(tools=[my_tool], store=store)
{
"graphs": {
"my_agent": "./agent.py:graph"
},
"auth": {
"path": "./auth/handler.py:auth"
}
}
from langgraph.func import task
@task(name="fetch_user_profile")
def _t(user_id: str) -> dict:
# your implementation
return {"id": user_id}
future = _t("u-123")
result = future.result()
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
agent = create_react_agent(
model=ChatOpenAI(model="gpt-4o"),
tools=[...],
prompt="You are a concise security analyst. Answer in bullet points.",
)
result = agent.invoke({"messages": [{"role": "user", "content": "Summarize CVE-2024-1234"}]})
from langgraph.func import entrypoint
@entrypoint(checkpointer=checkpointer)
def my_graph(input: str) -> entrypoint.final[str, dict]:
result = run_pipeline(input)
# Return the string to the caller; save the full dict to the checkpoint
return entrypoint.final(value=result["summary"], save=result)
from langgraph.utils.future import run_coroutine_threadsafe
import asyncio
loop = asyncio.get_event_loop()
future = run_coroutine_threadsafe(my_async_task(), loop)
result = future.result(timeout=30)
from langgraph.utils.runnable import RunnableSeq
seq = RunnableSeq(
step_a,
step_b,
trace_inputs=lambda x: {"sanitized_input": x["query"]},
)
result = seq.invoke({"query": "explain RBAC", "user_token": "s3cr3t"})
from langgraph.func import entrypoint, task
@task
def fetch_data(url: str):
...
@entrypoint()
def pipeline(input: dict):
return fetch_data(input["url"]).result()
# pipeline is now an EntrypointPregel
graph = pipeline.get_graph(xray=True)
graph.print_ascii()
from langgraph.config import get_store
@task
def save_result(key: str, value: str):
store = get_store()
store.put(("results",), key, {"value": value})
from langgraph.func import entrypoint
from pydantic import BaseModel
class MyConfig(BaseModel):
temperature: float = 0.7
max_tokens: int = 256
@entrypoint(config_schema=MyConfig)
def my_workflow(inputs: dict) -> str:
# config is validated against MyConfig before execution
...
from langgraph.func import entrypoint
@entrypoint()
def my_workflow(inputs: dict, previous: list | None = None) -> list:
history = previous or []
history.append(inputs["message"])
return history
subgraph = subgraph_builder.compile(checkpointer=True)
parent = parent_builder.compile(checkpointer=memory_checkpointer)
parent.add_node("sub", subgraph)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent("openai:gpt-4", tools)
await saver.aput_writes(config, writes, task_id, task_path="agent/subgraph")
saver.put_writes(config, writes, task_id, task_path="agent:tool_call")
await async_saver.aput_writes(config, writes, task_id, task_path="agent:tool_call")
saver.put_writes(config, writes, task_id, task_path="parent_task/child_task")
from pydantic import BaseModel
from langgraph.prebuilt import create_react_agent
class AgentAnswer(BaseModel):
answer: str
confidence: float
agent = create_react_agent(
model,
tools=[...],
response_format=AgentAnswer,
)
result = agent.invoke({"messages": [("user", "What is the capital of France?")]})
print(result["structured_response"]) # AgentAnswer(answer='Paris', confidence=0.99)
from typing import TypedDict
from langgraph.prebuilt import create_react_agent
class Summary(TypedDict):
key_findings: list[str]
risk_level: str
agent = create_react_agent(
model,
tools=[...],
response_format=(
"Extract the security findings and risk level from the conversation.",
Summary,
),
)
result = agent.invoke({"messages": [("user", "Analyze this log: ...")]})
print(result["structured_response"])
from langgraph.types import Command
updates = [("messages", new_message), ("turn_count", 5)]
cmd = Command(update=updates)
from langgraph.graph.message import add_messages
from typing import Annotated
from typing_extensions import TypedDict
class State(TypedDict):
messages: Annotated[list, add_messages(format="langchain-openai")]
from langgraph.func import task
@task
async def fetch_data(url: str, timeout: int = 30) -> dict:
# async I/O here
...
from langgraph_sdk.auth.types import StudioUser
def my_auth_handler(user, action, resource):
if isinstance(user, StudioUser):
raise PermissionError("Studio users cannot access this resource")
return True
{
"disable_studio_auth": true
}
from langgraph.types import Command
# Now valid: update can be any type, including None or a plain string
cmd = Command(goto="next_node", update="my_custom_payload")
from langchain_core.messages import ToolMessage
from langgraph.types import Command
# Both messages returned; validation passes because one has the matching tool_call_id
cmd = Command(
update={
"messages": [
ToolMessage(content="debug info", tool_call_id="other-id"),
ToolMessage(content="actual result", tool_call_id="call-123"),
]
}
)
from langgraph_sdk.auth import Auth
auth = Auth()
@auth.authenticate
async def authenticate(authorization: str) -> dict:
user_id = verify_token(authorization) # your token logic
return {"identity": user_id, "permissions": ["runs:create", "threads:read"]}
from langgraph_sdk import Auth
auth = Auth()
@auth.authenticate
async def my_auth_handler(token: str):
if not is_valid(token):
raise auth.exceptions.HTTPException(
status_code=403,
detail="You do not have permission to access this resource."
)
return {"user": decode(token)}
# langgraph.json
{
"auth": {
"path": "./my_auth.py:handler",
"disable_studio_auth": true
}
}
from langgraph_sdk import Auth
auth = Auth()
@auth.authenticate
async def verify_token(token: str):
# validate token and return user scopes
user = await my_token_validator(token)
return {"id": user.id, "scopes": user.scopes}
@auth.on
async def global_handler(ctx, value):
# allow only requests where the resource owner matches the caller
if ctx.user.id != value.get("owner"):
raise Auth.exceptions.HTTPException(status_code=403)
from langgraph_sdk import Auth
auth = Auth()
@auth.on.threads.read
async def restrict_thread_reads(ctx, value):
# inject a filter so the query only returns threads owned by the caller
return {"owner": ctx.user.id}
from langgraph.types import Command
# Previously required Send; now a plain string works
def my_node(state):
return Command(goto="approval_node")
from langgraph.utils.fields import get_enhanced_type_hints
# Get type hints plus defaults and descriptions for a config schema
hints = get_enhanced_type_hints(MyConfigSchema)
print(hints)
from langgraph.func import task, entrypoint
@task
def call_model_a(prompt: str) -> str:
return llm_a.invoke(prompt)
@task
def call_model_b(prompt: str) -> str:
return llm_b.invoke(prompt)
@entrypoint()
def compare_models(prompt: str) -> dict:
future_a = call_model_a(prompt)
future_b = call_model_b(prompt)
return {"a": future_a.result(), "b": future_b.result()}
result = compare_models.invoke("Explain quantum entanglement")
from langchain_core.tools import tool
from langgraph.types import Command
@tool
def escalate_to_human(reason: str) -> Command:
"""Escalate the conversation to a human agent."""
return Command(goto="human_node", update={"escalation_reason": reason})
# Register with ToolNode as usual — Command routing is handled automatically
from langgraph.prebuilt import ToolNode
tool_node = ToolNode([escalate_to_human])
async for chunk in client.stream(
assistant_id,
thread_id,
input=input_data,
params={"my_filter": "value", "limit": 10},
):
print(chunk)
from langgraph.types import Command, Send
cmd = Command(goto=[Send("node_a", {"x": 1}), "node_b"])
from langgraph.types import Command, Send
# Route to a named node and dynamically send a message to another node
cmd = Command(goto=["review_node", Send("process_node", {"input": data})])
from langgraph.types import interrupt
def my_node(state):
first_answer = interrupt("Please provide your name")
second_answer = interrupt("Please provide your role")
return {"name": first_answer, "role": second_answer}
from langgraph.types import Command
def subgraph_node(state):
# Direct this command at the parent graph instead of the current one
return Command(goto="some_parent_node", update={"status": "delegated"}, graph=Command.PARENT)
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
agent = create_react_agent(ChatOpenAI(model="gpt-4o"), tools=[])
result = agent.invoke({"messages": [{"role": "user", "content": "Summarise the history of cryptography."}]})
from langgraph.pregel.remote import RemoteGraph
from langgraph.types import Command
remote = RemoteGraph("my-deployed-graph", url="https://my-langgraph-server")
for chunk in remote.stream(Command(goto="review_node", update={"approved": True}), config={"thread_id": "abc123"}):
print(chunk)
runs = await client.runs.list(thread_id="<thread_id>", status="pending")
async for chunk in client.runs.join_stream(thread_id="<thread_id>", run_id="<run_id>", cancel_on_disconnect=True):
print(chunk)
async for chunk in client.assistants.stream(assistant_id="<assistant_id>", command=<command>):
print(chunk)
from langgraph.store.postgres.base import ANNIndexConfig, IVFFlatConfig
index_config = ANNIndexConfig(
kind="ivfflat",
ann_index_config=IVFFlatConfig(nlist=256),
)
langgraph dev --debug-port 5678 --wait-for-client
from langgraph_cli.config import IndexConfig, StoreConfig
store = StoreConfig(
index=IndexConfig(
dims=1536,
embed="openai:text-embedding-3-small",
fields=["text", "description"],
)
)
results = await client.store.search_items(namespace, query="latest customer complaints about billing")
for item in results.items:
print(item.score, item.key, item.value)
await client.store.put_item(namespace, key="user-42", value={"name": "Alice", "notes": "VIP customer", "internal_id": 99}, index=["name", "notes"])
await client.store.put_item(namespace, key="secret-config", value={"api_key": "s3cr3t"}, index=False)
from langgraph.store.memory import InMemoryStore
from langgraph.store.base import IndexConfig
from langchain_openai import OpenAIEmbeddings
store = InMemoryStore(
index=IndexConfig(
dims=1536,
embed=OpenAIEmbeddings(model="text-embedding-3-small"),
fields=["text", "summary"],
)
)
# Store an item (indexed by default)
await store.aput(("users", "alice"), "mem-1", {"text": "Alice prefers dark mode."})
# Retrieve semantically similar items
results = await store.asearch(("users", "alice"), query="UI preferences", limit=5)
for item in results:
print(item.key, item.score, item.value)
from langgraph.store.base.embed import ensure_embeddings
import numpy as np
def my_embed(texts: list[str]) -> list[list[float]]:
# Replace with your local model call
return [np.random.rand(768).tolist() for _ in texts]
embeddings = ensure_embeddings(my_embed)
from langgraph.store.base import IndexConfig
config = IndexConfig(dims=768, embed=embeddings)
results = await store.asearch(
("projects", "sec-team"),
query="privilege escalation techniques",
filter={"severity": {"$gt": 7}, "status": {"$eq": "open"}},
limit=10,
)
for item in results:
print(item.key, item.score, item.value["severity"])
namespaces = await store.alist_namespaces(prefix=("user", "alice"), depth=3, limit=50)
env:
OPENAI_API_KEY: "sk-..."
MY_CUSTOM_VAR: "value"
from langgraph_cli.config import validate_config_file
config = validate_config_file("langgraph.json")
langgraph dev --port 8123 --no-browser --config langgraph.json
pip install "langgraph-cli[inmem]"
from langgraph.checkpoint.memory import MemorySaver, PersistentDict
with MemorySaver(factory=lambda: PersistentDict("/tmp/checkpoints.pkl")) as saver:
# compile and run your graph with `saver` as the checkpointer
graph = my_graph.compile(checkpointer=saver)
graph.invoke({"messages": []}, config={"configurable": {"thread_id": "session-1"}})
await graph.aupdate_state(config, values=None, as_node=None)
graph.update_state(config, values=None, as_node=None)
langgraph new my-agent-project
langgraph dockerfile --add-docker-compose langgraph.json
from langgraph.checkpoint.serde.types import INTERRUPT, RESUME
# Check whether a checkpoint write corresponds to an interrupt or resume
def is_interrupt_write(write):
return write.channel in (INTERRUPT, RESUME)
async for chunk in client.runs.stream(
thread_id,
assistant_id,
command={"resume": "user_approved"},
stream_mode="messages-tuple",
):
print(chunk)
await client.runs.cancel(thread_id, run_id, action="rollback")
from langgraph.types import interrupt, Command
def review_node(state):
# Pause execution and surface data to the caller
decision = interrupt({"payload": state["draft"], "prompt": "Approve this draft?"})
# Execution resumes here once Command(resume=...) is issued
return {"approved": decision}
# From outside the graph, resume after the interrupt:
graph.invoke(Command(resume=True), config=config)
graph = StateGraph(MyState)
graph.add_sequence([
("ingest", ingest_node),
("analyze", analyze_node),
("summarize", summarize_node),
])
app = graph.compile()
subgraph = StateGraph(SubState)
subgraph.add_node("step", step_node)
subgraph.set_entry_point("step")
compiled_sub = subgraph.compile(checkpointer=False)
from langgraph.graph.state import GraphCommand
def router_node(state):
if state["needs_review"]:
return GraphCommand(goto="human_review", update={"routed": True})
return GraphCommand(goto="auto_approve")
from langgraph.types import Control
def router_node(state: dict) -> Control:
if state["score"] > 0.9:
return Control(goto="high_confidence_node", update={"routed": True})
else:
return Control(goto="low_confidence_node", update={"routed": True})
from langgraph.errors import ErrorCode
# The validation runs automatically inside create_react_agent;
# catch it explicitly to handle incomplete histories gracefully.
try:
result = agent.invoke({"messages": chat_history})
except ValueError as e:
if ErrorCode.INVALID_CHAT_HISTORY in str(e):
print("Chat history has unmatched tool calls:", e)
from langgraph.pregel.remote import RemoteGraph
remote = RemoteGraph(graph_id="my-graph", url="https://my-deployment.example.com")
for chunk in remote.stream({"messages": []}, stream_mode="messages-tuple"):
print(chunk)
from langgraph.pregel.remote import RemoteGraph
remote = RemoteGraph("my-remote-graph", url="http://localhost:8000")
# When invoked as a subgraph, RemoteGraph now inherits and propagates
# the parent graph's stream modes and namespace context automatically.
async for chunk in remote.astream(
{"input": "hello"},
config={"configurable": {"thread_id": "abc"}},
stream_mode="updates",
):
print(chunk)
tool_node = ToolNode(tools, messages_key="chat_history")
condition = tools_condition(messages_key="chat_history")
from langgraph.prebuilt import ToolNode
tool_node = ToolNode(
tools,
handle_tool_errors=(ValueError, KeyError), # only catch these types
)
# — or use a callable for dynamic formatting —
tool_node = ToolNode(
tools,
handle_tool_errors=lambda exc: f"Tool failed: {type(exc).__name__}: {exc}",
)
result = await client.wait(thread_id, run_id, raise_error=False)
if "__error__" in result:
print("Run failed:", result["__error__"])
async for chunk in client.runs.stream(
thread_id=user_thread_id,
assistant_id="my-assistant",
input={"messages": [{"role": "user", "content": "Hello"}]},
if_not_exists="create",
):
print(chunk)
result = await client.runs.wait(
thread_id=incoming_thread_id,
assistant_id="my-assistant",
input={"messages": [{"role": "user", "content": "Continue"}]},
if_not_exists="reject", # raises if thread_id not found
)
from langgraph.constants import TAG_NOSTREAM
# When binding or invoking a chat model you want kept off the stream,
# pass TAG_NOSTREAM as a tag so StreamMessagesHandler skips it.
silent_model = llm.with_config({"tags": [TAG_NOSTREAM]})
# Use silent_model inside a node as normal — its tokens won't be streamed.
def my_node(state):
result = silent_model.invoke(state["messages"])
return {"messages": [result]}
from langgraph.errors import ErrorCode
from langgraph.errors import GraphRecursionError
try:
graph.invoke(inputs)
except GraphRecursionError as e:
if ErrorCode.GRAPH_RECURSION_LIMIT.value in str(e):
# surface a user-friendly message or increase recursion_limit
print("Graph hit recursion limit — consider increasing recursion_limit or breaking cycles.")
from langgraph.managed import RemainingSteps
def agent_node(state, remaining_steps: RemainingSteps):
if remaining_steps < 2:
# Not enough headroom — return a safe fallback instead of calling tools
return {"messages": [AIMessage(content="Stopping early: too few steps remaining.")]}
# ... normal tool-calling logic
return model_with_tools.invoke(state["messages"])
from langgraph.pregel.remote import RemoteGraph
remote_graph = RemoteGraph(
url="https://my-deployment.langgraph.app",
api_key="<your-api-key>",
graph_id="my-graph"
)
async for chunk in remote_graph.astream({"input": "Hello"}):
print(chunk)
response = await client.threads.update_state(
thread_id=thread_id,
values={"messages": [{"role": "assistant", "content": "Corrected reply"}]},
)
print(response) # ThreadUpdateStateResponse with checkpoint info
async for chunk in client.runs.stream(
thread_id=thread_id,
assistant_id=assistant_id,
input={"messages": [{"role": "user", "content": "Hello"}]},
stream_mode=["messages", "custom"],
):
print(chunk)
from langgraph.pregel.utils import find_subgraph_pregel
subgraph = find_subgraph_pregel(my_runnable)
if subgraph:
print("Found Pregel subgraph:", subgraph)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model=llm,
tools=tools,
checkpointer=checkpointer, # single-thread (per-conversation) state
store=store, # cross-thread (multi-user) persistence
)
from typing import Annotated
from langgraph.prebuilt.tool_node import InjectedStore
from langgraph.store.base import BaseStore
def save_note(note: str, store: Annotated[BaseStore, InjectedStore()]) -> str:
"""Save a note to the store."""
store.put(("notes",), "latest", {"text": note})
return "Saved."
from langgraph_sdk import get_client
client = get_client()
# Store a user preference
await client.store.put_item(
namespace=("users", "alice"),
key="preferences",
value={"theme": "dark", "language": "en"}
)
# Retrieve it later
item = await client.store.get_item(
namespace=("users", "alice"),
key="preferences"
)
print(item["value"])
from langgraph_sdk import get_client
client = get_client()
results = await client.store.search_items(
namespace_prefix=("users",),
filter={"language": "en"}
)
for item in results["items"]:
print(item["namespace"], item["key"], item["value"])
from langgraph_sdk import get_sync_client
client = get_sync_client()
namespaces = client.store.list_namespaces(prefix=("users",))
for ns in namespaces["namespaces"]:
print(ns)
import json
from decimal import Decimal
from langgraph.store.postgres import PostgresStore
def my_deserializer(data: str):
return json.loads(data, parse_float=Decimal)
store = PostgresStore(conn_string="postgresql://user:pass@localhost/db", deserializer=my_deserializer)
import json
from langgraph.store.postgres.aio import AsyncPostgresStore
def my_deserializer(data: str):
return json.loads(data, object_hook=lambda d: {k: v.upper() if isinstance(v, str) else v for k, v in d.items()})
store = AsyncPostgresStore(conn_string="postgresql://user:pass@localhost/db", deserializer=my_deserializer)
from langgraph.store.postgres import PostgresStore
with PostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb") as store:
store.setup() # create tables and run migrations
store.put(("agents", "session-42"), "state", {"step": 1, "status": "running"})
item = store.get(("agents", "session-42"), "state")
print(item)
import asyncio
from langgraph.store.postgres.aio import AsyncPostgresStore
async def main():
async with AsyncPostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb") as store:
await store.setup()
await store.put(("sessions", "user-99"), "context", {"history": []})
results = await store.search(("sessions",))
print(results)
asyncio.run(main())
from langgraph.prebuilt import create_react_agent
# model_like is any LanguageModelLike, not necessarily a BaseChatModel
agent = create_react_agent(model=model_like, tools=[my_tool])
result = agent.invoke({"messages": [{"role": "user", "content": "Search for X"}]})
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
# Store a user fact under a namespaced key
store.put(("users", "alice"), "preference", {"theme": "dark"})
# Retrieve it later
item = store.get(("users", "alice"), "preference")
print(item.value) # {"theme": "dark"}
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
store.put(("sessions", "s1"), "summary", {"turns": 5})
store.put(("sessions", "s2"), "summary", {"turns": 12})
results = store.search(("sessions",))
for item in results:
print(item.namespace, item.key, item.value)
subgraphs = list(graph.get_subgraphs(namespace="my_agent"))
from langgraph.prebuilt import ToolNode
from langchain_core.tools import tool
@tool
def capture_screenshot(url: str) -> list:
"""Capture a screenshot and return it as image content."""
image_bytes = fetch_screenshot(url) # your existing logic
return [{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": image_bytes}}]
node = ToolNode([capture_screenshot])
await client.assistants.set_latest(assistant_id="asst_abc123", version=3)
versions = await client.assistants.get_versions(assistant_id="asst_abc123")
for v in versions:
print(v.version, v.config)
await client.runs.create(thread_id="thread_xyz", assistant_id="asst_abc123", after_seconds=60)
from langgraph.types import Send, Interrupt
for chunk in graph.stream(inputs, stream_mode="messages"):
print(chunk)
# Inside a node definition:
def my_node(state, *, write):
write({"status": "halfway done"})
return state
# Consuming the stream:
for chunk in graph.stream(inputs, stream_mode="custom"):
print(chunk)
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from my_project.serializers import MyCustomSerde
async with AsyncPostgresSaver.from_conn_string(
"postgresql://user:pass@localhost/mydb",
serde=MyCustomSerde(),
) as saver:
await saver.setup()
# attach saver to your compiled graph
graph = workflow.compile(checkpointer=saver)
from langgraph.utils.pydantic import create_model
from langgraph.graph import StateGraph
MyState = create_model('MyState', messages=(list, []), step=(int, 0))
graph = StateGraph(state_schema=MyState)
from dataclasses import dataclass, field
from langgraph.graph import StateGraph
@dataclass
class AgentState:
messages: list = field(default_factory=list)
step: int = 0
graph = StateGraph(AgentState)
from langgraph.prebuilt import ToolNode
node = ToolNode(tools=[my_tool])
print(node.name) # "ToolNode"
from pydantic import BaseModel
from langgraph.prebuilt import ToolNode
from langchain_core.tools import tool
class AgentState(BaseModel):
messages: list
user_id: str
@tool
def lookup_user(user_id: str) -> str:
"""Look up a user by ID."""
return f"User: {user_id}"
node = ToolNode([lookup_user])
# AgentState instance is now passed directly — ToolNode reads fields via getattr
result = node.invoke(AgentState(messages=[...], user_id="u-123"))
from langgraph.errors import TaskNotFound
try:
result = await pregel_loop.execute_task(task_id)
except TaskNotFound:
print(f"Task {task_id} no longer exists in the execution graph")
from langgraph.utils.fields import get_field_default
from typing import Optional
from pydantic import BaseModel
class MyState(BaseModel):
messages: list = []
user_id: Optional[str] = None
default = get_field_default(MyState.model_fields["messages"])
print(default) # []
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
async def setup():
saver = await AsyncPostgresSaver.from_conn_string("postgresql://user:pass@localhost/db")
return saver
# In a synchronous context:
import asyncio
saver = asyncio.run(setup())
# Now call sync wrappers directly from sync code:
checkpoint_tuple = saver.get_tuple(config)
all_checkpoints = list(saver.list(config))
saver.put(config, checkpoint, metadata, new_versions)
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
saver = AsyncSqliteSaver.from_conn_string("checkpoints.db")
# Synchronous put now works without wrapping in asyncio.run()
saver.put(config, checkpoint, metadata, new_versions)
# Synchronous put_writes also available
saver.put_writes(config, writes, task_id)
from langgraph.prebuilt import ToolNode, create_react_agent
shared_tool_node = ToolNode([search_tool, calculator_tool])
agent_a = create_react_agent(model_a, shared_tool_node)
agent_b = create_react_agent(model_b, shared_tool_node)
from langgraph.graph import StateGraph, END
builder = StateGraph(MyState)
builder.add_node("analyze", analyze_fn)
builder.add_edge("analyze", END) # No explicit add_node(END) needed
graph = builder.compile()
threads = await client.threads.search(values={"topic": "billing", "status": "open"})
final_state = await client.runs.join(thread_id, run_id)
print(final_state)
{
"node_version": "20",
"graphs": {
"my_graph": "./src/graph.ts:graph"
}
}
from psycopg_pool import ConnectionPool
from langgraph.checkpoint.postgres import PostgresSaver
pool = ConnectionPool("postgresql://user:password@localhost/db", min_size=2, max_size=10)
saver = PostgresSaver(pool)
from psycopg_pool import AsyncConnectionPool
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
pool = AsyncConnectionPool("postgresql://user:password@localhost/db", min_size=2, max_size=10)
saver = AsyncPostgresSaver(pool)
async for chunk in client.runs.join_stream(thread_id, run_id):
print(chunk)
async for chunk in client.runs.stream(
thread_id,
assistant_id,
input=input_data,
on_disconnect="cancel",
on_completion="delete",
):
print(chunk)
run = await client.runs.create(
thread_id,
assistant_id,
input=input_data,
on_completion="keep",
)
from langgraph.managed.base import ManagedValue
class MyRuntimeValue(ManagedValue, runtime=True):
...
from langgraph.checkpoint.serde.types import ERROR
# In a custom checkpointer's put_writes, tag a failed write with the ERROR sentinel
writes = [(ERROR, exception_value)]
await checkpointer.put_writes(config, writes, task_id)
for chunk in graph.stream(inputs, stream_mode="debug"):
if chunk["type"] == "task_result":
payload = chunk["payload"]
if payload["error"]:
print("Task error:", payload["error"])
if payload["interrupts"]:
print("Interrupts:", payload["interrupts"])
from langgraph_sdk import get_client
client = get_client(
url="https://your-langgraph-endpoint",
headers={"x-tenant-id": "acme-corp", "x-trace-id": "abc123"},
)
state = await client.threads.get_state(
thread_id="<thread_id>",
checkpoint_id="<checkpoint_id>",
checkpoint_ns="pipeline-a",
)
from langgraph.graph.state import StateGraph
from langgraph.managed.shared_value import SharedValue
from langgraph.store.memory import MemoryStore
store = MemoryStore()
graph = StateGraph(...)
# SharedValue field is accessible and writable by all nodes
graph.add_node("node_a", node_a_fn)
graph.add_node("node_b", node_b_fn)
app = graph.compile(store=store)
from langgraph.store.memory import MemoryStore
from langgraph.store.batch import AsyncBatchedStore
batched_store = AsyncBatchedStore(MemoryStore())
app = graph.compile(store=batched_store)
from langgraph.managed.base import is_writable_managed_value, is_readonly_managed_value
if is_writable_managed_value(my_value):
await my_value.aupdate(new_data)
elif is_readonly_managed_value(my_value):
print("This value cannot be updated")
from langgraph.errors import NodeInterrupt
def review_node(state):
if state["needs_approval"]:
raise NodeInterrupt("Waiting for human approval before proceeding")
return state
from langgraph.errors import GraphInterrupt
try:
result = graph.invoke(inputs)
except GraphInterrupt as e:
for interrupt in e.interrupts:
print(f"Interrupted {interrupt.when}: {interrupt.value}")
snapshot = await graph.aget_state(config)
for task in snapshot.tasks:
if task.error is not None:
print(f"Task {task.id} failed with: {task.error}")
from langgraph.checkpoint.postgres import PostgresSaver
with PostgresSaver.from_conn_string("postgresql://user:pass@localhost/db") as saver:
saver.setup() # applies all pending MIGRATIONS instead of recreating tables
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
async with AsyncPostgresSaver.from_conn_string("postgresql://user:pass@localhost/db") as saver:
await saver.setup() # applies MIGRATIONS for the async variant
from langgraph.checkpoint.sqlite import SqliteSaver
with SqliteSaver.from_conn_string("./local_state.db") as checkpointer:
graph = app.compile(checkpointer=checkpointer)
result = graph.invoke(
{"messages": ["Hello"]},
config={"configurable": {"thread_id": "dev-session-1"}}
)
from langgraph.checkpoint.memory import MemorySaver
with MemorySaver() as saver:
# saver is fully initialised; resources released on exit
checkpoints = list(saver.list(config))
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
serde = JsonPlusSerializer()
type_tag, encoded = serde.dumps_typed(b"\x89PNG\r\n")
restored = serde.loads_typed((type_tag, encoded))
assert isinstance(restored, bytes)
from langgraph_sdk import get_client
client = get_client() # url is now optional
assistant = await client.assistants.create(
graph_id="my_graph",
config={"configurable": {"model": "gpt-4o"}},
if_exists="return_existing",
)
new_thread = await client.threads.copy(thread_id="<thread_id>")
graph.update_state(config, values=None)
from typing import Annotated
from langgraph.prebuilt.tool_node import InjectedState
from langchain_core.tools import tool
class AgentState(TypedDict):
messages: list
user_id: str
@tool
def lookup_policy(
topic: str,
state: Annotated[AgentState, InjectedState()],
) -> str:
"""Look up company policy, scoped to the current user."""
user_id = state["user_id"] # injected automatically; model never sees it
return fetch_policy(topic, user_id)
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
def modify_state(state):
# state is the full graph state, not just messages
return [{"role": "system", "content": "You are a helpful security analyst."}] + state["messages"]
agent = create_react_agent(
model=ChatOpenAI(model="gpt-4o"),
tools=[...],
state_modifier=modify_state,
)
from typing import TypedDict, Annotated
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import operator
class MyAgentState(TypedDict):
messages: Annotated[list, operator.add]
user_role: str # custom field
session_id: str # custom field
agent = create_react_agent(
model=ChatOpenAI(model="gpt-4o"),
tools=[...],
state_schema=MyAgentState,
)
langgraph dockerfile --config langgraph.json --output Dockerfile
crons = await client.crons.search(assistant_id="asst-abc", limit=20, offset=0)
graph.add_node("my_agent", my_runnable, metadata={"team": "red-team", "criticality": "high"})
from langgraph.checkpoint.sqlite import SqliteSaver
checkpointer = SqliteSaver.from_conn_string('checkpoints.db')
# During a custom checkpointer integration, flush task writes explicitly:
checkpointer.put_writes(config, writes, task_id)
from langgraph.prebuilt import ToolNode
tool_node = ToolNode(tools=[my_tool], handle_tool_errors=False)
from langchain_core.messages import RemoveMessage
# Return a RemoveMessage from a node to delete the message with the given ID
def cleanup_node(state):
return {"messages": [RemoveMessage(id="msg-abc123")]}
langgraph dev --debugger-base-url https://my-dev-server.example.com:8123
langgraph test Summary
LangGraph is an open-source, MIT-licensed orchestration framework for building stateful, long-running agents, distributed as a Python library (with a JS/TS equivalent) that you install with pip and import directly into application code rather than run as a standalone service. It handles durable execution, letting agents persist through failures and resume where they left off, and supports human-in-the-loop steps for inspecting or modifying agent state mid-run, plus checkpointed state history and streaming APIs for observability. It's aimed at developers building agentic applications rather than end users, and the README points to Deep Agents as a higher-level package built on top of it for those wanting more scaffolding out of the box. Backed by LangChain, it has 320 contributors, over 1,700 commits in the past year, and a release 22 days ago, indicating active development.
LangGraph is a framework for building stateful, multi-actor applications using language models with cyclic computational graphs.
What LangGraph answers
What happens to a long-running agent if the process crashes partway through?
node-level error handlers catch failures where they occur, and execution can resume from the last checkpoint after a host crash instead of restarting the whole run
Do I need to run a separate server to use this?
no — it is a library you install and import into application code, though a CLI can deploy graphs to a hosted studio if you want that later
How do I watch what an agent is doing while it runs?
streaming APIs expose node-level events, message and tool-call output, and full write-history retrieval for a thread, over either SSE or WebSocket
Will checkpoint storage keep growing as an agent runs for a long time?
state is stored as incremental deltas rather than full snapshots at every step, with periodic forced snapshots so replay never has an unbounded gap
Can I connect an agent's execution to a system outside the process it runs in?
remote graph execution supports the same streaming protocol as local runs, so a graph invoked over the network still gives real-time output
Examples
Command line
No option matches that search.
| option | found in | since | description |
|---|
No option matches that search.
Values are placeholders taken from each option’s declared default. Nothing is executed here — the output shown is a recording of a run that already happened.
Release history
- sdk==0.4.4
LangGraph SDK 0.4.4 routes LangSmith traces from thread streams for deeper agent observability.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.4.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.4.4
- ›Routes LangSmith traces from thread streams, enabling trace visibility for streaming thread operations.
- sdk==0.4.3
LangGraph SDK 0.4.3 adds decrypted replacement results and clears cron end_time via update(end_time=None).
└──▷ GET THIS VERSION$ git clone --branch sdk==0.4.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.4.3
- ›Supports clearing a cron job's
end_timeby calling update(end_time=None) on the cron client. - ›Adds decrypt replacement result support to the Python SDK.
- ›Supports clearing a cron job's
- 1.2.11
LangGraph 1.2.11 exposes
trace_policyonadd_nodefor per-node tracing control.└──▷ GET THIS VERSION$ git clone --branch 1.2.11 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.11
└──▷ USE ITSuppress or customize tracing for a specific node without affecting the rest of the graph.graph.add_node("my_node", my_node_fn, trace_policy=<policy>)- ›Adds
trace_policyparameter toadd_node, letting callers control tracing behavior on a per-node basis.
- ›Adds
- 1.2.11
LangGraph 1.2.11 exposes
trace_policyonadd_nodefor per-node tracing control.└──▷ GET THIS VERSION$ git clone --branch 1.2.11 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.11
- ›Adds
trace_policyparameter toadd_nodeto control tracing behaviour on a per-node basis.
- ›Adds
- checkpoint==4.2.0
LangGraph checkpoint 4.2.0 adds opt-in
omit_expiredflag to skip expired rows on checkpoint reads.└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.2.0
- ›Adds
omit_expiredopt-in parameter to checkpoint and checkpoint-postgres read operations to skip expired rows, enabling cleaner state retrieval without stale data.
- ›Adds
- checkpoint==4.2.0
LangGraph checkpoint 4.2.0 adds opt-in
omit_expiredflag to skip expired checkpoint rows on read.└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.2.0
- ›Adds opt-in
omit_expiredparameter to checkpoint and checkpoint-postgres readers to skip expired rows when reading checkpoint history, reducing noise and improving read performance in long-running workflows.
- ›Adds opt-in
- checkpoint==4.2.0
LangGraph checkpoint 4.2.0 adds opt-in
omit_expiredflag to skip expired checkpoint rows on read.└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.2.0
- ›Adds opt-in
omit_expiredparameter to checkpoint and checkpoint-postgres readers to skip expired rows when reading checkpoint history, reducing noise and improving read performance in long-running workflows.
- ›Adds opt-in
- checkpointpostgres==3.1.1
LangGraph checkpoint-postgres 3.1.1 adds opt-in
omit_expiredflag to skip expired checkpoint rows on read.└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.1.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.1.1
- ›Adds
omit_expiredopt-in parameter to checkpoint reads, allowing callers to skip expired rows instead of returning them.
- ›Adds
- checkpointpostgres==3.1.1
checkpoint-postgres 3.1.1 adds opt-in
omit_expiredflag to skip expired checkpoint rows on read.└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.1.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.1.1
- ›Adds opt-in
omit_expiredparameter to checkpoint read operations, allowing callers to skip expired rows and avoid processing stale state.
- ›Adds opt-in
- checkpointpostgres==3.1.1
checkpoint-postgres 3.1.1 adds opt-in
omit_expiredflag to skip expired checkpoint rows on read.└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.1.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.1.1
- ›Adds opt-in
omit_expiredparameter to checkpoint read operations, allowing callers to skip expired rows and avoid processing stale state.
- ›Adds opt-in
- 1.2.10
LangGraph 1.2.10 adds
trace_policyonadd_nodeand typed v3stream_eventsreturn with native projections.└──▷ GET THIS VERSION$ git clone --branch 1.2.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.10
└──▷ USE ITAttach atrace_policyto a specific node to control how that node's execution is traced, without affecting the rest of the graph.graph.add_node('my_node', my_node_fn, trace_policy=TracePolicy(...))- ›Exposes
trace_policyparameter onadd_node, letting you control tracing behavior per node when building graphs. - ›Types the v3
stream_eventsreturn value and adds native projections, enabling strongly-typed streaming event handling.
- ›Exposes
- 1.2.10
LangGraph 1.2.10 exposes
trace_policyonadd_nodeand drops tags from TracePolicy for cleaner tracing control.└──▷ GET THIS VERSION$ git clone --branch 1.2.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.10
└──▷ USE ITAttach a per-node trace policy at graph construction time to control which nodes are traced in production.graph.add_node('my_node', my_node_fn, trace_policy=TracePolicy(...))- ›Exposes
trace_policyparameter onadd_node, letting callers set per-node tracing behavior directly when wiring the graph. - ›Drops
tagsfromTracePolicy, narrowing the tracing configuration surface. - ›Adds typed return for v3
stream_eventsand native projections support.
└──▷ BREAKING ON UPGRADE- !The
tagsfield has been removed fromTracePolicy; any code that setstagson aTracePolicyinstance will break.
- ›Exposes
- cli==0.4.31
LangGraph CLI now supports prebuild images for langgraph deploy.
└──▷ GET THIS VERSION$ git clone --branch cli==0.4.31 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.31
- ›Supports prebuild images for
langgraph deploy, enabling faster deployments by skipping the image build step.
- ›Supports prebuild images for
- 1.2.3
LangGraph 1.2.3 adds v3 streaming support, WebSocket transport, and tool-dispatched subagent naming to RemoteGraph.
└──▷ GET THIS VERSION$ git clone --branch 1.2.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.3
- ›Adds v3 streaming support to
RemoteGraph, enabling the latest streaming protocol for remote graph execution. - ›Wires
RemoteGraph.interleavetosdk-pyinterleave_projectionsfor interleaved stream output. - ›Names tool-dispatched subagents via
lc_agent_namefor clearer agent identification in multi-agent graphs. - ›Adds WebSocket stream transport to the Python SDK (
sdk-py) as an alternative to SSE. - ›Adds
messagesand tool call projections tosdk-pyfor structured stream consumption.
+1 moreshow less
- ›Adds v3 streaming primitives and SSE transport to
sdk-py.
- ›Adds v3 streaming support to
- sdk==0.4.1
LangGraph SDK 0.4.1 adds interleave_projections stream decoder and v3 streaming support for RemoteGraph.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.4.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.4.1
- ›Extracts stream decoders into a reusable module and adds
interleave_projectionsstream decoder. - ›Adds v3 streaming protocol support to
RemoteGraph, enabling richer real-time output from remote graph execution.
- ›Extracts stream decoders into a reusable module and adds
- sdk==0.4.0
LangGraph SDK 0.4.0 adds WebSocket streaming, reconnect resilience, scoped subgraph handles, and sync/async thread stream helpers.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.4.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.4.0
- ›Adds WebSocket stream transport support, enabling lower-latency bidirectional streaming as an alternative to SSE.
- ›Adds SSE transport and v3 streaming primitives as a foundational streaming layer.
- ›Adds WebSocket stream selection wiring so clients can choose between SSE and WebSocket transports.
- ›Adds async stream reconnect support with hardened reconnect logic for resilient long-running streams.
- ›Adds async and sync thread stream helpers for high-level, ergonomic consumption of streamed thread output.
+4 moreshow less
- ›Adds scoped subgraph handles (async and sync) for targeting and streaming specific subgraph execution.
- ›Adds messages and tool call projections to extract structured message and tool-call data from stream events.
- ›Adds output, values, and controller extraction from stream lifecycle state.
- ›Adds shared stream subscriptions for multiplexing a single stream across multiple consumers.
- sdk==0.3.15
LangGraph SDK 0.3.15 adds metadata filtering for cron job search and count operations.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.15 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.15
└──▷ USE ITFilter cron job searches by metadata to find only crons matching specific labels or properties.crons = await client.crons.search(metadata={"env": "production", "team": "infra"})- ›Supports metadata filter parameter when searching and counting cron jobs via the SDK.
- 1.2.1
LangGraph 1.2.1 adds
before_builtinsopt-in for stream transformers.└──▷ GET THIS VERSION$ git clone --branch 1.2.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.1
- ›Adds
before_builtinsopt-in option for stream transformers, enabling custom transformation logic to run before built-in stream processing.
- ›Adds
- 1.2.0
LangGraph 1.2.0 adds node defaults, durable error-handler resume, and delta-channel snapshot guarantees.
└──▷ GET THIS VERSION$ git clone --branch 1.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.0
└──▷ USE ITApply shared defaults (e.g. a model or retry policy) to every node in a graph without repeating config on each .add_node() call.from langgraph.graph import StateGraph builder = StateGraph(MyState) builder.set_node_defaults(config={"model": "gpt-4o", "temperature": 0}) builder.add_node("extract", extract_node) builder.add_node("summarize", summarize_node)- ›Adds set_node_defaults() to
StateGraph, letting you set shared default configuration across nodes. - ›Enables durable error-handler resume so graph execution can recover across host crashes.
- ›Forces a delta channel snapshot after a configurable max number of supersteps since the last snapshot, preventing unbounded replay.
- ›Overrides
get_delta_channel_historyin the SQLite checkpoint backend with a streaming walk for more efficient history retrieval.
- ›Adds set_node_defaults() to
- checkpoint==4.1.0
LangGraph checkpoint 4.1.0 forces delta channel snapshots after max supersteps to ensure durability.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.1.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.1.0
- ›Adds forced delta channel snapshot after a configurable maximum number of supersteps since the last snapshot, preventing unbounded checkpoint gaps.
- cli==0.4.25
LangGraph CLI gains Studio deploy support for pushing graphs directly to LangGraph Studio.
└──▷ GET THIS VERSION$ git clone --branch cli==0.4.25 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.25
- ›Adds
studio deploycommand to the LangGraph CLI, enabling direct deployment to LangGraph Studio.
- ›Adds
- checkpointsqlite==3.1.0a1
LangGraph SQLite checkpointer gains a public get_writes_history API and streaming delta channel history.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==3.1.0a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==3.1.0a1
- ›Adds public
get_writes_historysaver API for retrieving write history with reworked delta cadence. - ›Overrides
get_delta_channel_historywith a streaming walk implementation for more efficient history retrieval.
- ›Adds public
- sdk==0.3.14
LangGraph SDK 0.3.14 adds
return_minimalto thread updates, trimming response payload size.└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.14 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.14
└──▷ USE ITReduce response payload size when updating a thread — useful in high-throughput pipelines where the full thread object is not needed.client.threads.update(thread_id, return_minimal=True)
- ›Adds
return_minimalparameter to the threads update API, allowing callers to request a reduced response payload.
- ›Adds
- checkpointpostgres==3.1.0a4
langgraph-checkpoint-postgres 3.1.0a4 exposes a public
get_writes_historysaver API with reworked delta cadence.└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.1.0a4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.1.0a4
└──▷ USE ITRetrieve the full write history for a thread to audit or replay state transitions stored in Postgres.history = await saver.get_writes_history(config)
- ›Adds public
get_writes_historyAPI on the checkpoint saver, enabling programmatic retrieval of write history for a thread. - ›Reworks delta cadence logic for checkpoint writes, enabling finer-grained control over how incremental state changes are persisted.
- ›Adds public
- prebuilt==1.1.0a1
LangGraph prebuilt 1.1.0a1 adds stream_events v3 dispatch and streaming transformer infrastructure.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.1.0a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.1.0a1
- ›Dispatches stream_events(version='v3') on Pregel, enabling finer-grained streaming event visibility.
- ›Adds streaming transformer infrastructure, providing a new layer for composing and testing stream transformations in the graph runtime.
- 1.2.0a3
LangGraph 1.2.0a3 adds node-level error handlers, graceful shutdown/drain, stream_events v3, and richer streaming infrastructure.
└──▷ GET THIS VERSION$ git clone --branch 1.2.0a3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.0a3
└──▷ USE ITSubscribe to v3 stream events from a Pregel graph for fine-grained observability of node execution.# (Python) — stream_events v3 async for event in graph.astream_events(input, version='v3'): print(event)Return a mix of Commands and ToolMessages from a ToolNode tool to drive conditional graph routing alongside structured output.from langgraph.prebuilt import ToolNode from langgraph.types import Command from langchain_core.messages import ToolMessage def my_tool(tool_call_id: str, query: str) -> list: return [ ToolMessage(content="result", tool_call_id=tool_call_id), Command(goto="follow_up_node"), ] node = ToolNode([my_tool])- ›Adds node-level error handlers, letting graphs catch and handle errors at individual nodes rather than propagating them globally.
- ›Supports graceful graph shutdown/drain on request, allowing in-flight work to complete cleanly before termination.
- ›Dispatches stream_events(version='v3') on Pregel graphs, enabling richer event streaming for observability pipelines.
- ›Introduces
DeltaChannelfor storing sentinels in blobs and reconstructing state from checkpoint writes. - ›Adds native v2 projections for
custom,updates,checkpoints,debug, andtasksstream modes.
+2 moreshow less
- ›Introduces streaming transformer infrastructure for composable, testable stream processing.
- ›Allows
ToolNodetools to returnlist[Command | ToolMessage], enabling richer tool output patterns.
- checkpoint==4.1.0a3
LangGraph checkpoint 4.1.0a3 introduces DeltaChannel with sentinel storage and checkpoint_writes reconstruction.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.1.0a3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.1.0a3
- ›Adds
DeltaChannel: stores sentinels in blobs and reconstructs state fromcheckpoint_writes, enabling more efficient incremental state tracking.
- ›Adds
- 1.2.0a2
LangGraph 1.2.0a2 adds node-level error handlers for fine-grained fault control in graphs.
└──▷ GET THIS VERSION$ git clone --branch 1.2.0a2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.0a2
- ›Adds node-level error handlers, enabling per-node fault handling logic directly in graph definitions.
- checkpointpostgres==3.1.0a1
checkpoint-postgres 3.1.0a1 adds DeltaChannel sentinel storage in blobs with checkpoint_writes reconstruction.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.1.0a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.1.0a1
- ›Adds
DeltaChannelsupport: stores sentinel values in blobs and reconstructs state fromcheckpoint_writes, enabling more efficient incremental checkpointing.
- ›Adds
- prebuilt==1.0.13
LangGraph prebuilt 1.0.13 adds alpha timer support and streaming transformer infrastructure.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.13
- ›Introduces alpha timer support for scheduling and time-based graph behaviors.
- ›Adds streaming transformer infrastructure enabling new streaming pipeline patterns in graphs.
- checkpoint==4.1.0a1
LangGraph checkpoint 4.1.0a1 adds timer support (alpha) and a new DeltaChannel for efficient checkpoint reconstruction.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.1.0a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.1.0a1
- ›Adds alpha timer support for checkpoint-based workflows.
- ›Introduces
DeltaChannel: stores sentinel values in blobs and reconstructs state fromcheckpoint_writesrather than full snapshots.
- 1.2.0a1
LangGraph 1.2.0a1 adds graceful shutdown/drain, timer support, DeltaChannel checkpointing, and native v2 streaming projections.
└──▷ GET THIS VERSION$ git clone --branch 1.2.0a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.2.0a1
- ›Adds graceful shutdown/drain support, allowing graphs to finish in-flight work before stopping on request.
- ›Introduces alpha timer primitives for scheduling time-based graph behavior.
- ›New
DeltaChannelstores sentinel values in blobs and reconstructs state from checkpoint writes. - ›Adds native v2 projections for custom, updates, checkpoints, debug, and tasks streams.
- ›Adds streaming transformer infrastructure enabling richer, composable stream processing pipelines.
- 1.1.10
LangGraph 1.1.10 lets ToolNode tools return mixed lists of Command and ToolMessage objects.
└──▷ GET THIS VERSION$ git clone --branch 1.1.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.10
└──▷ USE ITWhen a tool needs to both update graph state (via Command) and return a ToolMessage to the model in the same invocation.from langgraph.prebuilt import ToolNode from langgraph.types import Command from langchain_core.messages import ToolMessage def my_tool(tool_call_id: str, query: str) -> list: # Emit a state update command AND a tool result message return [ Command(update={"retrieved": query}), ToolMessage(content=f"Result for {query}", tool_call_id=tool_call_id), ] node = ToolNode([my_tool])- ›Enables ToolNode tools to return
list[Command | ToolMessage], allowing a single tool call to emit both control-flow commands and tool messages in one response.
- ›Enables ToolNode tools to return
- prebuilt==1.0.11
LangGraph prebuilt 1.0.11 lets ToolNode return mixed Command/ToolMessage lists and exposes available tools on ToolRuntime.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.11 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.11
└──▷ USE ITReturn a mix of graph-control Commands and ToolMessages from a single tool — useful when a tool needs to both update state and produce an observable message.from langgraph.prebuilt import ToolNode from langgraph.types import Command from langchain_core.messages import ToolMessage def my_tool(tool_call_id: str, query: str) -> list: # Return a Command to update state AND a ToolMessage for the model return [ Command(update={"retrieved": query}), ToolMessage(content=f"Searched for: {query}", tool_call_id=tool_call_id), ] node = ToolNode([my_tool])- ›Enables ToolNode tools to return
list[Command | ToolMessage], allowing a single tool call to emit a mix of graph commands and tool messages. - ›Exposes the set of available tools on
ToolRuntime, making it possible to inspect or enumerate registered tools at runtime.
- ›Enables ToolNode tools to return
- checkpoint==4.0.2
LangGraph checkpoint 4.0.2 documents
LANGGRAPH_STRICT_MSGPACKenvironment variable for checkpoint security hardening.└──▷ GET THIS VERSION$ git clone --branch checkpoint==4.0.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==4.0.2
- ›Documents
LANGGRAPH_STRICT_MSGPACKenvironment variable to control strict MessagePack deserialization security for checkpoints.
- ›Documents
- 1.1.7a1
LangGraph 1.1.7a1 adds graph lifecycle callback handlers for hooking into graph execution events.
└──▷ GET THIS VERSION$ git clone --branch 1.1.7a1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.7a1
- ›Adds graph lifecycle callback handlers, enabling hooks into key stages of graph execution.
- cli==0.4.20
LangGraph CLI gains remote build support for
langgraph deploy└──▷ GET THIS VERSION$ git clone --branch cli==0.4.20 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.20
- ›Adds remote build support for
langgraph deploy, enabling builds to run on remote infrastructure instead of locally.
- ›Adds remote build support for
- sdk==0.3.13
LangGraph SDK adds
langsmith_tracingparameter to runs.create/stream/wait for per-call tracing control.└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.13
└──▷ USE ITDisable LangSmith tracing for a specific run invocation to avoid logging sensitive payloads.result = await client.runs.create( thread_id=thread_id, assistant_id=assistant_id, input={"messages": [{"role": "user", "content": "hello"}]}, langsmith_tracing=False, )- ›Adds
langsmith_tracingparameter toruns.create,runs.stream, andruns.waitto enable or disable LangSmith tracing on a per-call basis.
- ›Adds
- 1.1.5
LangGraph 1.1.5 adds remote build support for
langgraph deployand richer runtime execution information.└──▷ GET THIS VERSION$ git clone --branch 1.1.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.5
- ›Adds remote build support to
langgraph deployin the CLI. - ›Enhances the runtime with more execution information.
- ›Adds remote build support to
- prebuilt==1.0.9
LangGraph prebuilt 1.0.9 exposes richer execution information at runtime for agent observability.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.9 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.9
- ›Enhances the runtime with additional execution information, giving agents and tools access to more context about the current run.
- 1.1.4
LangGraph 1.1.4 adds LangSmith integration metadata to graph runs.
└──▷ GET THIS VERSION$ git clone --branch 1.1.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.4
- ›Adds LangSmith integration metadata to LangGraph, enabling richer tracing and observability linkage between graph runs and LangSmith.
- cli==0.4.19
LangGraph CLI 0.4.19 adds
deploy revisions listcommand to inspect deployment revisions.└──▷ GET THIS VERSION$ git clone --branch cli==0.4.19 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.19
└──▷ TRY ITList all revisions for a deployed LangGraph app to audit deployment history or roll back.$ langgraph deploy revisions list- ›Adds
deploy revisions listsubcommand to list revisions of a LangGraph deployment.
- ›Adds
- 1.1.3
LangGraph 1.1.3 adds execution info to the runtime context.
└──▷ GET THIS VERSION$ git clone --branch 1.1.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.3
- ›Adds execution info to the LangGraph runtime, exposing contextual metadata during graph execution.
- cli==0.4.16
LangGraph CLI gains deploy logs, list, delete subcommands and distributed runtime support.
└──▷ GET THIS VERSION$ git clone --branch cli==0.4.16 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.16
└──▷ TRY ITTail logs from a running LangGraph deployment to debug production agent behavior.$ langgraph deploy logs <deployment-id>List all active deployments to audit or identify targets for cleanup.$ langgraph deploy listDelete a specific deployment to decommission a retired agent service.$ langgraph deploy delete <deployment-id>- ›Adds
langgraph deploy logssubcommand to stream or retrieve logs from a deployment. - ›Adds
langgraph deploy listsubcommand to enumerate active deployments. - ›Adds
langgraph deploy deletesubcommand to remove a deployment. - ›Adds distributed runtime support to the LangGraph CLI for scalable deployment configurations.
- ›Adds
- 1.1.2
LangGraph 1.1.2 adds context support for remote graph API calls.
└──▷ GET THIS VERSION$ git clone --branch 1.1.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.2
- ›Adds context parameter support for remote graph API interactions.
- 1.1.0
LangGraph 1.1 adds opt-in
version="v2"for type-safe streaming and invoke with Pydantic/dataclass output coercion.└──▷ GET THIS VERSION$ git clone --branch 1.1.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.1.0
└──▷ USE ITGet a typed return value and cleanly inspect interrupts after invoking a graph — no more fishing throughresult["__interrupt__"]in a plain dict.result = graph.invoke({"input": "hello"}, version="v2") result.value # your output state result.interrupts # tuple[Interrupt, ...], empty if noneStream graph events with full type narrowing — branch onpart["type"]and let your type checker know exactly whatpart["data"]contains for each mode.from langgraph.types import ValuesStreamPart, UpdatesStreamPart for part in graph.stream({"input": "hello"}, version="v2"): if part["type"] == "values": state = part["data"] # OutputT — full typed state interrupts = part["interrupts"] elif part["type"] == "updates": delta = part["data"] # dict[str, Any]When your state is a Pydantic model, confirm the output is already coerced to the right type — no manual MyState(**result) call needed.from pydantic import BaseModel from langgraph.graph import StateGraph class MyState(BaseModel): answer: str count: int compiled = StateGraph(MyState).compile() # ... add nodes/edges first result = compiled.invoke({"answer": "", "count": 0}, version="v2") assert isinstance(result.value, MyState)- ›Adds
version="v2"opt-in to invoke(), ainvoke(), stream(), and astream() for fully type-safe outputs. - ›New
GraphOutputreturn type from invoke(..., version="v2") exposes.valueand.interruptsattributes, cleanly separating state from interrupt signals. - ›New strongly-typed
StreamPartdiscriminated union (and per-mode TypedDicts:ValuesStreamPart,UpdatesStreamPart,MessagesStreamPart,CustomStreamPart,CheckpointStreamPart,TasksStreamPart,DebugStreamPart) enables full type narrowing in editors and type checkers. - ›Automatic output coercion to Pydantic models or dataclasses when the graph's state schema is declared as one — no manual parsing needed.
- ›Non-
"values"stream modes withversion="v2"returnlist[StreamPart]from invoke() instead oflist[tuple].
- ›Adds
- cli==0.4.15
LangGraph CLI gains a
langgraph deploycommand for direct deployment from the CLI.└──▷ GET THIS VERSION$ git clone --branch cli==0.4.15 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.15
└──▷ TRY ITDeploy a LangGraph application to LangGraph Cloud without leaving the terminal.$ langgraph deploy- ›Adds
langgraph deploycommand to deploy LangGraph applications directly from the CLI.
- ›Adds
- sdk==0.3.10
LangGraph SDK 0.3.10 adds type-safe stream/invoke with proper output type coercion
└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.10
- ›Adds type-safe
stream/invokecalls with proper output type coercion, enabling strongly-typed responses from graph runs
- ›Adds type-safe
- cli==0.4.14
LangGraph CLI gains a
keep_latestprune strategy for ThreadTTLConfig and checkpointer config passthrough.└──▷ GET THIS VERSION$ git clone --branch cli==0.4.14 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.14
- ›Adds
keep_latestprune strategy toThreadTTLConfig, giving finer control over which threads are retained when TTL cleanup runs. - ›Passes checkpointer config through to the CLI, enabling checkpointer settings to be applied via CLI invocation.
- ›Adds
- sdk==0.3.8
LangGraph Python SDK 0.3.8 adds stream_mode, stream_subgraphs, stream_resumable, and durability options to cron jobs, plus improved store auth type safety.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.8
- ›Adds
stream_mode,stream_subgraphs,stream_resumable, anddurabilityparameters to cron job creation in the Python SDK. - ›Improves type safety and docstrings for store auth in the Python SDK.
- ›Adds
- sdk==0.3.4
LangGraph Python SDK gains cron job update, enable, and disable methods in the crons client.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.3.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.3.4
- ›Adds
updatemethod to the crons client for modifying existing cron jobs. - ›Supports enabling and disabling cron jobs via the crons client.
- ›Adds
- prebuilt==1.0.7
LangGraph prebuilt 1.0.7 adds dynamic tool calling via a
tooloverride inwrap_model_call.└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.7
- ›Supports dynamic tool calling by accepting a
tooloverride parameter inwrap_model_call.
- ›Supports dynamic tool calling by accepting a
- 1.0.6
LangGraph 1.0.6 adds compile-time checkpointer type validation to catch configuration errors early.
└──▷ GET THIS VERSION$ git clone --branch 1.0.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.0.6
- ›Validates checkpointer type at compile time, surfacing misconfigured checkpointers before runtime.
- prebuilt==1.0.6
LangGraph prebuilt 1.0.6 adds compile-time checkpointer validation, custom encryption at rest, and paginated assistant search.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.6
- ›Validates checkpointer type at compile time, catching misconfiguration before runtime.
- ›Supports custom encryption at rest for checkpoint data.
- ›Includes pagination in assistants search responses.
- 1.0.5
LangGraph 1.0.5 adds custom encryption at rest, stream event IDs, and pagination for assistants search.
└──▷ GET THIS VERSION$ git clone --branch 1.0.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.0.5
- ›Adds custom encryption at rest for persisted graph state.
- ›Emits
idas part of stream events in the Python SDK. - ›Includes pagination in assistants search responses.
- cli==0.4.8
LangGraph CLI 0.4.8 adds webhook configuration and custom encryption at rest.
└──▷ GET THIS VERSION$ git clone --branch cli==0.4.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.8
- ›Adds webhook configuration support to the CLI.
- ›Supports custom encryption at rest for stored data.
- sdk==0.2.12
LangGraph SDK 0.2.12 adds pagination to assistants search and a sentinel to skip auto-loading API keys.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.2.12 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.2.12
└──▷ USE ITInstantiate the SDK client without auto-loading the API key from the environment, supplying credentials explicitly instead.from langgraph_sdk import get_client, SKIP_LOAD_API_KEY client = get_client(url="http://localhost:8123", api_key=SKIP_LOAD_API_KEY)
- ›Adds pagination metadata to the assistants search response, enabling clients to page through large assistant lists.
- ›Introduces a sentinel value to skip automatic API key loading when instantiating the SDK client, allowing explicit credential control.
- sdk==0.2.10
LangGraph Python SDK 0.2.10 adds
namefiltering to Assistants search and cursory Python 3.14 support.└──▷ GET THIS VERSION$ git clone --branch sdk==0.2.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.2.10
└──▷ USE ITFilter the Assistants search results to a specific assistant name instead of iterating all assistants.assistants = await client.assistants.search(name="my-assistant")
- ›Adds
nameparameter to the Assistants search API, enabling filtering assistants by name. - ›Adds cursory Python 3.14 support.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; projects running on Python 3.9 must upgrade their runtime.
- ›Adds
- 1.0.2
LangGraph 1.0.2 adds Overwrite reducer bypass, Python 3.14 support, and ships Checkpointers 3.0.
└──▷ GET THIS VERSION$ git clone --branch 1.0.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 1.0.2
└──▷ USE ITUse Overwrite on a state field when you want the latest value to always win instead of being merged by a reducer.from langgraph.types import Overwrite from typing import Annotated from typing_extensions import TypedDict class State(TypedDict): messages: Annotated[list, Overwrite()] # latest assignment replaces, no reducer merging- ›Adds Overwrite type to bypass reducers and directly overwrite state channel values without merging.
- ›Adds cursory Python 3.14 support.
- ›Ships Checkpointers 3.0 release.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; the minimum supported Python version has been raised.
- prebuilt==1.0.2
LangGraph prebuilt 1.0.2 adds Python 3.14 support and drops Python 3.9.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==1.0.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==1.0.2
- ›Adds cursory Python 3.14 support for prebuilt components.
- ›Un-deprecates ToolNode, restoring it as a supported API.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; setups running on Python 3.9 will break on upgrade.
- prebuilt==0.6.5
LangGraph prebuilt 0.6.5 adds Redis node-level caching and SDK client query-parameter support.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.6.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.6.5
- ›Adds Redis node-level cache via
feat(langgraph): implement redis node level cache, enabling per-node result caching backed by Redis. - ›Adds query-parameter support to the Python SDK client (
feat(sdk-py): client qparams), allowing callers to pass arbitrary query parameters through SDK calls.
- ›Adds Redis node-level cache via
- checkpointpostgres==3.0.0
langgraph-checkpoint-postgres 3.0 adds cursory Python 3.14 support.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==3.0.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==3.0.0
- ›Adds cursory Python 3.14 support, enabling use of the Postgres checkpointer on the latest Python release.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; setups running langgraph-checkpoint-postgres on Python 3.9 will break on upgrade.
- checkpointsqlite==3.0.0
LangGraph checkpointsqlite 3.0 adds Python 3.14 support and drops Python 3.9.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==3.0.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==3.0.0
- ›Adds cursory Python 3.14 support, keeping the library compatible with the upcoming CPython release.
- ›Drops Python 3.9 support; minimum supported Python version is now 3.10 or higher.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; running checkpointsqlite on Python 3.9 will break after upgrading to 3.0.0.
- checkpoint==3.0.0
LangGraph checkpoint 3.0 drops Python 3.9 and adds cursory Python 3.14 support.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==3.0.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==3.0.0
- ›Adds cursory Python 3.14 support to the checkpointers library.
- ›Restricts 'json' type deserialization for tighter serialization safety.
└──▷ BREAKING ON UPGRADE- !Python 3.9 is no longer supported; upgrade to Python 3.10 or later before upgrading to checkpoint 3.0.0.
- cli==0.4.3
LangGraph CLI 0.4.3 adds auth control on custom routes and server customization ordering.
└──▷ GET THIS VERSION$ git clone --branch cli==0.4.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.4.3
- ›Adds
authflag inHttpConfigto enable or disable authentication on custom routes. - ›Adds configuration for controlling the ordering of server customization (middleware/routers).
- ›Adds
- 0.6.8
LangGraph 0.6.8 adds guardrails that prevent arbitrary resumes when multiple interrupts are pending.
└──▷ GET THIS VERSION$ git clone --branch 0.6.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.6.8
- ›Adds enforcement that prevents arbitrary graph resumes when multiple pending interrupts exist, ensuring interrupt handling is ordered and intentional.
- 0.6.7
LangGraph CLI gains monorepo support for managing multi-package LangGraph projects.
└──▷ GET THIS VERSION$ git clone --branch 0.6.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.6.7
- ›Adds monorepo support in the LangGraph CLI, enabling multi-package project structures to be managed from a single repository.
- 0.6.3
LangGraph 0.6.3 adds a durability mode to
invokeandainvokefor controlling checkpoint persistence.└──▷ GET THIS VERSION$ git clone --branch 0.6.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.6.3
└──▷ USE ITControl whether LangGraph persists checkpoints during a synchronous graph run — useful when you want to skip persistence overhead for ephemeral, fire-and-forget invocations.graph.invoke(input, durability="ephemeral")
- ›Adds
durabilitymode parameter toinvokeandainvokefor controlling checkpoint persistence behavior.
- ›Adds
- 0.6.0
LangGraph 0.6 introduces a typed Context/Runtime API, durability modes, dynamic model/tool selection, and a solidified public API surface.
└──▷ GET THIS VERSION$ git clone --branch 0.6.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.6.0
└──▷ USE ITPass typed, run-scoped context (e.g. authenticated user ID and DB connection) to graph nodes without nesting values insideconfig['configurable'].from dataclasses import dataclass from langgraph.graph import StateGraph from langgraph.runtime import Runtime @dataclass class Context: user_id: str db_connection: str def node(state: State, runtime: Runtime[Context]): user_id = runtime.context.user_id db_conn = runtime.context.db_connection ... builder = StateGraph(state_schema=State, context_schema=Context) # add nodes, edges, compile... result = graph.invoke( {'input': 'abc'}, context=Context(user_id='123', db_connection='conn_mock') )Dynamically swap the LLM provider and toolset per-invocation in a ReAct agent based on runtime context.from dataclasses import dataclass from typing import Literal from langgraph.prebuilt import create_react_agent from langgraph.runtime import Runtime @dataclass class CustomContext: provider: Literal['anthropic', 'openai'] tools: list[str] def select_model(state, runtime: Runtime[CustomContext]): model = {'openai': openai_model, 'anthropic': anthropic_model}[runtime.context.provider] selected_tools = [t for t in [weather, compass] if t.name in runtime.context.tools] return model.bind_tools(selected_tools) agent = create_react_agent(select_model, tools=[weather, compass]) agent.invoke(some_input, context=CustomContext(provider='openai', tools=['compass']))- ›Adds a new Context API with
Runtime[Context]parameter for type-safe, run-scoped context injection, replacing theconfig['configurable']pattern. - ›Introduces
context_schemaargument onStateGraphas the successor toconfig_schema, enabling typed context definitions via dataclasses. - ›Adds
durabilityargument with three modes —"exit","async", and"sync"— giving fine-grained control over checkpoint persistence behavior. - ›Enables
create_react_agentto dynamically select model and tools at runtime via a custom context object. - ›Makes
StateGraphand Pregel generic overstate_schema,context_schema,input_schema, andoutput_schemafor compile-time type checking of node signatures andinvoke/streaminputs.
+3 moreshow less
- ›Refines the Interrupt interface: adds
id(unique identifier encoding namespace) andvalueattributes as the canonical surface. - ›Centralizes all error classes under
langgraph.errors; moves Send and Interrupt imports tolanggraph.types. - ›Adds
get_context_jsonschemafor graph introspection, supersedingget_config_jsonschema.
└──▷ BREAKING ON UPGRADE- !Importing from
langgraph.channelsis removed — all error classes must now be imported fromlanggraph.errors. - !The
TAG_NOSTREAM_ALTconstant is removed fromlanggraph.constants; useNOSTREAMinstead. - !The Interrupt attributes
when,resumable, andnsare removed; namespace info is now encoded in theidattribute.
- ›Adds a new Context API with
- prebuilt==0.6.0
LangGraph prebuilt 0.6.0 adds dynamic model selection in create_react_agent and a new context API replacing config['configurable'].
└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.6.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.6.0
- ›Adds dynamic model support to
create_react_agent, allowing the LLM to be swapped at runtime per invocation. - ›Introduces a new context API as a cleaner replacement for
config['configurable']andconfig_schemapatterns.
└──▷ BREAKING ON UPGRADE- !Public/private differentiations have been solidified — previously accessible private symbols may no longer be importable from their old paths.
- ›Adds dynamic model support to
- cli==0.3.6
LangGraph CLI 0.3.6 introduces an api-version option and a new context API replacing config['configurable'] and config_schema.
└──▷ GET THIS VERSION$ git clone --branch cli==0.3.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.3.6
- ›Adds
api-versionoption for explicit API version control. - ›Introduces new context API as a replacement for
config['configurable']andconfig_schemafor passing configuration to graph nodes.
└──▷ BREAKING ON UPGRADE- !The new context API replaces
config['configurable']andconfig_schema; existing code relying on these patterns will need to be migrated.
- ›Adds
- sdk==0.2.0
LangGraph Python SDK 0.2.0 adds context API support and exposes interrupts in thread state
└──▷ GET THIS VERSION$ git clone --branch sdk==0.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.2.0
└──▷ USE ITInspect interrupts on a thread after a run is suspended, to determine why execution paused.thread_state = await client.threads.get_state(thread_id) interrupts = thread_state.interrupts
- ›Adds SDK support for the
contextAPI, enabling callers to pass context through the LangGraph SDK. - ›Adds
interruptsfield to thread state, making interrupt information accessible when inspecting thread state. - ›Cleans up the Interrupt interface for v1, refining the interrupt contract.
└──▷ BREAKING ON UPGRADE- !The Interrupt interface has been changed as part of a v1 cleanup — existing code relying on the previous Interrupt interface shape may break.
- ›Adds SDK support for the
- 0.5.4
LangGraph 0.5.4 adds ParentCommand handling in RemoteGraph for cross-graph command propagation.
└──▷ GET THIS VERSION$ git clone --branch 0.5.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.5.4
- ›Supports
ParentCommandinRemoteGraph, enabling commands issued inside a remote graph to propagate up to the parent graph.
- ›Supports
- sdk==0.1.73
LangGraph SDK 0.1.73 exposes is_studio_user flag to identify Studio-originated requests.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.73 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.73
- ›Adds
is_studio_userattribute to identify whether the current user is a LangGraph Studio user.
- ›Adds
- checkpointpostgres==2.0.22
LangGraph checkpoint-postgres 2.0.22 adds numpy array serialization and pandas pickle fallback in JsonPlusSerializer.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.22 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.22
- ›Supports numpy array serialization in
JsonPlusSerializer, enabling checkpoint storage of numpy arrays without manual conversion. - ›Adds pickle fallback for pandas objects in
JsonPlusSerializerviaserialize/deserializepath, so DataFrames and Series round-trip through checkpoints reliably. - ›Extends pipeline mode in
checkpoint-postgresto use the same lock used in non-pipeline mode, improving consistency under concurrent writes. - ›Centralizes
CheckpointTuplecreation into a shared helper function withincheckpoint_postgres, reducing duplication across sync and async paths.
└──▷ BREAKING ON UPGRADE- !
Checkpoint.metadata.writeshas been removed; any code reading or writing this field will break on upgrade. - !
Checkpoint.pending_sendshas been removed; any code referencing this field will break on upgrade.
- ›Supports numpy array serialization in
- cli==0.3.4
LangGraph CLI 0.3.4 adds a flag to retain build dependencies (setuptools, pip, wheel) in container builds.
└──▷ GET THIS VERSION$ git clone --branch cli==0.3.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.3.4
- ›Adds a CLI argument to retain build dependencies (setuptools, pip, wheel) in the build output instead of pruning them.
- 0.5.0
LangGraph 0.5 adds NodeBuilder, granular streaming modes, NumPy serialization, and a stricter StateGraph API ahead of 1.0.
└──▷ GET THIS VERSION$ git clone --branch 0.5.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.5.0
└──▷ USE ITSubscribe only to task-level stream events to reduce overhead when you don't need checkpoint deltas.for event in graph.stream(input, stream_mode="tasks"): print(event)Define a typed graph with explicit input and output schemas using the new requiredstate_schemaand renamed schema parameters.from langgraph.graph import StateGraph graph = StateGraph( state_schema=MyState, input_schema=UserQuery, output_schema=AssistantResponse, )- ›New
NodeBuilderutility provides a declarative way to create nodes and attach them to channels, replacingChannel.subscribe_to. - ›Introduces
stream_mode="tasks"andstream_mode="checkpoints"as individually selectable streaming modes (and"debug"becomes an alias for both). - ›Adds
print_mode=argument toinvoke/streamfor controlling output printing. - ›
StateGraphnow acceptsinput_schemaandoutput_schemaparameters (replacinginput/output). - ›
JsonPlusSerializernow natively handles NumPy arrays (including Fortran-ordered) without pickle fallback.
+3 moreshow less
- ›Checkpoints are leaner: redundant keys dropped, per-task writes stored directly, and legacy
pending_sendsdata is auto-migrated on first load. - ›Allows same-name channels and nodes in
StateGraph. - ›Task masquerading with
update_stateis now supported.
└──▷ BREAKING ON UPGRADE- !
state_schemais now required inStateGraph.__init__; graphs constructed without it will error. - !The
inputandoutputkeyword arguments toStateGraphare deprecated and renamed toinput_schemaandoutput_schema; the old names raise a deprecation warning. - !Subclassing both
PregelNodeand Runnable is no longer supported; drop the Runnable base class. - !add_conditional_edge(..., then=) has been removed.
- !
Checkpoint.writesandCheckpoint.pending_sendsfields have been removed. - !The postgres shallow checkpointer has been removed.
- !Context channel/managed value and
SharedValuehave been removed. - !Support for a node reading a single managed value has been removed.
- !The
retryparameter is renamed toretry_policy. - !Dict subclasses used for
values/updatesstream chunks have been removed. - !The default for
checkpoint_duringhas been flipped. - !
Channel.subscribe_to(the Channel node builder) has been removed.
- ›New
- 0.4.10
LangGraph 0.4.10 adds 'tasks' and 'checkpoints' stream modes and numpy/pandas serialization support.
└──▷ GET THIS VERSION$ git clone --branch 0.4.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.10
└──▷ USE ITStream both task-level and checkpoint events to observe exactly when each node runs and when state is persisted.async for chunk in graph.astream(inputs, stream_mode=["tasks", "checkpoints"]): print(chunk)- ›Introduces
tasksandcheckpointsstream modes for finer-grained visibility into graph execution. - ›Supports numpy array serialization in
JsonPlusSerializer, enabling numpy data in graph state. - ›Adds pickle fallback for pandas serialization/deserialization via
JsonPlusSerializer. - ›Allows same-name channels and nodes in
StateGraph, removing a previous naming constraint. - ›Skips saving checkpoints for subgraphs when
checkpoint_during=False, reducing unnecessary checkpoint overhead.
- ›Introduces
- checkpoint==2.1.0
langgraph-checkpoint 2.1.0 adds NumPy array and pandas serialization support to JsonPlusSerializer
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.1.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.1.0
- ›Supports NumPy array serialization in JsonPlusSerializer, enabling checkpoint storage of array-heavy state.
- ›Adds pickle fallback for pandas serialization, allowing DataFrames and Series to round-trip through the checkpoint layer.
└──▷ BREAKING ON UPGRADE- !
Checkpoint.writeshas been removed. - !
Checkpoint.pending_sendshas been removed.
- cli==0.2.11
LangGraph CLI 0.2.11 adds
image_distroconfig support and warns when distro is not set to Wolfi.└──▷ GET THIS VERSION$ git clone --branch cli==0.2.11 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.11
- ›Supports
image_distrosetting in the LangGraph config file for controlling the base image distribution used in Dockerfile generation. - ›Adds a warning when the image distro is not configured as Wolfi, nudging users toward the recommended distro.
- ›Supports
- 0.4.8
LangGraph 0.4.8 adds NodeBuilder to replace Channel.subscribe_to and flips the default for checkpoint_during.
└──▷ GET THIS VERSION$ git clone --branch 0.4.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.8
- ›Adds
NodeBuilderclass as the new way to define node subscriptions, replacingChannel.subscribe_to. - ›Flips the default value for
checkpoint_during, changing checkpoint behavior out of the box. - ›Stream modes
messagesandcustomnow respectsubgraphs=False, giving finer control over subgraph output filtering. - ›Requires
state_schemainStateGraph.__init__, enforcing explicit schema declaration at graph construction.
└──▷ BREAKING ON UPGRADE- !
MessageGraphhas been removed; graphs usingMessageGraphwill break on upgrade. - !add_conditional_edge(..., then=) argument has been removed; any call using the
then=parameter will break. - !
Checkpoint.writeshas been removed; code reading or writing this field will break. - !
Checkpoint.pending_sendshas been removed; code reading or writing this field will break. - !The postgres shallow checkpointer has been removed; setups using it must migrate to another checkpointer.
- !
UntrackedValuechannel has been removed; any code referencing it will break. - !Context channel/managed value and
SharedValuehave been removed; code relying on them will break. - !
ChannelsManagerhas been removed; managed values are now static classes and can no longer be instantiated. - !
SchemaCoercionMapperhas been removed; code referencing it will break. - !Dict subclasses used for
values/updatesstream chunks have been removed; code that relied on the specific types of those chunks may break. - !The non-state Graph base class has been removed; code subclassing it directly will break.
- !The Channel node builder has been removed; use the new
NodeBuilderclass instead. - !
state_schemais now required inStateGraph.__init__; existing code that omits it will raise an error. - !The default for
checkpoint_duringhas been flipped; existing graphs that relied on the previous default behavior will behave differently without an explicit override.
- ›Adds
- 0.4.6
LangGraph 0.4.6 adds push_message() for manual stream writes, SQLiteStore, and smarter
stream_mode=valuesemission.└──▷ GET THIS VERSION$ git clone --branch 0.4.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.6
└──▷ USE ITUse SqliteStore as a persistence backend for checkpointing or memory in a LangGraph application.from langgraph.store.sqlite import SqliteStore store = SqliteStore("./my_app.db") results = store.list_namespaces(max_depth=2)- ›Adds push_message() method to manually push messages directly to the
messages/message-tuplestream from within a graph node. - ›Introduces
SqliteStoreas a new built-in store backend. - ›Optimizes
stream_mode=valuesto emit chunks only when output channels have actually changed, reducing noise in high-frequency graphs. - ›Prints output for cached
@taskfunctions, making task caching observable in the stream. - ›Updates
list_namespacesin SQLite withmax_depthsupport for scoped namespace queries.
- ›Adds push_message() method to manually push messages directly to the
- prebuilt==0.2.0
LangGraph prebuilt 0.2.0 adds a post_model_hook, HumanInterruptNode, parallel tool calls via Send, and a SqliteStore with namespace search.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.2.0
└──▷ USE ITInject a post-model validation or logging step into a ReAct agent without subclassing.from langgraph.prebuilt import create_react_agent def my_post_model_hook(state): # inspect or mutate state after each model call print("Model output:", state["messages"][-1].content) return state agent = create_react_agent( model=llm, tools=[...], post_model_hook=my_post_model_hook, )Persist agent memory across sessions using the new SqliteStore backend.from langgraph.store.sqlite import SqliteStore store = SqliteStore("agent_memory.db") # list namespaces up to 2 levels deep namespaces = store.list_namespaces(max_depth=2) print(namespaces)- ›Adds
post_model_hookparameter to inject custom logic after model responses increate_react_agent. - ›Introduces
HumanInterruptNodefor structured human-in-the-loop interruption handling in prebuilt agents. - ›Switches parallel tool call execution to use Send by default, enabling concurrent tool dispatch in the ReAct agent.
- ›Releases
SqliteStoreas a persistent key-value store backend with namespace search andlist_namespacessupportingmax_depthfiltering.
└──▷ BREAKING ON UPGRADE- !The
state_modifierparameter has been removed fromcreate_react_agent; existing code passingstate_modifierwill break on upgrade.
- ›Adds
- checkpointsqlite==2.0.8
LangGraph SQLite checkpoint adds SqliteStore and InMemoryCache for persistent and in-memory state storage.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==2.0.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==2.0.8
└──▷ USE ITClear all entries from a store in one call, useful for resetting state between test runs.store = SqliteStore("./agent_state.db") # ... populate store ... store.clear() # deletes all entries when called without arguments- ›New
SqliteStoreprovides a SQLite-backed key-value store for persisting LangGraph state across runs. - ›New
InMemoryCache(moved into the sqlite package alongsideFileCache) enables fast, non-persistent caching without a database. - ›Adds
SqliteStorerelease as the official sqlite store integration for LangGraph checkpointing. - ›Overloaded clear() method on the store now deletes all entries when called without arguments.
- ›New
- checkpoint==2.0.26
LangGraph checkpoint 2.0.26 adds InMemoryCache, namespace-scoped cache keys, TTL support, and pickle fallback for the JSON serializer.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.26 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.26
- ›Adds
InMemoryCacheas a new cache backend alongside the existing file-based cache. - ›Moves
FileCacheto the sqlite package and re-implements it using SQLite for more reliable storage. - ›Adds namespace support to cache keys, enabling isolated cache spaces across different workloads.
- ›Implements TTL (time-to-live) expiry in
FileCache, allowing automatic cache entry invalidation. - ›Overloads the
clearmethod so calling it without arguments deletes all cache entries.
+2 moreshow less
- ›Adds
pickle_fallbackoption to the JSON-plus serializer, enabling serialization of objects that are not natively JSON-serializable. - ›Removes Python version upper bounds, allowing installation on future Python releases without constraint conflicts.
- ›Adds
- 0.4.4
LangGraph 0.4.4 adds update_state for the functional API, a caching layer with InMemoryCache, and deferred node execution.
└──▷ GET THIS VERSION$ git clone --branch 0.4.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.4
└──▷ USE ITApply a state update inside a functional-API entrypoint, the same way you would in a StateGraph.from langgraph.func import entrypoint, task from langgraph.types import Command from langgraph.checkpoint.memory import MemorySaver checkpointer = MemorySaver() @entrypoint(checkpointer=checkpointer) def my_graph(state): return state # Update state for a specific thread mid-run my_graph.update_state({"configurable": {"thread_id": "thread-1"}}, {"key": "new_value"})- ›Implements
update_statefor the functional API, enabling state updates mid-graph in entrypoint-based workflows. - ›Introduces a cache interface with
InMemoryCacheandFileCache(moved to sqlite package), includingclearmethods and namespace-scoped cache keys. - ›Adds
cache_policyacceptance on graph, entrypoint, and pregel for default caching configuration. - ›Adds support for Deferred Nodes, enabling nodes whose execution can be deferred within a graph.
- ›Adds ability to start the dev server externally.
- ›Implements
- sdk==0.1.69
LangGraph Python SDK adds customizable client timeouts, loop-safe ASGI transport, and a new 'running' RunStatus.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.69 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.69
└──▷ USE ITSet per-request timeouts when initializing the LangGraph client to avoid hung calls in production.from langgraph_sdk import get_client client = get_client(url="http://localhost:8123", timeout=30)
- ›Supports customizable timeouts in get_client() for fine-grained control over request lifecycle.
- ›Adds optional loop-safe ASGI transport to avoid event-loop conflicts in async environments.
- ›Adds missing
'running'value toRunStatusenum, enabling accurate status checks on in-progress runs.
└──▷ BREAKING ON UPGRADE- !Private SDK functions are now prefixed with
_; any code calling these functions by their former unprefixed names will break.
- 0.4.3
LangGraph 0.4.3 uses tuples for streamed message events in RemoteGraph and adds a draw limit to Pregel graphs.
└──▷ GET THIS VERSION$ git clone --branch 0.4.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.3
- ›Uses tuples for streamed message events in RemoteGraph, aligning remote streaming with local graph conventions.
- ›Adds a node limit to
Pregel.drawto prevent rendering failures on very large graphs.
- 0.4.2
LangGraph 0.4.2 decouples RemoteGraph name from assistant ID and executes parallel tool calls via Send by default.
└──▷ GET THIS VERSION$ git clone --branch 0.4.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.2
- ›Decouples the graph name from the assistant ID in
RemoteGraph, allowing them to be set independently. - ›Switches
prebuiltparallel tool calls to execute via Send by default, enabling more controlled parallel tool dispatch.
- ›Decouples the graph name from the assistant ID in
- checkpointsqlite==2.0.7
LangGraph checkpoint-sqlite 2.0.7 adds a delete_thread method to the Checkpointer class.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==2.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==2.0.7
└──▷ USE ITDelete all checkpoint state for a specific thread to free storage or reset a conversation.checkpointer.delete_thread(thread_id)
- ›Adds
delete_threadmethod to the Checkpointer class for removing thread state from SQLite checkpoints.
- ›Adds
- cli==0.2.8
LangGraph CLI 0.2.8 adds custom base image support and configurable headers schema for Docker workflows.
└──▷ GET THIS VERSION$ git clone --branch cli==0.2.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.8
- ›Supports specifying a custom base image in Docker commands.
- ›Adds schema updates for configurable headers.
- sdk==0.1.66
LangGraph SDK 0.1.66 adds
checkpoint_duringparameter to control mid-execution checkpointing in graph runs.└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.66 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.66
└──▷ USE ITDisable mid-run checkpointing for a streaming run to reduce storage overhead when you only need a final checkpoint on completion or interruption.async for chunk in client.runs.stream( thread_id, assistant_id, input=input_data, checkpoint_during=False, ): print(chunk)Force checkpointing after every node when running long graphs where intermediate state recovery matters.run = await client.runs.create( thread_id, assistant_id, input=input_data, checkpoint_during=True, )- ›Adds optional
checkpoint_during: Optional[bool]parameter tostream,create,wait, andcreate_for_threadclient methods, letting callers control whether checkpoints are written during graph execution or only at the end/interruption.
- ›Adds optional
- sdk==0.1.65
LangGraph SDK 0.1.65 adds sorting support to assistants search with new sort_by and sort_order parameters.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.65 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.65
└──▷ USE ITRetrieve the most recently updated assistants first — useful for auditing or surfacing active agents in a large deployment.results = await client.assistants.search(sort_by="updated_at", sort_order="desc")
- ›Adds
sort_byandsort_orderparameters toClient.searchfor assistants, enabling sorting byassistant_id,graph_id,name,created_at, orupdated_atin ascending or descending order. - ›Introduces new type aliases
AssistantSortBy,ThreadSortBy, andSortOrderfor strongly-typed sort parameter hints across assistant and thread searches.
- ›Adds
- 0.4.1
LangGraph 0.4.1 adds incremental UI message merging and drops Pydantic V1 support.
└──▷ GET THIS VERSION$ git clone --branch 0.4.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.1
└──▷ USE ITStream incremental prop updates to a UI message (e.g. progressively reveal content) instead of replacing the whole message on each update.from langgraph.graph.ui import push_ui_message # First emission creates the message push_ui_message("my-component", {"status": "loading"}, message_id="msg-1") # Subsequent call merges new props into the existing message push_ui_message("my-component", {"status": "done", "result": "42"}, message_id="msg-1", merge=True)- ›Adds a
mergeparameter topush_ui_messageenabling incremental/partial updates to existing UI messages without replacing them wholesale. - ›Drops Pydantic V1 support —
SchemaCoercionMapperandlanggraph.utils.pydanticnow exclusively use Pydantic V2 APIs.
└──▷ BREAKING ON UPGRADE- !Pydantic V1 models are no longer supported in
SchemaCoercionMapper; graphs using Pydantic V1 models will break on upgrade. - !
TAG_NOSTREAMvalue changed from"langsmith:nostream"to"nostream"; code comparing against the old string literal will no longer match (the old value is available asTAG_NOSTREAM_ALTfor backward compatibility).
- ›Adds a
- 0.4.0
LangGraph 0.4.0 adds targeted interrupt resumption by ID and exposes pending interrupts on StateSnapshot
└──▷ GET THIS VERSION$ git clone --branch 0.4.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.4.0
└──▷ USE ITResume a specific interrupt by ID when multiple interrupts are pending in the same graph run, rather than sending a single resume value for all.graph.invoke(Command(resume={interrupt.interrupt_id: "approved"}), config)Inspect which interrupts are still pending after a step before deciding how to resume each one.snapshot = graph.get_state(config) for interrupt in snapshot.interrupts: print(interrupt.interrupt_id, interrupt.value)- ›Adds
interrupt_idproperty on Interrupt that generates a unique ID from its namespace, enabling precise identification of individual interrupts. - ›Enhances
Command.resumeto accept a mapping of interrupt IDs to resume values, allowing targeted resumption of specific interrupts rather than all-or-nothing. - ›Adds
interruptsfield toStateSnapshotto track interrupts that occurred in a step and are pending resolution. - ›Propagates interrupts in
"values"stream mode soinvoke/ainvokeand streaming consumers now see interrupts emitted during graph execution. - ›Adds
add_edgeutility in graph visualization to prevent duplicate edges when rendering graphs with END nodes.
- ›Adds
- checkpoint==2.0.25
LangGraph checkpoint savers gain
delete_threadandadelete_threadmethods to remove all data for a given thread ID.└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.25 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.25
└──▷ USE ITPurge all checkpoint data for a completed or abandoned thread to free storage and enforce data-retention policies.from langgraph.checkpoint.memory import InMemorySaver saver = InMemorySaver() # synchronous saver.delete_thread(thread_id="thread-abc123") # async await saver.adelete_thread(thread_id="thread-abc123")
- ›Adds
delete_threadandadelete_threadmethods toBaseCheckpointSaverandInMemorySaverfor deleting all checkpoints and writes associated with a specific thread ID.
- ›Adds
- 0.3.32
LangGraph 0.3.32 adds
draw_graphfor graph visualization andget_static_writesfor static analysis of conditional edges.└──▷ GET THIS VERSION$ git clone --branch 0.3.32 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.32
└──▷ USE ITVisualize a compiled graph including subgraphs and conditional edges using the new dedicateddraw_graphfunction.from langgraph.pregel.draw import draw_graph draw_graph(compiled_graph)
- ›Adds
get_static_writesmethod toChannelWriteto support static analysis of what a writer might write, enabling better resolution of conditional edges. - ›Extends
ChannelWrite.register_writerto accept static declarations for writers, with a newstaticfield onChannelWriteTupleEntryto declare writes for static analysis. - ›Adds new
langgraph.pregel.drawmodule with adraw_graphfunction that simulates execution to discover edges, correctly handling subgraphs and conditional edges.
- ›Adds
- cli==0.2.7
LangGraph CLI gains
--imageoption to deploy pre-built Docker images without a rebuild step.└──▷ GET THIS VERSION$ git clone --branch cli==0.2.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.7
└──▷ TRY ITDeploy a previously built LangGraph image directly in CI without rebuilding — useful for promotion workflows wherelanggraph buildalready ran in an earlier stage.$ langgraph up --image my-custom-langgraph-image:latest
- ›Adds
--imageoption tolanggraph upto specify a pre-built Docker image for the langgraph-api service, skipping the build process entirely.
- ›Adds
- cli==0.2.6
LangGraph CLI 0.2.6 adds
--tunnelflag to expose local dev server publicly via Cloudflare.└──▷ GET THIS VERSION$ git clone --branch cli==0.2.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.6
└──▷ TRY ITExpose your local LangGraph dev server publicly so remote teammates or browser-based frontends can reach it without localhost blocking.$ langgraph dev --tunnel
- ›Adds
--tunnelflag to thedevcommand to expose the local LangGraph API server through a public Cloudflare tunnel, enabling remote frontend access without localhost restrictions.
- ›Adds
- sdk==0.1.62
LangGraph SDK 0.1.62 adds sort_by and sort_order parameters to thread search for ordered result retrieval.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.62 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.62
└──▷ USE ITRetrieve the most recently updated threads first — useful when triaging active or stalled agent runs.threads = await client.threads.search( sort_by="updated_at", sort_order="desc" )- ›Adds
sort_byandsort_orderparameters toClient.searchfor sorting thread results byid,status,created_at, orupdated_atin ascending or descending order.
- ›Adds
- checkpointpostgres==2.0.20
LangGraph Postgres checkpoint library adds thread deletion and tightens search method signatures.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.20 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.20
└──▷ USE ITPurge all checkpoint data for a completed or abandoned thread to reclaim storage.saver = PostgresSaver(conn) saver.delete_thread(thread_id="thread-abc123")
Purge thread data in an async workflow without blocking the event loop.saver = AsyncPostgresSaver(conn) await saver.adelete_thread(thread_id="thread-abc123")
- ›Adds
delete_threadmethod toPostgresSaverfor complete removal of all checkpoints and writes tied to a specific thread ID. - ›Adds
adelete_thread(async) anddelete_thread(sync, with main-thread safety checks) toAsyncPostgresSaverfor the same capability in async workflows. - ›Updates
searchonPostgresStoreandasearchonAsyncPostgresStoreto requirequeryas an explicit keyword argument rather than a positional parameter.
└──▷ BREAKING ON UPGRADE- !The
queryparameter inPostgresStore.searchis now a named (keyword) parameter; callers passing it positionally will break. - !The
queryparameter inAsyncPostgresStore.asearchis now a named (keyword) parameter; callers passing it positionally will break.
- ›Adds
- cli==0.2.5
LangGraph CLI 0.2.5 adds internal config option to override Docker tags in generated Dockerfiles.
└──▷ GET THIS VERSION$ git clone --branch cli==0.2.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.5
└──▷ USE ITPin a specific base image tag in your generated Dockerfile instead of relying on the auto-detected Python/Node.js version.{ "_INTERNAL_docker_tag": "3.11-slim-bookworm" }- ›Adds
_INTERNAL_docker_tagconfiguration option to override the default Docker tag used in generated Dockerfiles, falling back to the Python or Node.js version when not set.
- ›Adds
- 0.3.31
LangGraph 0.3.31 adds
CONFIG_KEY_THREAD_IDconstant for tracking thread IDs in concurrent graph invocations.└──▷ GET THIS VERSION$ git clone --branch 0.3.31 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.31
└──▷ USE ITAccess the current invocation's thread ID inside a node or custom checkpointer to correlate concurrent runs.from langgraph.constants import CONFIG_KEY_THREAD_ID def my_node(state, config): thread_id = config["configurable"].get(CONFIG_KEY_THREAD_ID) print(f"Running on thread: {thread_id}") return state- ›New
langgraph.constants.CONFIG_KEY_THREAD_IDconstant enables explicit tracking of thread IDs for current invocations in checkpointing and state management.
- ›New
- 0.3.28
LangGraph 0.3.28 adds support for multiple retry policies per node or task, applying the first matching policy on exception.
└──▷ GET THIS VERSION$ git clone --branch 0.3.28 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.28
└──▷ USE ITAssign different retry policies per exception type on a node — e.g., retry rate-limit errors aggressively and network errors conservatively.from langgraph.types import RetryPolicy from langgraph.graph import StateGraph rate_limit_policy = RetryPolicy(retry_on=RateLimitError, max_attempts=5, backoff_factor=2.0) network_policy = RetryPolicy(retry_on=ConnectionError, max_attempts=2, backoff_factor=1.0) graph = StateGraph(MyState) graph.add_node("my_node", my_node_fn, retry=[rate_limit_policy, network_policy])Apply ordered retry policies to a functional task so the first matching policy governs backoff and attempt count.from langgraph.func import task from langgraph.types import RetryPolicy @task(retry=[RetryPolicy(retry_on=TimeoutError, max_attempts=3), RetryPolicy(retry_on=Exception, max_attempts=1)]) def fetch_data(url: str): ...- ›Supports passing a sequence of retry policies to
StateGraph.add_node,langgraph.func.task, and Pregel, applying the first matching policy when an exception occurs. - ›Improves
SchemaCoercionMapperperformance withfunctools.lru_cachecaching, fast paths for basic types, and better handling of tuple, set, and other collection types. - ›Adds compatibility with both Pydantic v1 and v2 in schema coercion via
SchemaCoercionMapper.
- ›Supports passing a sequence of retry policies to
- cli==0.2.2
LangGraph CLI 0.2.2 adds auto-detection of Python/JS graphs and smarter Docker base-image selection for mixed-language projects.
└──▷ GET THIS VERSION$ git clone --branch cli==0.2.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.2.2
- ›Automatically detects Python and JavaScript graphs by file extension, eliminating manual language configuration.
- ›Selects the appropriate Docker base image automatically based on project composition via new
default_base_imagelogic. - ›Supports mixed Python/Node.js projects in a single configuration, with
validate_confignow auto-detecting and setting correct runtime versions for each graph file. - ›New
docker_tagutility generates correct Docker image tags based on project configuration.
- 0.3.27
LangGraph 0.3.27 adds
checkpoint_duringparameter to skip per-step checkpointing and boost large-graph performance.└──▷ GET THIS VERSION$ git clone --branch 0.3.27 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.27
└──▷ USE ITSkip per-step checkpointing on a large graph to reduce saver overhead during a high-throughput batch run.result = graph.invoke({"messages": messages}, config=config, checkpoint_during=False)Use the async streaming interface with end-only checkpointing to reduce latency in production pipelines.async for chunk in graph.astream({"messages": messages}, config=config, checkpoint_during=False): process(chunk)- ›Adds
checkpoint_duringparameter to stream(), astream(), invoke(), and ainvoke() — set to False to checkpoint only at run end, reducing overhead in large graphs.
└──▷ BREAKING ON UPGRADE- !
checkpoint_every_stepis renamed tocheckpoint_duringinPregelLoop— any code referencing the old name will break.
- ›Adds
- cli==0.1.89
LangGraph CLI now accepts dictionary-format graph definitions with a 'path' key in addition to plain import-path strings.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.89 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.89
- ›Supports dictionary-format graph definitions (with a
'path'key) in the configuration file, alongside the existing plain import-path string format, enabling additional metadata to be co-located with graph paths.
- ›Supports dictionary-format graph definitions (with a
- 0.3.25
LangGraph 0.3.25 adds a UI messaging system to push, remove, and reduce UI component updates during graph execution.
└──▷ GET THIS VERSION$ git clone --branch 0.3.25 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.25
└──▷ USE ITStream UI component updates to a frontend during graph execution — e.g. show a progress card that is later replaced.from langgraph.graph.ui import push_ui_message, delete_ui_message, ui_message_reducer # Inside a graph node: def my_node(state): msg = push_ui_message("progress-card", {"status": "running", "step": 1}) # ... do work ... delete_ui_message(msg["id"]) return stateWireui_message_reducerinto a typed state so your graph automatically merges UI additions and removals across nodes.from typing import Annotated from langgraph.graph.ui import AnyUIMessage, ui_message_reducer from typing_extensions import TypedDict class GraphState(TypedDict): ui: Annotated[list[AnyUIMessage], ui_message_reducer]- ›New UIMessage TypedDict represents UI component updates with properties and metadata during graph execution.
- ›New
RemoveUIMessageTypedDict enables removal of UI components from the current graph state. - ›New
AnyUIMessageUnion type combines UIMessage andRemoveUIMessagefor flexible type annotations. - ›New push_ui_message() function creates and sends UI messages to render components mid-execution.
- ›New delete_ui_message() function removes a UI component from state by ID.
+1 moreshow less
- ›New ui_message_reducer() function merges UI message lists, handling both additions and deletions.
- prebuilt==0.1.8
LangGraph prebuilt 0.1.8 adds a
pre_model_hooktocreate_react_agentfor trimming or summarizing long message histories before LLM calls.└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.1.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.1.8
└──▷ USE ITTrim a long conversation to the last N messages before each LLM call to avoid exceeding the model's context window.from langgraph.prebuilt import create_react_agent from langchain_core.messages import trim_messages def pre_model_hook(state): trimmed = trim_messages(state["messages"], max_tokens=4096, token_counter=len) return {"llm_input_messages": trimmed} agent = create_react_agent( model=llm, tools=tools, pre_model_hook=pre_model_hook, )Summarize earlier conversation turns and replace them with a summary message before each LLM call, without mutating the stored state.def summarizing_hook(state): messages = state["messages"] if len(messages) > 20: summary = llm.invoke(f"Summarize this conversation: {messages[:-5]}") return {"llm_input_messages": [summary] + messages[-5:]} return {"llm_input_messages": messages} agent = create_react_agent( model=llm, tools=tools, pre_model_hook=summarizing_hook, )- ›Adds
pre_model_hookparameter tocreate_react_agent, letting you inject a custom node before every LLM call to preprocess message history via trimming, summarization, or other logic. - ›Hook can return
messagesto update agent state orllm_input_messagesto reshape only what the LLM sees, leaving persisted state untouched.
- ›Adds
- cli==0.1.84
LangGraph CLI 0.1.84 adds custom UI configuration support for dev server and Docker builds.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.84 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.84
- ›Supports
uiandui_configoptions in config files for customized UI when runninglanggraph dev. - ›Docker image builds now automatically detect and install UI dependencies (npm, yarn, pnpm, bun) when UI is configured.
- ›Docker images now include
LANGGRAPH_UIandLANGGRAPH_UI_CONFIGenvironment variables when UI is configured.
- ›Supports
- sdk==0.1.61
LangGraph SDK 0.1.61 adds description support to assistant create and update methods.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.61 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.61
└──▷ USE ITTag a new assistant with a human-readable description so teammates can identify its purpose at a glance.assistant = await client.assistants.create( graph_id="my-graph", description="Triages incoming support tickets and routes to the correct queue." )Update an existing assistant's description after a workflow change without recreating it.await client.assistants.update( assistant_id="asst_abc123", description="Revised: handles both support tickets and billing inquiries." )- ›Adds optional
descriptionfield toAssistantBaseTypedDict for storing assistant descriptions. - ›Adds
descriptionparameter tocreateandupdatemethods (async and sync) on the assistants client.
- ›Adds optional
- checkpoint==2.0.24
LangGraph checkpoint 2.0.24 adds explicit None serialization support in JsonPlusSerializer.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.24 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.24
└──▷ USE ITSerialize and deserialize a None value in checkpoint state without errors — useful when graph state fields are legitimately null.from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer serde = JsonPlusSerializer() type_tag, data = serde.dumps_typed(None) # returns ("null", b"") value = serde.loads_typed((type_tag, data)) # returns None- ›Supports None values in
JsonPlusSerializervia a new"null"type designation, enabling round-trip serialization of null checkpoint state fields.
- ›Supports None values in
- 0.3.23
LangGraph 0.3.23 adds
REMOVE_ALL_MESSAGESto clear entire conversation histories in one operation.└──▷ GET THIS VERSION$ git clone --branch 0.3.23 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.23
└──▷ USE ITClear an entire conversation history in one step instead of removing messages one by one — useful when resetting context between sessions or tasks.from langgraph.graph.message import REMOVE_ALL_MESSAGES from langchain_core.messages import RemoveMessage # Pass this to your graph state update to discard all prior messages state_update = {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)]}- ›Adds
REMOVE_ALL_MESSAGESconstant to wipe an entire MessageGraph conversation history in a singleRemoveMessagecall.
- ›Adds
- cli==0.1.83
LangGraph CLI 0.1.83 adds TTL-based checkpointer config for automatic thread data cleanup in deployments.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.83 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.83
└──▷ USE ITConfigure automatic deletion of stale thread checkpoints after a set period to keep storage lean in long-running deployments.from langgraph_cli.config import CheckpointerConfig, ThreadTTLConfig checkpointer = CheckpointerConfig( ttl=ThreadTTLConfig( default_minutes=1440, # delete thread data older than 24 hours sweep_interval_minutes=60, strategy="delete", ) )- ›Adds
CheckpointerConfigclass to configure the built-in checkpointer in LangGraph deployments via the main config file. - ›Adds
ThreadTTLConfigclass to set default TTL (in minutes), sweep interval, and expiry strategy ("delete") for automatic cleanup of thread checkpoints. - ›Supports passing checkpointer configuration to Docker environments via the
LANGGRAPH_CHECKPOINTERenvironment variable automatically. - ›Switches from msgpack to ormsgpack for improved serialization performance.
- ›Adds
- cli==0.1.82
LangGraph CLI dev command gains
--allow-blockingflag to suppress synchronous I/O blocking errors└──▷ GET THIS VERSION$ git clone --branch cli==0.1.82 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.82
└──▷ TRY ITRun the dev server with a graph that intentionally uses blocking I/O (e.g., a synchronous HTTP client or file read) without the server aborting on detection.$ langgraph dev --allow-blocking
- ›Adds
--allow-blockingflag to thedevcommand, allowing the server to run without raising errors when synchronous I/O blocking operations are detected.
- ›Adds
- cli==0.1.81
LangGraph CLI 0.1.81 adds
ui_configparameter to customize the LangGraph UI via configuration.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.81 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.81
- ›Adds
ui_configparameter to the LangGraph configuration for customizing the LangGraph UI. - ›Exposes
LANGGRAPH_UI_CONFIGDocker environment variable when UI configurations are provided, enabling container-level UI customization.
- ›Adds
- sdk==0.1.60
LangGraph SDK 0.1.60 adds dictionary-like access to the auth user object — index, check, and iterate over user properties.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.60 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.60
└──▷ USE ITAccess, check, and iterate over user properties inside a LangGraph auth handler without calling getattr.from langgraph_sdk.auth import Auth auth = Auth() @auth.authenticate async def authenticate(headers: dict) -> Auth.types.MinimalUserDict: # ... token validation ... return {"identity": "user-123", "role": "admin"} @auth.on async def handle(ctx, value): user = ctx.user role = user["role"] # __getitem__ if "role" in user: # __contains__ for key in user: # __iter__ print(key, user[key])- ›Adds
__getitem__to the auth user object, enabling dictionary-style property access (e.g.,user["sub"]). - ›Adds
__contains__to the auth user object so you can check property existence with theinoperator. - ›Adds
__iter__to the auth user object, allowing iteration over all user properties in auth handlers.
- ›Adds
- cli==0.1.80
LangGraph CLI now reads package.json metadata to auto-detect Yarn, pnpm, or Bun when no lock file is present.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.80 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.80
- ›Adds get_pkg_manager_name() helper that reads
packageManagerordevEngines.packageManager.namefrom package.json to detect the correct package manager (Yarn, pnpm, Bun, or npm) even when no lock file exists.
- ›Adds get_pkg_manager_name() helper that reads
- sdk==0.1.59
LangGraph SDK 0.1.59 adds per-request custom HTTP headers across all API client methods.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.59 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.59
└──▷ USE ITPass a correlation or tenant-tracking header on a per-run basis without modifying the global client config.run = await client.runs.create( thread_id="<thread_id>", assistant_id="<assistant_id>", headers={"X-Tenant-ID": "org-42", "X-Request-ID": "req-abc123"} )Inject a per-request auth token when streaming a run, e.g. for short-lived credentials that differ from the client's default.async for chunk in client.runs.stream( thread_id="<thread_id>", assistant_id="<assistant_id>", headers={"Authorization": "Bearer <ephemeral_token>"} ): print(chunk)- ›Adds an optional
headersparameter to all HTTP methods (get,post,put,patch,delete,stream) onHttpClientandSyncHttpClient, merging custom headers with existing request headers. - ›Adds optional
headersparameter to all methods onAssistantsClientandSyncAssistantsClient(includingget,create,update,delete,search). - ›Adds optional
headersparameter to all thread-related methods onThreadsClientandSyncThreadsClient, including state management, history, and creation. - ›Adds optional
headersparameter to all run methods onRunsClientandSyncRunsClient, covering create, stream, wait, and management operations. - ›Adds optional
headersparameter to all cron job methods onCronClientandSyncCronClient(create, search, delete).
+1 moreshow less
- ›Adds optional
headersparameter to all store operations onStoreClientandSyncStoreClient, including item storage, retrieval, and namespace management.
- ›Adds an optional
- checkpoint==2.0.22
langgraph-checkpoint 2.0.22 adds blob storage for InMemorySaver, upgrades to ormsgpack, and supports custom serialization hooks.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.22 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.22
- ›Adds dedicated blob storage system to
InMemorySaverfor more efficient, lower-memory channel value management via a newblobsstore and_load_blobsmethod. - ›Bumps checkpoint format to
LATEST_VERSION = 2, adopted by empty_checkpoint() and create_checkpoint(), to support the new storage layout. - ›Replaces
msgpackwithormsgpackinJsonPlusSerializerfor faster serialization, including newbytearraysupport and optimized serialization options. - ›Adds customizable
JsonPlusSerializer.__init__accepting an optional custom unpacking hook, plus_msgpack_ext_hook_to_jsonfor better MessagePack-to-JSON type translation.
- ›Adds dedicated blob storage system to
- 0.3.19
LangGraph 0.3.19 adds dependency-aware node scheduling and XXH3-based task ID hashing for faster graph execution.
└──▷ GET THIS VERSION$ git clone --branch 0.3.19 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.19
└──▷ USE ITExplicitly declare that a callable node accepts the LangChain config, avoiding runtime parameter inspection overhead.from langgraph.utils.runnable import RunnableCallable def my_node(state, config): # config is available here return {"result": config["configurable"].get("user_id")} node = RunnableCallable(my_node, func_accepts_config=True)Attach a subgraph directly to a PregelNode without wrapping it in a bound runnable — useful when composing graphs programmatically.from langgraph.pregel.read import PregelNode child_graph = build_child_graph() # returns a compiled Pregel node = PregelNode( channels=["input"], triggers=["input"], mapper=None, subgraphs=[child_graph], )- ›Adds dependency-aware node scheduling: only nodes whose trigger channels were updated in the previous step are evaluated, reducing unnecessary work in large graphs.
- ›Adds
trigger_to_nodesproperty on Pregel to expose the mapping from channel triggers to dependent nodes. - ›Adds
subgraphsparameter onPregelNodeto directly specify subgraphs instead of extracting them from a bound runnable. - ›Adds
func_accepts_configparameter onRunnableCallableto explicitly control whether a wrapped function receives the LangChain config argument. - ›Switches task ID generation to the XXH3 hash algorithm (via
_xxhash_str) for newer checkpoint versions, replacing the slower SHA-1 implementation.
- cli==0.1.78
LangGraph CLI
devcommand gains--studio_urloption to connect to custom Studio instances.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.78 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.78
└──▷ TRY ITPoint the local dev server at a self-hosted or staging LangGraph Studio instance instead of the defaultsmith.langchain.com.$ langgraph dev --studio_url https://studio.internal.example.com
- ›Adds
--studio_urloption to thedevcommand, enabling connection to a custom LangGraph Studio instance instead of the default https://smith.langchain.com.
- ›Adds
- sdk==0.1.58
LangGraph SDK 0.1.58 adds
superstepsandgraph_idparameters to thread creation for cross-deployment thread copying.└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.58 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.58
└──▷ USE ITCopy a thread from one deployment to another by replaying its supersteps at creation time.thread = await client.threads.create( supersteps=source_supersteps, graph_id="my-graph", metadata={"copied_from": source_thread_id} )- ›Adds
superstepsparameter to sync and async ThreadsClient.create(), enabling a sequence of state updates to be applied at thread creation — useful for copying threads between deployments. - ›Adds
graph_idparameter to ThreadsClient.create() to associate a new thread with a specific graph at creation time.
- ›Adds
- 0.3.17
LangGraph 0.3.17 adds bulk state update methods for efficient sequential graph state mutations.
└──▷ GET THIS VERSION$ git clone --branch 0.3.17 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.17
└──▷ USE ITApply several state patches at once during human-in-the-loop correction instead of callingupdate_staterepeatedly.from langgraph.types import StateUpdate # graph is a compiled Pregel graph, config identifies the thread updates = [ StateUpdate(values={"status": "reviewed"}, as_node="reviewer"), StateUpdate(values={"score": 0.95}, as_node="scorer"), ] graph.bulk_update_state(config, updates)Same workflow in an async context — useabulk_update_stateinside an async agent loop to batch corrections without blocking.from langgraph.types import StateUpdate updates = [ StateUpdate(values={"approved": True}, as_node="approver"), StateUpdate(values={"notes": "LGTM"}, as_node="annotator"), ] await graph.abulk_update_state(config, updates)- ›Adds
bulk_update_stateandabulk_update_statemethods to Pregel for applying multiple state updates to a graph in a single sequential operation. - ›Introduces
StateUpdateNamedTuple (fields:values,as_node) as a structured type for representing individual state updates passed to bulk operations.
- ›Adds
- 0.3.15
LangGraph 0.3.15 adds is_available() channel introspection and improves Pregel task execution performance.
└──▷ GET THIS VERSION$ git clone --branch 0.3.15 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.15
└──▷ USE ITCheck whether a channel holds a value before reading it, avoiding try/except boilerplate in custom channel logic.if channel.is_available(): value = channel.get()- ›Adds is_available() method to all channel types (
AnyValue,BinaryOperatorAggregate,DynamicBarrierValue,EphemeralValue,LastValue,NamedBarrierValue, Topic,UntrackedValue) for exception-free channel state checks. - ›Changes
PregelExecutableTask.triggerstype fromlist[str]toSequence[str]for more flexible and performant trigger handling.
└──▷ BREAKING ON UPGRADE- !The
return_exceptionparameter is removed from read_channel() inlanggraph.pregel.io; code passing that argument will break.
- ›Adds is_available() method to all channel types (
- 0.3.13
LangGraph 0.3.13 adds RemoteGraph visualization support and improves handling of multiple concurrent interrupts.
└──▷ GET THIS VERSION$ git clone --branch 0.3.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.13
└──▷ USE ITVisualize a graph that includes RemoteGraph nodes — now renders correctly instead of being skipped.await compiled_graph.aget_graph(xray=True)
- ›Adds support for visualizing
RemoteGraphinstances in both sync and async graph drawing methods. - ›Enables parallel traversal of subgraphs during async graph visualization via asyncio.gather(), speeding up rendering of complex graphs.
- ›Enhances multiple concurrent interrupt handling by collecting and combining them into a single interrupt for cleaner propagation.
- ›Adds support for visualizing
- checkpoint==2.0.21
LangGraph checkpoint adds EncryptedSerializer and CipherProtocol for at-rest encryption of checkpoint data.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.21 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.21
└──▷ USE ITEncrypt all checkpoint data at rest using AES — useful when storing sensitive agent state in a shared or cloud-backed checkpointer.from langgraph.checkpoint.serde.encrypted import EncryptedSerializer # Key can also be supplied via LANGGRAPH_AES_KEY env var serializer = EncryptedSerializer.from_pycryptodome_aes(key=b"your-32-byte-aes-key-here!!!!!") # Pass the serializer to your checkpointer of choice from langgraph.checkpoint.memory import MemorySaver checkpointer = MemorySaver(serde=serializer)
Implement a custom cipher (e.g., a KMS-backed one) by conforming toCipherProtocolinstead of using the built-in AES factory.from langgraph.checkpoint.serde.base import CipherProtocol from langgraph.checkpoint.serde.encrypted import EncryptedSerializer class MyKMSCipher(CipherProtocol): def encrypt(self, plaintext: bytes) -> bytes: ... # call your KMS def decrypt(self, ciphertext: bytes) -> bytes: ... # call your KMS serializer = EncryptedSerializer(cipher=MyKMSCipher())- ›New
CipherProtocolinterface defines encrypt/decrypt contract for pluggable cipher implementations. - ›New
EncryptedSerializerclass wraps any underlying serializer (defaults toJsonPlusSerializer) to transparently encrypt and decrypt checkpoint data. - ›Factory method
EncryptedSerializer.from_pycryptodome_aesenables AES-encrypted checkpoints via the pycryptodome library with minimal setup. - ›Supports AES key supply via
LANGGRAPH_AES_KEYenvironment variable or direct key passing, and is backward-compatible with existing unencrypted checkpoint data.
- ›New
- checkpointpostgres==2.0.17
langgraph-checkpoint-postgres 2.0.17 adds TTL support for Postgres store items with automatic background expiry sweeping.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.17 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.17
└──▷ USE ITAutomatically expire agent memory store entries after 60 minutes, with a background sweeper running every 30 seconds.from langgraph.store.postgres import PostgresStore store = PostgresStore.from_conn_string( "postgresql://user:pass@localhost/mydb", ttl={"default_ttl": 60, "sweep_interval_minutes": 0.5}, ) store.start_ttl_sweeper() # ... use store in your LangGraph app ... store.stop_ttl_sweeper()Use the async store with TTL in an async LangGraph application, ensuring cleanup on shutdown.from langgraph.store.postgres.aio import AsyncPostgresStore async with AsyncPostgresStore.from_conn_string( "postgresql://user:pass@localhost/mydb", ttl={"default_ttl": 120}, ) as store: await store.start_ttl_sweeper() # ... use store in your async LangGraph app ... await store.stop_ttl_sweeper()Manually trigger a TTL sweep on demand, e.g. as part of a scheduled maintenance job.from langgraph.store.postgres import PostgresStore store = PostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb") deleted_count = store.sweep_ttl() print(f"Swept {deleted_count} expired items")- ›Adds
ttlparameter toPostgresStoreandAsyncPostgresStoreconstructors to configure Time To Live behavior for store items. - ›Adds start_ttl_sweeper() and stop_ttl_sweeper() methods to manage a background thread/task that automatically deletes expired items.
- ›Adds sweep_ttl() method (sync and async) for on-demand manual deletion of expired store items.
- ›Supports TTL configuration via from_conn_string() for both sync and async store classes.
- ›Adds
expires_atandttl_minutescolumns plus an index onexpires_atto the store table via new database migrations.
+1 moreshow less
- ›Enables TTL refresh on GET and SEARCH operations so item lifetimes can be extended on access.
- ›Adds
- checkpoint==2.0.20
LangGraph checkpoint 2.0.20 adds configurable TTL sweep intervals for automatic expiry cleanup in stores.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.20 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.20
└──▷ USE ITEnable background TTL sweeping so expired store entries are deleted automatically every N minutes without manual intervention.from langgraph.store.base import TTLConfig ttl_config = TTLConfig( sweep_interval_minutes=30 )- ›Adds
sweep_interval_minutesfield to TTLConfig to schedule automatic periodic deletion of expired store items.
- ›Adds
- cli==0.1.77
LangGraph CLI 0.1.77 adds automatic TTL sweeping via new
sweep_interval_minutesconfig option.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.77 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.77
└──▷ USE ITEnable automatic TTL sweeping every 10 minutes so expired store entries are cleaned up without manual intervention.ttl_config = TTLConfig( sweep_interval_minutes=10 )- ›Adds
sweep_interval_minutesto TTLConfig, enabling the store to periodically delete expired items automatically; omitting it preserves the previous no-sweep behavior.
- ›Adds
- 0.3.10
LangGraph 0.3.10 adds env-var recursion control, cached schema coercion, and flexible task return types.
└──▷ GET THIS VERSION$ git clone --branch 0.3.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.10
└──▷ TRY ITOverride the default recursion limit for all graphs in a deployment without changing application code — useful in long-chain agentic workflows.$ export LANGGRAPH_DEFAULT_RECURSION_LIMIT=100- ›New
SchemaCoercionMapperclass provides cached schema coercion supporting Pydantic v1/v2, nested lists, dicts, tuples, and unions. - ›Configures graph recursion limit via the
LANGGRAPH_DEFAULT_RECURSION_LIMITenvironment variable (default: 25), removing the need for per-run config. - ›Expands
PregelTask.resultfield to accept Any type, enabling flexible non-dict return values from tasks.
└──▷ BREAKING ON UPGRADE- !The
require_at_least_one_ofparameter is removed fromChannelWrite; code that passes this parameter will break on upgrade.
- ›New
- sdk==0.1.57
LangGraph SDK adds
stream_modefiltering andcancel_on_disconnecttojoin_streamfor precise run output control.└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.57 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.57
└──▷ USE ITFilter a joined run stream to only receive graph state values and debug events, reducing noise in long-running pipelines.async for chunk in client.runs.join_stream(thread_id, run_id, stream_mode=["values", "debug"]): print(chunk)Usecancel_on_disconnectin the sync client so a stalled run is automatically cancelled when your process disconnects.for chunk in client.runs.join_stream(thread_id, run_id, stream_mode=["values"], cancel_on_disconnect=True): print(chunk)- ›Adds
stream_modeparameter to both sync and asyncRunClient.join_stream, enabling filtering of streamed run output by mode (e.g."values","debug"). - ›Adds
cancel_on_disconnectparameter to the syncRunClient.join_stream, reaching feature parity with the async version.
- ›Adds
- prebuilt==0.1.3
LangGraph prebuilt 0.1.3 adds Pydantic agent state models and Callable tool support in create_react_agent.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.1.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.1.3
└──▷ USE ITUse a plain Python callable as a tool in a ReAct agent — no need to wrap it in a BaseTool subclass.from langgraph.prebuilt import create_react_agent def lookup_user(user_id: str) -> str: """Look up a user by ID.""" return f"User {user_id}: Alice" agent = create_react_agent(model, tools=[lookup_user])Use Pydantic-based agent state for strict type validation and serialization in a ReAct agent.from langgraph.prebuilt import create_react_agent from langgraph.prebuilt.chat_agent_executor import AgentStatePydantic agent = create_react_agent(model, tools=[...], state_schema=AgentStatePydantic)
- ›Adds
AgentStatePydanticandAgentStateWithStructuredResponsePydanticPydantic models for representing agent state with messages, remaining steps, and structured responses. - ›Enables
create_react_agentto accept plain Callable objects as tools, in addition toBaseToolinstances. - ›Supports both TypedDict and Pydantic models interchangeably for agent state schema via updated
StateSchemaType.
- ›Adds
- checkpoint==2.0.19
LangGraph Checkpoint 2.0.19 adds TTL configuration support for stores with default TTL values and refresh-on-read control.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.19 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.19
└──▷ USE ITSet a store-wide default TTL and enable automatic TTL refresh on reads so cached items stay alive while actively used.from langgraph.store.base import TTLConfig # When constructing your store implementation store = MyStore( ttl_config=TTLConfig( default_ttl=60, # minutes; applied to put/aput when no TTL is specified refresh_on_read=True # extends TTL whenever an item is fetched ) )- ›Adds TTLConfig TypedDict to configure Time-To-Live behavior at the store level, including
default_ttl(in minutes) andrefresh_on_readoptions. - ›Adds
ttl_configproperty toBaseStoreso TTL policy is set once and applied automatically toget,search,put, and their async counterparts. - ›Adds
NotProvidedsentinel class andNOT_PROVIDEDconstant to distinguish between explicitly passingttl=Noneand omitting a TTL value entirely.
└──▷ BREAKING ON UPGRADE- !The
refresh_ttlparameter onget,search, and async counterparts now defaults to None (inherit store's TTL configuration) instead of True; stores that relied on TTLs being refreshed on every read will no longer do so unless TTLConfig(refresh_on_read=True) is set orrefresh_ttl=Trueis passed explicitly.
- ›Adds TTLConfig TypedDict to configure Time-To-Live behavior at the store level, including
- cli==0.1.76
LangGraph CLI 0.1.76 adds TTL configuration for stores, enabling automatic expiration of stored items.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.76 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.76
└──▷ USE ITExpire store entries after 60 minutes and keep them alive as long as they're being read — useful for session-scoped memory that should age out when users go idle.from langgraph.config import StoreConfig, TTLConfig store_cfg = StoreConfig( ttl=TTLConfig( default_ttl=60, # minutes until a new item expires refresh_on_read=True, # reset the clock whenever the item is read ) )- ›Adds TTLConfig TypedDict to control automatic expiration of store items, with per-read TTL refresh and a configurable default TTL in minutes.
- ›Extends
StoreConfigwith an optionalttlfield to attach TTL settings to any store definition.
- 0.3.7
LangGraph 0.3.7 adds Pydantic v1/v2 model validation for graph inputs via
input_modelsupport.└──▷ GET THIS VERSION$ git clone --branch 0.3.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.7
└──▷ USE ITEnforce structured, validated inputs on a compiled state graph by passing a Pydantic model asinput_modelso invalid payloads are caught before execution begins.from pydantic import BaseModel from langgraph.graph.state import StateGraph class MyInput(BaseModel): query: str max_results: int = 5 builder = StateGraph(MyInput) # ... add nodes and edges ... graph = builder.compile() # Pydantic validation now runs automatically on invoke result = graph.invoke({"query": "threat actors targeting finance", "max_results": 10})- ›Adds
input_modelsupport to Pregel for validating graph inputs against Pydantic v1 and v2 models, usingconstruct/model_constructrespectively. - ›Extends
get_input_schemato prioritize theinput_modelwhen available, surfacing typed input schemas for state graphs. - ›Introduces
_pick_mapperfunction inStateGraph/CompiledStateGraphto correctly handle Pydantic and non-Pydantic schema types during state coercion.
- ›Adds
- 0.3.6
LangGraph 0.3.6 adds input schema inference for conditional edges and a dedicated Branch module with a new
from_pathfactory method.└──▷ GET THIS VERSION$ git clone --branch 0.3.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.6
└──▷ USE ITUseBranch.from_pathto build a conditional edge with automatic input schema inference, so the router function only receives the fields it declares rather than the full graph state.from langgraph.graph.branch import Branch branch = Branch.from_path( path=my_router_fn, path_map={"yes": "node_a", "no": "node_b"}, # input_schema is inferred automatically from my_router_fn's signature ) graph.add_conditional_edges("entry", branch)- ›Adds
input_schemafield to Branch for automatic schema inference on conditional edges inStateGraph. - ›New
Branch.from_pathfactory method handlespath_mapconversion and optionally infers input schema. - ›Extends
StateGraph.add_conditional_edgeswith schema inference, improving type safety for branch routing. - ›Improves type annotations on the
taskdecorator to consistently prioritize async functions in Union types.
- ›Adds
- checkpointpostgres==2.0.16
LangGraph Postgres checkpoint store exposes
PLACEHOLDERandget_distance_operatoras public API└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.16 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.16
└──▷ USE ITReference the now-public PLACEHOLDER constant when building custom batch queries against the Postgres store.from langgraph.store.postgres.base import PLACEHOLDER
- ›Exposes
PLACEHOLDERconstant (formerly_PLACEHOLDER) as a public symbol inlanggraph.store.postgres.basefor use in external code. - ›Exposes
get_distance_operatorfunction (formerly_get_distance_operator) as a public API inlanggraph.store.postgres.basefor custom vector-distance logic.
└──▷ BREAKING ON UPGRADE- !The
_PLACEHOLDERconstant is renamed toPLACEHOLDER; any code importing_PLACEHOLDERdirectly will break. - !The
_get_distance_operatorfunction is renamed toget_distance_operator; any code importing or calling_get_distance_operatordirectly will break.
- ›Exposes
- checkpoint==2.0.18
LangGraph checkpoint 2.0.18 lets BaseStore operations accept non-string keys with automatic conversion.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.18 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.18
└──▷ USE ITUse integer or other non-string keys directly in store put/get calls without manually casting to str first.store.put(("namespace",), 42, {"value": "data"}) result = store.get(("namespace",), 42)- ›Enables non-string keys (integers, tuples, etc.) in all BaseStore operations (
get,put,delete, and async variants) by automatically converting them to strings before storage.
- ›Enables non-string keys (integers, tuples, etc.) in all BaseStore operations (
- sdk==0.1.55
LangGraph SDK 0.1.55 adds TTL support to the store API, enabling automatic expiration and refresh of stored items.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.55 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.55
└──▷ USE ITStore a short-lived session token that auto-expires after 30 minutes, so stale credentials are never returned.await client.store.put_item(namespace, key="session:user123", value={"token": "abc"}, ttl=30)Retrieve a cached item and slide its expiration window forward so active users stay authenticated without a re-login.item = await client.store.get_item(namespace, key="session:user123", refresh_ttl=True)
- ›Adds
ttlparameter toput_itemto set item expiration time (in minutes) in the store API. - ›Adds
refresh_ttlparameter toget_itemto control whether an item's TTL is refreshed on read. - ›Adds
refresh_ttlparameter tosearch_itemsto control TTL refresh for items returned by search.
- ›Adds
- checkpoint==2.0.17
LangGraph Checkpoint 2.0.17 adds TTL support for store items, enabling automatic expiration of stored data.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.17 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.17
- ›Adds TTL (time-to-live) support to
BaseStorevia asupports_ttlflag, letting store implementations enable automatic expiration of stored items. - ›Adds
ttl: Optional[float] = Noneparameter toPutOpto set per-item expiration time in minutes when writing to the store. - ›Adds
refresh_ttl: bool = Trueparameter toGetOpandSearchOpto control whether TTLs are refreshed on retrieval or search.
- ›Adds TTL (time-to-live) support to
- cli==0.1.75
LangGraph CLI 0.1.75 adds IDE schema validation for langgraph.json and UI component configuration support.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.75 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.75
└──▷ USE ITDeclare UI components for an agent in langgraph.json using the newuiconfiguration key.{ "graphs": { "my_agent": "./agent.py:graph" }, "ui": { "my_agent": "./ui/MyAgentComponent.tsx" } }- ›Adds JSON schema files (
schema.jsonandschema.v0.json) referenceable inlanggraph.jsonto enable IDE autocompletion and validation of LangGraph configuration. - ›Adds a new
uiconfiguration option to the Config class for defining UI components associated with agents. - ›Supports setting the
LANGGRAPH_UIenvironment variable in Docker deployments to configure UI components.
└──▷ BREAKING ON UPGRADE- !
StoreConfig.embedis renamed toStoreConfig.index— anylanggraph.jsonor code referencingStoreConfig.embedwill break on upgrade.
- ›Adds JSON schema files (
- prebuilt==0.1.2
LangGraph prebuilt 0.1.2 lets create_react_agent accept a RunnableSequence as its model argument.
└──▷ GET THIS VERSION$ git clone --branch prebuilt==0.1.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout prebuilt==0.1.2
└──▷ USE ITUse a prompt-plus-model RunnableSequence as the agent's model so a fixed system prompt is baked into the chain rather than managed separately.from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_react_agent prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful security analyst."), ("placeholder", "{messages}"), ]) llm = ChatOpenAI(model="gpt-4o") # Pass the RunnableSequence (prompt | llm) directly as the model agent = create_react_agent(model=prompt | llm, tools=[my_tool])- ›Supports passing a
RunnableSequenceas the model tocreate_react_agent, enabling prompt-chained pipelines to be used directly as the agent's LLM backbone.
- ›Supports passing a
- 0.3.4
LangGraph 0.3.4 adds
config_schemaandget_config_jsonschemamethods to Pregel, plus a new Pydantic-support utility.└──▷ GET THIS VERSION$ git clone --branch 0.3.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.3.4
└──▷ USE ITExpose a graph's configuration schema as JSON Schema for tooling, validation, or documentation.schema = graph.get_config_jsonschema() print(schema)
Check whether a custom config type will be handled natively by Pydantic before wiring it into a Pregel graph.from langgraph.utils.pydantic import is_supported_by_pydantic from typing import TypedDict class MyConfig(TypedDict): temperature: float max_tokens: int if is_supported_by_pydantic(MyConfig): print("Safe to use as a Pregel config type")- ›Adds
config_schemamethod to Pregel for proper configuration schema generation when the config type is a TypedDict, dataclass, or Pydantic model. - ›Adds
get_config_jsonschemamethod to Pregel for converting config schemas to JSON Schema format, consistent with existingget_input_jsonschema/get_output_jsonschema. - ›Adds
is_supported_by_pydanticutility function to detect whether a type (dataclass, Pydantic model, or TypedDict, including Python 3.12+) is directly supported by Pydantic.
- ›Adds
- cli==0.1.74
LangGraph CLI 0.1.74 adds langgraph 0.3.x support and the new langgraph-prebuilt high-level agent API.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.74 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.74
- ›Supports langgraph 0.3.x, enabling use of the latest core graph features in CLI-managed projects.
- ›Adds support for
langgraph-prebuiltv0.1.1, which provides high-level APIs for creating and executing LangGraph agents and tools.
- 0.2.75
LangGraph 0.2.75 adds structured response support and configuration schemas to the ReAct agent executor.
└──▷ GET THIS VERSION$ git clone --branch 0.2.75 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.75
└──▷ USE ITUse a typed structured response from a ReAct agent instead of free-form text — useful when you need machine-readable output from an agent loop.from langgraph.prebuilt.chat_agent_executor import AgentStateWithStructuredResponse
- ›Adds
AgentStateWithStructuredResponseclass to support structured responses in the ReAct agent executor. - ›Adds configuration schema support to the ReAct agent executor.
- ›Enhances
StreamMessagesHandlerto track message IDs nested within input dictionaries for proper deduplication. - ›Adds
py.typedmarkers to package subdirectories for improved type-checking support.
- ›Adds
- sdk==0.1.53
LangGraph SDK 0.1.53 adds store authorization via
@auth.on.storeand dynamic loopback transport configuration.└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.53 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.53
└──▷ USE ITRestrict store operations so each user can only read or write their own data.@auth.on.store async def authorize_store(ctx, value): # Allow access only if the namespace matches the authenticated user if ctx.user.identity not in value.get("namespace", []): raise Exception("Access denied")- ›Adds
@auth.on.storedecorator to authorize access to storage operations, enabling per-user data access control. - ›Adds
configure_loopback_transportsfunction and_registered_transportslist for dynamic server transport configuration. - ›Supports deferred loopback transport setup via the
__LANGGRAPH_DEFER_LOOPBACK_TRANSPORTenvironment variable.
- ›Adds
- cli==0.1.72
LangGraph CLI 0.1.72 adds Docker build-context support for parent-dir deps and new HTTP server config options including CORS and custom app mounting.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.72 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.72
└──▷ USE ITMount a custom FastAPI/Starlette app with middleware and configure CORS — useful when you need to add auth middleware or expose the server to a browser-based client.http: app: ./my_middleware_app.py:app cors: allow_origins: - "https://my-frontend.example.com" allow_methods: - "GET" - "POST" disable_routes: - assistants - store- ›Supports Docker build contexts for local dependencies located in parent directories, enabling more flexible project layouts.
- ›Adds
http.appconfig option to mount custom Starlette/FastAPI apps onto the LangGraph HTTP server. - ›Adds options to disable specific API route groups (assistants, threads, runs, store) via HTTP configuration.
- ›Adds CORS configuration support for the LangGraph HTTP server.
- 0.2.74
LangGraph 0.2.74 stabilizes the Functional API and adds custom task submission via
CONFIG_KEY_RUNNER_SUBMIT.└──▷ GET THIS VERSION$ git clone --branch 0.2.74 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.74
└──▷ USE ITOverride how PregelRunner dispatches tasks — useful for integrating custom thread pools, tracing, or rate-limiting at the task level.from langgraph.constants import CONFIG_KEY_RUNNER_SUBMIT def my_submit(fn, *args, **kwargs): print(f"Submitting task: {fn.__name__}") return fn(*args, **kwargs) graph.invoke( {"messages": [{"role": "user", "content": "Hello"}]}, config={"configurable": {CONFIG_KEY_RUNNER_SUBMIT: my_submit}}, )Use the now-stable Functional API to define reusable async tasks without wrapping in a full StateGraph.from langgraph.func import task, entrypoint @task def fetch_data(query: str) -> str: return f"result for {query}" @entrypoint() def pipeline(query: str): return fetch_data(query).result()- ›Adds
CONFIG_KEY_RUNNER_SUBMITconfiguration key, enabling custom task submission logic inPregelRunnerfor flexible execution control. - ›Promotes
langgraph.func.taskandlanggraph.func.entrypointdecorators to stable (Beta label removed). - ›Adds no-op fallback in
get_stream_writerso callers can safely invoke the stream writer even when none is configured.
- ›Adds
- checkpoint==2.0.15
LangGraph checkpoint 2.0.15 adds
get_checkpoint_metadatafor standardized, filtered checkpoint metadata extraction.└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.15 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.15
└──▷ USE ITStandardize metadata extraction from a RunnableConfig before storing a checkpoint, ensuring only primitive-typed, non-private fields are persisted.from langgraph.checkpoint.base import get_checkpoint_metadata metadata = get_checkpoint_metadata(config) # metadata contains only string/int/bool/float fields, private keys excluded
- ›Adds
get_checkpoint_metadatafunction to extract and process checkpoint metadata from aRunnableConfig, filtering out private/excluded keys and non-primitive types for consistent handling across checkpoint implementations.
- ›Adds
- checkpointpostgres==2.0.14
PostgreSQL checkpoint savers now store richer metadata by merging configurable properties with existing and explicit metadata.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.14 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.14
- ›Enriches checkpoint metadata automatically:
put/aputmethods onPostgresSaver,AsyncPostgresSaver,ShallowPostgresSaver, andAsyncShallowPostgresSavernow combine non-private configurable properties, existing metadata, and explicitly passed metadata into each saved checkpoint.
- ›Enriches checkpoint metadata automatically:
- checkpoint==2.0.13
InMemorySaver now serializes configurable options and existing metadata into checkpoint metadata
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.13
└──▷ USE ITAttach run-time configurable context (e.g. user ID, session tags) to checkpoints so they are queryable later without extra bookkeeping.from langgraph.checkpoint.memory import InMemorySaver saver = InMemorySaver() # config["configurable"] non-private keys and config["metadata"] are now # automatically merged into the stored checkpoint metadata by put() config = { "configurable": { "thread_id": "thread-42", "user_id": "alice", "__private_key": "ignored", # filtered out }, "metadata": {"session": "prod-run-1"}, } # After graph.invoke(..., config=config), checkpoints stored by InMemorySaver # will include thread_id, user_id, and session in their metadata.- ›Enriches
InMemorySaver.putcheckpoint metadata with non-privateconfig["configurable"]entries (keys not prefixed with__) and any existingconfig["metadata"]values
- ›Enriches
- checkpointsqlite==2.0.4
LangGraph SQLite checkpointers now store richer metadata including configurable fields and existing checkpoint metadata.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==2.0.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==2.0.4
- ›Enriches checkpoint metadata in
SqliteSaver.putandAsyncSqliteSaver.aputwith configurable fields (excluding private__-prefixedkeys) and any pre-existing metadata alongside explicitly provided metadata.
- ›Enriches checkpoint metadata in
- 0.2.71
LangGraph 0.2.71 adds a
destinationsparameter to add_node() for visualizing routing in edgeless graphs.└──▷ GET THIS VERSION$ git clone --branch 0.2.71 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.71
└──▷ USE ITAnnotate routing possibilities in a Command-driven edgeless graph so rendered visualizations show labeled edges between nodes.graph.add_node("router", router_fn, destinations={"process": "to_process", "fallback": "to_fallback"})Declare destination nodes as a tuple when edge labels aren't needed, still enabling accurate graph visualization.graph.add_node("router", router_fn, destinations=("process", "fallback"))- ›Adds optional
destinationsparameter to StateGraph.add_node(), accepting a dict of target-node→edge-label pairs or a tuple of node names, to declare possible routing paths for visualization. - ›Enables
NodeSpecandStateNodeSpecendsfield to accept either a tuple of strings or a dict mapping destination node names to edge labels, improving graph rendering fidelity for Command-basededgeless graphs.
- ›Adds optional
- checkpoint==2.0.12
LangGraph Checkpoint 2.0.12 adds provider-string embedding init and renames MemorySaver to InMemorySaver.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.12 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.12
└──▷ USE ITConfigure a vector store index with an embedding model using a provider string instead of a manually constructed embeddings instance.from langgraph.store.base import IndexConfig index_config = IndexConfig( embed="openai:text-embedding-3-small", dims=1536, )- ›Supports initializing embedding models via provider strings (e.g.,
"openai:text-embedding-3-small") inIndexConfig.embed, eliminating the need to manually instantiate an embeddings object. - ›Introduces
InMemorySaveras the canonical class name for the in-memory checkpoint saver, withMemorySaverretained as a backward-compatible alias.
- ›Supports initializing embedding models via provider strings (e.g.,
- 0.2.70
LangGraph 0.2.70 adds parallel tool execution in ReAct agents and graph naming for multi-agent systems.
└──▷ GET THIS VERSION$ git clone --branch 0.2.70 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.70
└──▷ USE ITRun tool calls in parallel across multiple ToolNode instances to speed up multi-tool ReAct agents.from langgraph.prebuilt import create_react_agent agent = create_react_agent( model=model, tools=[search, calculator, lookup], version="v2", # distributes tool calls via the Send API ) result = agent.invoke({"messages": [{"role": "user", "content": "Compare prices and specs for X and Y"}]})Name a compiled subgraph so it is identifiable in traces and multi-agent orchestration.from langgraph.graph import StateGraph builder = StateGraph(MyState) # ... add nodes and edges ... graph = builder.compile(name="research-agent")
Name a ReAct agent used as a subgraph so its AIMessages carry an identifiable agent name.from langgraph.prebuilt import create_react_agent agent = create_react_agent( model=model, tools=[search], name="web-search-agent", )- ›Adds
versionparameter to create_react_agent() enabling parallel tool execution via the Send API (v2) or single-node processing (v1, default). - ›Adds
nameparameter to Graph.compile(), StateGraph.compile(), and create_react_agent() to identify graphs when used as subgraphs. - ›Automatically attaches agent name to AIMessages generated by the ReAct agent for easier identification in multi-agent workflows.
- ›Enables
ToolNodeto accept direct tool calls as a list ofToolCalldicts. - ›Promotes
_inject_tool_argsto public methodinject_tool_argsonToolNode.
+1 moreshow less
- ›Extends
RunnableLiketype to support injected kwargs such aswriterandstorevia Concatenate andParamSpec.
- ›Adds
- 0.2.69
LangGraph 0.2.69 adds context utilities (get_config, get_store, get_stream_writer), tag support for streamed LLM messages, and optional store in ToolNode.
└──▷ GET THIS VERSION$ git clone --branch 0.2.69 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.69
└──▷ USE ITEmit custom progress events from inside a node during streaming without threading store/config through function signatures.from langgraph.config import get_stream_writer def my_node(state): writer = get_stream_writer() writer({"status": "starting scan", "targets": state["targets"]}) # ... do work ... writer({"status": "complete", "findings": 42}) return stateAccess the LangGraph store inside a node to read or write persistent data without passing it explicitly through the graph.from langgraph.config import get_store def enrich_node(state): store = get_store() record = store.get("threat-intel", state["ioc"]) state["intel"] = record.value if record else {} return stateGive a ToolNode access to the store for lookups during tool execution without making it a required parameter.from langgraph.prebuilt import ToolNode from langgraph.store.memory import InMemoryStore store = InMemoryStore() tool_node = ToolNode(tools=[my_tool], store=store)
- ›Adds get_config(), get_store(), and get_stream_writer() utilities in the new
langgraph.configmodule to access runtime context (config, store, and custom stream writer) from inside any node or task. - ›Adds optional
storeparameter support inToolNode, enabling tools to access the LangGraph store without requiring it as a mandatory dependency. - ›Adds tag support in
StreamMessagesHandlerso streamed LLM messages carry filtered tag metadata (excluding internal sequence-step tags). - ›Adds
subgraphsproperty toPregelNodeandsubgraphsfield toPregelExecutableTaskfor direct tracking and caching of nested graph references.
- ›Adds get_config(), get_store(), and get_stream_writer() utilities in the new
- cli==0.1.70
LangGraph CLI now supports auth configuration in langgraph.json with path validation and Docker container handling.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.70 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.70
└──▷ USE ITWire a custom auth handler into your LangGraph deployment so it is validated locally and resolved correctly inside the Docker container.{ "graphs": { "my_agent": "./agent.py:graph" }, "auth": { "path": "./auth/handler.py:auth" } }- ›Supports
authconfiguration block inlanggraph.json, with validation thatauth.pathfollows the required./path/to/file.py:attribute_nameformat. - ›Enables auth path resolution in Docker environments via new
_update_auth_pathfunction, so auth handlers are correctly wired when deploying containers.
- ›Supports
- 0.2.68
LangGraph 0.2.68 promotes the Functional API to Beta and adds a
nameparameter to thetaskdecorator.└──▷ GET THIS VERSION$ git clone --branch 0.2.68 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.68
└──▷ USE ITAssign a human-readable display name to a task that wraps a lambda or method where the default__name__would be unhelpful.from langgraph.func import task @task(name="fetch_user_profile") def _t(user_id: str) -> dict: # your implementation return {"id": user_id} future = _t("u-123") result = future.result()Use the newpromptparameter name increate_react_agentinstead of the deprecatedstate_modifier.from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI agent = create_react_agent( model=ChatOpenAI(model="gpt-4o"), tools=[...], prompt="You are a concise security analyst. Answer in bullet points.", ) result = agent.invoke({"messages": [{"role": "user", "content": "Summarize CVE-2024-1234"}]})- ›Adds
nameparameter to thetaskdecorator, allowing custom display names for tasks regardless of the underlying function name. - ›Promotes the Functional API (
@task,@entrypoint) from Experimental to Beta status with expanded documentation. - ›Introduces unified
SyncAsyncFuturetype inlanggraph.pregel.callthat implements both the Future interface and the awaitable protocol for task return values. - ›Renames
state_modifierparameter topromptincreate_react_agent, with full backward compatibility retained.
└──▷ BREAKING ON UPGRADE- !Generators are no longer supported in the Functional API (
@entrypoint); any entrypoint using a generator function will break on upgrade.
- ›Adds
- cli==0.1.69
LangGraph CLI now ships PostgreSQL with pgvector enabled for vector operations support.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.69 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.69
- ›Upgrades the bundled PostgreSQL Docker image to
pgvector/pgvector:pg16, enabling vector operations in local dev environments. - ›Loads the pgvector extension automatically via
shared_preload_libraries=vectorin the generated Docker Compose configuration.
- ›Upgrades the bundled PostgreSQL Docker image to
- 0.2.67
LangGraph 0.2.67 adds entrypoint.final for separating return vs. checkpointed values and async state modifiers in the chat agent executor.
└──▷ GET THIS VERSION$ git clone --branch 0.2.67 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.67
└──▷ USE ITReturn a clean response to the caller while persisting richer state to the checkpoint — useful when you want the graph's saved context to differ from what the user receives.from langgraph.func import entrypoint @entrypoint(checkpointer=checkpointer) def my_graph(input: str) -> entrypoint.final[str, dict]: result = run_pipeline(input) # Return the string to the caller; save the full dict to the checkpoint return entrypoint.final(value=result["summary"], save=result)- ›Adds
entrypoint.finalprimitive to return a value to the caller that differs from the value saved in the checkpoint. - ›Supports async coroutine functions as state modifiers in the chat agent executor.
- ›Adds thread-safe atomic counters in
PregelScratchpadfor safer concurrent graph execution. - ›Supports Union types in node function return annotations so
add_nodecorrectly extracts Command types. - ›Enhances
Command.updatewith automatic field extraction from type hints on dataclasses and typed objects.
+1 moreshow less
- ›Reduces tracing noise by applying
recurse=Falseto internalRunnableCallableinstances.
└──▷ BREAKING ON UPGRADE- !The
CONFIG_KEY_ENDconstant is renamed toCONFIG_KEY_PREVIOUS; any code referencingCONFIG_KEY_ENDwill break. - !
PregelScratchpadis changed from aTypedDictto a dataclass; code that constructs or unpacks it as a plain dict will break.
- ›Adds
- 0.2.66
LangGraph 0.2.66 adds
run_coroutine_threadsafe,explode_args, andtrace_inputsfor safer async execution and richer tracing.└──▷ GET THIS VERSION$ git clone --branch 0.2.66 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.66
└──▷ USE ITSafely submit a coroutine to a running event loop from a background thread — useful when mixing sync worker threads with an async LangGraph executor.from langgraph.utils.future import run_coroutine_threadsafe import asyncio loop = asyncio.get_event_loop() future = run_coroutine_threadsafe(my_async_task(), loop) result = future.result(timeout=30)
Customize how inputs appear in LangSmith / callback traces for a multi-step chain without changing runtime behaviour.from langgraph.utils.runnable import RunnableSeq seq = RunnableSeq( step_a, step_b, trace_inputs=lambda x: {"sanitized_input": x["query"]}, ) result = seq.invoke({"query": "explain RBAC", "user_token": "s3cr3t"})- ›Adds
explode_argsparameter toRunnableCallableto unpack a tuple of (args, kwargs) instead of passing it as the first positional argument; affects bothinvokeandainvokemethods. - ›Adds
trace_inputsparameter toRunnableSeqto customize how inputs are recorded in callbacks acrossinvoke,ainvoke,stream, andastream. - ›Adds
run_coroutine_threadsafefunction inlanggraph.utils.futurefor safely running coroutines from any thread context. - ›Adds
CONTEXT_NOT_SUPPORTEDflag inlanggraph.utils.futureto handle Python versions whose event loops do not supportcontextvars. - ›Adds
get_runnable_for_entrypointandget_runnable_for_taskfunctions inlanggraph.pregel.callfor targeted handling of distinct execution contexts.
+4 moreshow less
- ›Moves the
callfunction fromlanggraph.func.__init__tolanggraph.pregel.callfor better module organization. - ›Adds
_explode_args_trace_inputsutility inlanggraph.pregel.callto flatten function arguments in traces for improved debugging. - ›Enhances
chain_futureinlanggraph.utils.futureto return the destination future, enabling direct chaining. - ›Removes the restriction in
PregelRunnerthat only coroutine functions could be called in an async context, and adds context detection to return the appropriate future type (async or sync) based on the calling context.
- ›Adds
- 0.2.65
LangGraph 0.2.65 adds graph visualization for entrypoint functions and a new get_store() utility for easy store access.
└──▷ GET THIS VERSION$ git clone --branch 0.2.65 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.65
└──▷ USE ITVisualize an entrypoint function and all its nested tasks during development or debugging.from langgraph.func import entrypoint, task @task def fetch_data(url: str): ... @entrypoint() def pipeline(input: dict): return fetch_data(input["url"]).result() # pipeline is now an EntrypointPregel graph = pipeline.get_graph(xray=True) graph.print_ascii()Access the configured store inside a node or task without threading config through manually.from langgraph.config import get_store @task def save_result(key: str, value: str): store = get_store() store.put(("results",), key, {"value": value})- ›New
EntrypointPregelclass exposes a get_graph() method to visualize entrypoint functions and their dependent tasks, including nested subgraphs via x-ray mode. - ›New get_store() utility function retrieves the
BaseStorefrom the current config context without manual extraction. - ›Tasks decorated with
@tasknow carry a_is_pregel_taskattribute, making them automatically discoverable for graph visualization.
└──▷ BREAKING ON UPGRADE- !The
entrypointdecorator now returns anEntrypointPregelinstance instead of a Pregel instance; code that type-checks or depends on the exact return type being Pregel will break.
- ›New
- cli==0.1.68
LangGraph CLI 0.1.68 adds Bun package manager support and clearer JS-graph error guidance.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.68 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.68
- ›Supports Bun as a detected package manager: detects
bun.lockband runsbun iautomatically for Bun-based projects. - ›Adds a clear error message when users attempt to run JS graphs with the Python CLI, directing them to use
npx @langchain/langgraph-cliinstead.
- ›Supports Bun as a detected package manager: detects
- 0.2.64
LangGraph 0.2.64 adds config schema validation and
previousstate access to theentrypointdecorator.└──▷ GET THIS VERSION$ git clone --branch 0.2.64 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.64
└──▷ USE ITEnforce a typed config schema on a workflow so callers get validation errors when they pass unexpected config keys.from langgraph.func import entrypoint from pydantic import BaseModel class MyConfig(BaseModel): temperature: float = 0.7 max_tokens: int = 256 @entrypoint(config_schema=MyConfig) def my_workflow(inputs: dict) -> str: # config is validated against MyConfig before execution ...Accumulate state across invocations by reading the last return value viaprevious— useful for iterative, stateful agent loops.from langgraph.func import entrypoint @entrypoint() def my_workflow(inputs: dict, previous: list | None = None) -> list: history = previous or [] history.append(inputs["message"]) return history- ›Adds
config_schemaparameter to theentrypointdecorator, enabling schema validation for workflow configuration. - ›Adds support for an optional
previousparameter inentrypoint-decoratedfunctions to access the prior return value in stateful Pregel graphs. - ›Adds automatic input/output type detection from function signatures in the
entrypointdecorator, removing the need for manual type annotation wiring.
- ›Adds
- 0.2.63
LangGraph 0.2.63 adds subgraph checkpointing, string model IDs in create_react_agent, human-interrupt types, and eager streaming.
└──▷ GET THIS VERSION$ git clone --branch 0.2.63 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.63
└──▷ USE ITEnable persistent checkpointing for a subgraph without wiring up a full checkpointer object.subgraph = subgraph_builder.compile(checkpointer=True) parent = parent_builder.compile(checkpointer=memory_checkpointer) parent.add_node("sub", subgraph)Spin up a ReAct agent by referencing a model by string instead of instantiating a model object.from langgraph.prebuilt import create_react_agent agent = create_react_agent("openai:gpt-4", tools)- ›Supports
checkpointer=Trueon subgraphs to enable persistent checkpointing without passing a full checkpointer object. - ›Accepts string model identifiers in
create_react_agent, e.g. create_react_agent("openai:gpt-4", tools). - ›Adds structured type definitions for human-in-the-loop interactions:
HumanInterruptConfig,ActionRequest,HumanInterrupt, andHumanResponseinlanggraph.prebuilt.interrupt. - ›Adds
stream_eageroption tolanggraph.pregelto force stream events to emit eagerly. - ›Enables method chaining on
add_node,add_edge,add_sequence,add_conditional_edges,set_entry_point,set_conditional_entry_point, andset_finish_pointvia updated Self return types.
+1 moreshow less
- ›Allows mixed Command and non-Command types in list commands, removing the requirement that all list items be Command objects.
└──▷ BREAKING ON UPGRADE- !
get_configurableinlanggraph.utils.configis renamed toget_config; any code callingget_configurablewill break.
- ›Supports
- checkpointpostgres==2.0.12
langgraph-checkpoint-postgres 2.0.12 adds task_path tracking to checkpoint writes for better data organization.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.12 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.12
└──▷ USE ITTag checkpoint writes with a task path so you can trace which graph node produced each write.await saver.aput_writes(config, writes, task_id, task_path="agent/subgraph")
- ›Adds
task_pathparameter to put_writes() and aput_writes() on all saver classes (PostgresSaver,AsyncPostgresSaver,ShallowPostgresSaver,AsyncShallowPostgresSaver) to tag checkpoint writes with their originating task path. - ›Extends the
checkpoint_writestable schema with atask_pathcolumn, enabling path-based ordering and querying of checkpoint write records.
- ›Adds
- checkpointsqlite==2.0.3
LangGraph SQLite checkpointer adds
task_pathparameter to write-tracking methods for improved task traceability.└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==2.0.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==2.0.3
└──▷ USE ITTag writes with the originating task path so checkpoint records can be traced back to a specific graph node or subgraph.saver.put_writes(config, writes, task_id, task_path="agent:tool_call")
Do the same in async workflows using the async saver.await async_saver.aput_writes(config, writes, task_id, task_path="agent:tool_call")
- ›Adds optional
task_pathparameter to SqliteSaver.put_writes() for tracking which task path created a given set of writes. - ›Adds optional
task_pathparameter to AsyncSqliteSaver.put_writes() and AsyncSqliteSaver.aput_writes() for async task traceability.
- ›Adds optional
- checkpoint==2.0.10
LangGraph checkpoint 2.0.10 adds task path tracking to
put_writes/aput_writesfor consistent ordering in nested task graphs.└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.10
└──▷ USE ITPass the nested task path when writing checkpoint data so that sends are retrieved in a consistent, hierarchical order in complex subgraph workflows.saver.put_writes(config, writes, task_id, task_path="parent_task/child_task")
- ›Adds
task_pathparameter toput_writesandaput_writesonBaseCheckpointSaverandInMemorySaverto track the nested path of tasks creating checkpoint writes. - ›Enables deterministic, consistent ordering of pending sends by sorting on task path, task ID, and sequence number during checkpoint retrieval.
- ›Adds
- checkpointduckdb==2.0.2
LangGraph DuckDB checkpointer adds in-memory vector search support
└──▷ GET THIS VERSION$ git clone --branch checkpointduckdb==2.0.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointduckdb==2.0.2
- ›Adds in-memory vector search capability to the DuckDB checkpointer
- 0.2.62
LangGraph 0.2.62 adds a
response_formatparameter tocreate_react_agentfor structured, schema-validated agent outputs.└──▷ GET THIS VERSION$ git clone --branch 0.2.62 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.62
└──▷ USE ITEnforce a typed output schema on a ReAct agent so downstream code can rely on structured data instead of free-form text.from pydantic import BaseModel from langgraph.prebuilt import create_react_agent class AgentAnswer(BaseModel): answer: str confidence: float agent = create_react_agent( model, tools=[...], response_format=AgentAnswer, ) result = agent.invoke({"messages": [("user", "What is the capital of France?")]}) print(result["structured_response"]) # AgentAnswer(answer='Paris', confidence=0.99)Supply a custom extraction prompt alongside the schema when the default structured-output prompt doesn't fit your domain.from typing import TypedDict from langgraph.prebuilt import create_react_agent class Summary(TypedDict): key_findings: list[str] risk_level: str agent = create_react_agent( model, tools=[...], response_format=( "Extract the security findings and risk level from the conversation.", Summary, ), ) result = agent.invoke({"messages": [("user", "Analyze this log: ...")]}) print(result["structured_response"])- ›Adds
response_formatparameter tocreate_react_agentto enforce a schema on final agent output, returned in thestructured_responsestate key. - ›Supports OpenAI function/tool schemas, JSON Schema, TypedDict classes, and Pydantic models as the response schema.
- ›Accepts a (prompt, schema) tuple for
response_formatto supply a custom prompt when generating structured output.
- ›Adds
- sdk==0.1.50
LangGraph SDK 0.1.50 adds store authorization handlers and expands Command.update to accept tuple sequences.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.50 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.50
└──▷ USE ITUse tuple sequences in Command.update when state keys contain ordering semantics or you're building updates dynamically.from langgraph.types import Command updates = [("messages", new_message), ("turn_count", 5)] cmd = Command(update=updates)- ›Adds
auth.on.storedecorators to authorize store operations (put, get, search, list_namespaces, delete) at the handler level. - ›Introduces new TypedDict classes —
StoreGet,StoreSearch,StoreListNamespaces,StorePut,StoreDelete— for typed store operation authorization. - ›Expands
Command.updateto accept sequences of tuples in addition to dictionaries, enabling more flexible graph state updates.
- ›Adds
- 0.2.61
LangGraph 0.2.61 adds OpenAI-format message conversion to
add_messagesand a more flexibletaskdecorator with async support.└──▷ GET THIS VERSION$ git clone --branch 0.2.61 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.61
└──▷ USE ITEnsure all messages stored in a graph state channel are automatically normalized to OpenAI format (string, 'text', 'image_url' blocks) before passing to an OpenAI-compatible LLM.from langgraph.graph.message import add_messages from typing import Annotated from typing_extensions import TypedDict class State(TypedDict): messages: Annotated[list, add_messages(format="langchain-openai")]Wrap an async function as a LangGraph task using the decorator directly without parentheses — useful for fire-and-forget subtasks in a functional graph.from langgraph.func import task @task async def fetch_data(url: str, timeout: int = 30) -> dict: # async I/O here ...- ›Adds
format="langchain-openai"parameter toadd_messagesto automatically convert message content (strings, text blocks, image_url blocks) to OpenAI-compatible format. - ›Enables
add_messagesas a partial function when called without arguments, improving flexibility in type annotations. - ›Rewrites the
taskdecorator to support both direct (@task) and parameterized (@task(...)) usage, with proper coroutine detection and wrapping for async functions. - ›Expands
taskdecorator function signature to accept*argsand**kwargsand adds overloads for better IDE type inference.
- ›Adds
- checkpointpostgres==2.0.9
LangGraph Postgres checkpointer adds ShallowPostgresSaver and AsyncShallowPostgresSaver for lightweight, history-free checkpoint storage.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.9 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.9
- ›Adds
ShallowPostgresSaver, a drop-in replacement forPostgresSaverthat stores only the most recent checkpoint, reducing storage when time travel is not needed. - ›Adds
AsyncShallowPostgresSaver, the async counterpart toShallowPostgresSaver, with the same lightweight storage semantics and a full async interface.
└──▷ BREAKING ON UPGRADE- !The
batchmethod has been removed fromAsyncPostgresStore; callers must switch toabatchinstead.
- ›Adds
- sdk==0.1.48
LangGraph SDK 0.1.48 adds StudioUser class for fine-grained authorization control over LangGraph Studio UI access.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.48 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.48
└──▷ USE ITGate a resource to non-Studio users only — useful when you want to block Studio UI access to sensitive operations in production.from langgraph_sdk.auth.types import StudioUser def my_auth_handler(user, action, resource): if isinstance(user, StudioUser): raise PermissionError("Studio users cannot access this resource") return TrueDisable Studio authentication entirely for environments where Studio UI access should be unrestricted.{ "disable_studio_auth": true }- ›Adds
StudioUserclass inlanggraph_sdk/auth/types.pyrepresenting authenticated users from the LangGraph Studio UI, exposing properties for username, display name, identity, permissions, and auth status. - ›Enables custom authorization handlers to branch on Studio vs. non-Studio users via isinstance(user, StudioUser) checks.
- ›Supports disabling Studio authentication entirely via
disable_studio_auth: trueinlanggraph.json.
- ›Adds
- 0.2.60
LangGraph 0.2.60 makes Command.update accept any type and relaxes tool node validation for multi-message responses.
└──▷ GET THIS VERSION$ git clone --branch 0.2.60 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.60
└──▷ USE ITPass a custom non-dict value (e.g. a string or dataclass) through Command.update when routing between nodes — previously impossible without wrapping in a dict.from langgraph.types import Command # Now valid: update can be any type, including None or a plain string cmd = Command(goto="next_node", update="my_custom_payload")
Return multiple tool messages from a tool node (e.g. for logging + result) without triggering a validation error, as long as one message matches the tool call ID.from langchain_core.messages import ToolMessage from langgraph.types import Command # Both messages returned; validation passes because one has the matching tool_call_id cmd = Command( update={ "messages": [ ToolMessage(content="debug info", tool_call_id="other-id"), ToolMessage(content="actual result", tool_call_id="call-123"), ] } )- ›Extends
Command.updateto accept any type of value (not just dicts or sequences of tuples), including None, enabling more diverse node-to-node command patterns. - ›Relaxes prebuilt
tool_nodevalidation to allow multiple tool messages in a command update, requiring only that at least one message matches the tool call ID.
└──▷ BREAKING ON UPGRADE- !The default value of
Command.updatechanged from () (empty tuple) to None; code that checks if command.update == () or relies on the empty-tuple default will behave differently.
- ›Extends
- sdk==0.1.47
LangGraph SDK 0.1.47 simplifies auth handlers and renames scopes to permissions in the Auth module.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.47 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.47
└──▷ USE ITReturn a user object directly from an auth handler instead of the old (scopes, user) tuple pattern.from langgraph_sdk.auth import Auth auth = Auth() @auth.authenticate async def authenticate(authorization: str) -> dict: user_id = verify_token(authorization) # your token logic return {"identity": user_id, "permissions": ["runs:create", "threads:read"]}- ›Simplifies authentication handler return type: handlers now return a user representation directly (string, dict, or object) instead of a (scopes, user) tuple.
- ›Adds
permissionsfield toMinimalUserDictandpermissionsproperty to theBaseUserinterface inAuth.types. - ›Updates Authenticator type signature to reflect the new single-object return format.
└──▷ BREAKING ON UPGRADE- !The
scopesfield/property is renamed topermissionsthroughout the Auth module — any code referencingscopeson auth objects orMinimalUserDictwill break. - !Authentication handlers must now return a single user representation (string, dict with
identity/permissions, or compatible object) instead of a tuple of (scopes, user).
- cli==0.1.64
LangGraph CLI now validates
dependenciesin configuration, with graceful fallback when the field is absent.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.64 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.64
- ›Adds
dependenciesfield validation tovalidate_config, ensuring dependency declarations are checked and included during config processing.
- ›Adds
- sdk==0.1.46
LangGraph SDK 0.1.46 adds HTTPException to auth handlers for precise HTTP error control
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.46 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.46
└──▷ USE ITReturn a 403 with a custom message from an auth handler instead of the default 401 Unauthorized.from langgraph_sdk import Auth auth = Auth() @auth.authenticate async def my_auth_handler(token: str): if not is_valid(token): raise auth.exceptions.HTTPException( status_code=403, detail="You do not have permission to access this resource." ) return {"user": decode(token)}- ›Adds HTTPException class to
Auth.exceptions, letting auth handlers return custom HTTP status codes, error messages, and headers instead of generic failures. - ›Exposes
exceptionsmodule on the Auth class for clean, importable access to auth-related exception types.
- ›Adds HTTPException class to
- cli==0.1.63
LangGraph CLI 0.1.63 adds OpenAPI security scheme configuration to AuthConfig for customizing API auth settings.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.63 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.63
- ›Adds
SecurityConfigTypedDict class for defining OpenAPI security schemes and requirements in authentication config. - ›Extends
AuthConfigwith a newopenapifield of typeSecurityConfig, enabling customization of API security settings such as OAuth2 scopes and token endpoints.
- ›Adds
- cli==0.1.62
LangGraph CLI 0.1.62 adds auth configuration support for LangGraph Studio with a new AuthConfig type.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.62 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.62
└──▷ USE ITDisable Studio's built-in auth and point to a custom auth handler when running the dev server locally.# langgraph.json { "auth": { "path": "./my_auth.py:handler", "disable_studio_auth": true } }- ›New
AuthConfigTypedDict withpathanddisable_studio_authfields enables custom authentication configuration for LangGraph Studio. - ›New
authfield on the main Config TypedDict wires auth settings into config validation and Docker environment generation. - ›The
devcommand now accepts auth configuration, allowing Studio auth to be controlled at dev-server launch time.
- ›New
- sdk==0.1.45
LangGraph SDK 0.1.45 adds an Auth class with decorator-based authentication and fine-grained per-resource authorization.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.45 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.45
└──▷ USE ITProtect all LangGraph resources with a global auth handler that validates a bearer token and returns user scopes.from langgraph_sdk import Auth auth = Auth() @auth.authenticate async def verify_token(token: str): # validate token and return user scopes user = await my_token_validator(token) return {"id": user.id, "scopes": user.scopes} @auth.on async def global_handler(ctx, value): # allow only requests where the resource owner matches the caller if ctx.user.id != value.get("owner"): raise Auth.exceptions.HTTPException(status_code=403)Apply a resource-specific rule so only thread owners can read their own threads, while leaving other resources on the global handler.from langgraph_sdk import Auth auth = Auth() @auth.on.threads.read async def restrict_thread_reads(ctx, value): # inject a filter so the query only returns threads owned by the caller return {"owner": ctx.user.id}- ›Adds Auth class providing a unified authentication and authorization system for LangGraph applications.
- ›Supports decorator-based auth handlers to verify credentials and return user scopes.
- ›Enables fine-grained access control per resource (threads, assistants, crons) and per action (create, read, update, delete, search).
- ›Implements a hierarchical handler system supporting global fallback handlers alongside specific per-action handlers.
- ›Introduces a new types module with typed dictionaries (e.g.,
ThreadsCreate,AssistantsRead), protocol definitions for user objects and auth handlers, and strongly-typed context objects.
- 0.2.59
LangGraph 0.2.59 enables config-aware tool execution by passing configuration to prebuilt tool node invocations.
└──▷ GET THIS VERSION$ git clone --branch 0.2.59 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.59
- ›Enables prebuilt tool node to pass the configuration object to tools during both synchronous (
invoke) and asynchronous (ainvoke) execution, allowing tools to access runtime configuration parameters.
- ›Enables prebuilt tool node to pass the configuration object to tools during both synchronous (
- 0.2.58
LangGraph 0.2.58 adds string node names in Command.goto and richer config metadata with defaults and descriptions.
└──▷ GET THIS VERSION$ git clone --branch 0.2.58 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.58
└──▷ USE ITRoute to a node by name directly in Command.goto instead of wrapping it in a Send object.from langgraph.types import Command # Previously required Send; now a plain string works def my_node(state): return Command(goto="approval_node")Inspect richer config metadata — including defaults and descriptions — for a compiled graph.from langgraph.utils.fields import get_enhanced_type_hints # Get type hints plus defaults and descriptions for a config schema hints = get_enhanced_type_hints(MyConfigSchema) print(hints)
- ›Supports string values in
Command.goto, enabling direct node-name references instead of requiring Send objects for state transitions. - ›Adds
get_enhanced_type_hintsutility to extract type hints along with default values and descriptions, covering Pydantic models, TypedDict, and dataclasses. - ›Enriches
Pregel.config_specsoutput with default values and descriptions for configuration fields viaget_enhanced_type_hints.
- ›Supports string values in
- 0.2.57
LangGraph 0.2.57 adds a functional API with
@task/@entrypointdecorators and lets tools return Command objects.└──▷ GET THIS VERSION$ git clone --branch 0.2.57 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.57
└──▷ USE ITRun two LLM calls in parallel inside a functional-API workflow — use@taskso both futures resolve concurrently, then collect results in the@entrypoint.from langgraph.func import task, entrypoint @task def call_model_a(prompt: str) -> str: return llm_a.invoke(prompt) @task def call_model_b(prompt: str) -> str: return llm_b.invoke(prompt) @entrypoint() def compare_models(prompt: str) -> dict: future_a = call_model_a(prompt) future_b = call_model_b(prompt) return {"a": future_a.result(), "b": future_b.result()} result = compare_models.invoke("Explain quantum entanglement")Return a Command from a tool to redirect graph control flow — now supported directly inToolNodewithout extra wiring.from langchain_core.tools import tool from langgraph.types import Command @tool def escalate_to_human(reason: str) -> Command: """Escalate the conversation to a human agent.""" return Command(goto="human_node", update={"escalation_reason": reason}) # Register with ToolNode as usual — Command routing is handled automatically from langgraph.prebuilt import ToolNode tool_node = ToolNode([escalate_to_human])- ›Adds
@taskdecorator (langgraph.func.task) for creating parallel async tasks that return futures, with optional retry policies. - ›Adds
@entrypointdecorator (langgraph.func.entrypoint) to wrap regular or generator functions into Pregel graphs as callable entry points. - ›Enables Command objects to be returned directly from LangChain tools via
ToolOutputMixincompatibility andToolNodesupport. - ›Adds
StateGraphsupport for lists of Command objects and tuple-based state updates in node outputs. - ›Adds
_repr_mimebundle_to Graph for inline Mermaid diagram visualization in Jupyter notebooks.
- ›Adds
- sdk==0.1.43
LangGraph SDK 0.1.43 adds query-param streaming and expands Command routing flexibility
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.43 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.43
└──▷ USE ITFilter a streaming run by passing query parameters directly on the stream call, avoiding manual URL construction.async for chunk in client.stream( assistant_id, thread_id, input=input_data, params={"my_filter": "value", "limit": 10}, ): print(chunk)Route a command to multiple destinations using the expandedgotofield that now accepts a sequence of Send objects or node-name strings.from langgraph.types import Command, Send cmd = Command(goto=[Send("node_a", {"x": 1}), "node_b"])- ›Adds optional
paramsargument to HttpClient.stream() (async and sync) so query parameters can be passed with streaming requests. - ›Expands Command TypedDict's
gotofield to accept Send,str, or a sequence of either, enabling richer graph routing in command structures.
└──▷ BREAKING ON UPGRADE- !The Command TypedDict field
sendis renamed togoto; any code referencing Command(send=...) will break on upgrade.
- ›Adds optional
- 0.2.55
LangGraph 0.2.55 overhauls interrupt/resume with scratchpad tracking and consolidates Send into the goto field
└──▷ GET THIS VERSION$ git clone --branch 0.2.55 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.55
└──▷ USE ITPass both a static node name and a dynamic Send object in a single Command, now that goto accepts both types.from langgraph.types import Command, Send # Route to a named node and dynamically send a message to another node cmd = Command(goto=["review_node", Send("process_node", {"input": data})])Handle multiple sequential interrupts inside one node reliably — the rewritten interrupt function tracks counts so each resume value is matched correctly.from langgraph.types import interrupt def my_node(state): first_answer = interrupt("Please provide your name") second_answer = interrupt("Please provide your role") return {"name": first_answer, "role": second_answer}- ›Adds
CONFIG_KEY_WRITESconstant exposing a read-only list of existing task writes to task configuration - ›Adds
CONFIG_KEY_SCRATCHPADconstant providing temporary storage scoped to the current task - ›Rewrites the
interruptfunction with interrupt-count tracking to correctly handle multiple interrupts within the same node - ›Enables
gotofield on Command to accept both string node names and Send objects, unifying send/goto into one API - ›Deduplicates writes to special channels in
PregelLoop.put_writes(last write wins)
└──▷ BREAKING ON UPGRADE- !The
sendfield is removed from the Command class; any code passingsend=to Command will break — usegotoinstead. - !The
CONFIG_KEY_RESUME_VALUEconstant is removed; code referencing it directly will break — useCONFIG_KEY_WRITESandCONFIG_KEY_SCRATCHPADinstead.
- ›Adds
- 0.2.54
LangGraph 0.2.54 adds parent-graph command routing, empty-tool ReAct agents, and Command input support for RemoteGraph.
└──▷ GET THIS VERSION$ git clone --branch 0.2.54 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.54
└──▷ USE ITSend a command from a subgraph node up to the parent graph to update parent state or redirect control flow.from langgraph.types import Command def subgraph_node(state): # Direct this command at the parent graph instead of the current one return Command(goto="some_parent_node", update={"status": "delegated"}, graph=Command.PARENT)Build a zero-tool ReAct agent for pure LLM reasoning tasks where no external tools are needed.from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI agent = create_react_agent(ChatOpenAI(model="gpt-4o"), tools=[]) result = agent.invoke({"messages": [{"role": "user", "content": "Summarise the history of cryptography."}]})Pass a Command object directly into a RemoteGraph to resume or redirect a running remote workflow.from langgraph.pregel.remote import RemoteGraph from langgraph.types import Command remote = RemoteGraph("my-deployed-graph", url="https://my-langgraph-server") for chunk in remote.stream(Command(goto="review_node", update={"approved": True}), config={"thread_id": "abc123"}): print(chunk)- ›Adds
Command.PARENTconstant ("__parent__") and agraphfield on Command so nodes in a subgraph can route commands up to the parent graph. - ›Adds
GraphBubbleUpbase exception class and newParentCommandexception to propagate parent-directed commands cleanly through the graph hierarchy. - ›Enables
create_react_agentto accept an empty tools list, producing a simple LLM-only graph without tool-calling plumbing. - ›Enables
RemoteGraph.streamandRemoteGraph.invoketo accept Command objects directly as input, with pass-through of additional client kwargs. - ›Graph validation now only requires at least one edge from START; unreachable nodes no longer cause a validation error.
+1 moreshow less
- ›Adds Python 3.11+ exception notes in retry mechanisms for richer error diagnostics when tasks fail.
- ›Adds
- sdk==0.1.42
LangGraph SDK 0.1.42 adds run status filtering, cancel-on-disconnect streaming, and command support in assistant APIs.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.42 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.42
└──▷ USE ITList only runs that are currently pending or running — useful for building dashboards or cleanup scripts that act on in-progress work.runs = await client.runs.list(thread_id="<thread_id>", status="pending")
Stream a run and ensure it is automatically cancelled server-side if your client drops the connection, preventing orphaned background work.async for chunk in client.runs.join_stream(thread_id="<thread_id>", run_id="<run_id>", cancel_on_disconnect=True): print(chunk)Pass a command to an assistant stream to steer execution dynamically at invocation time.async for chunk in client.assistants.stream(assistant_id="<assistant_id>", command=<command>): print(chunk)- ›Adds
statusparameter to RunsAPI.list() to filter runs by execution status. - ›Adds
cancel_on_disconnectparameter to RunsAPI.join_stream() to automatically cancel a run when the client disconnects from the stream. - ›Adds
commandparameter to AssistantAPI.stream(), .create(), and .wait() for finer control over assistant execution. - ›Adds Interrupt type definition and exposes interrupt information on the Thread schema for improved interrupt handling.
- ›Adds
- checkpointpostgres==2.0.7
langgraph-checkpoint-postgres 2.0.7 adds configurable vector indices (HNSW, IVFFlat, flat) and improved vector search ordering.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.7
└──▷ USE ITUse an IVFFlat index with a custom cluster count when you have a large embedding dataset and want to trade recall for speed.from langgraph.store.postgres.base import ANNIndexConfig, IVFFlatConfig index_config = ANNIndexConfig( kind="ivfflat", ann_index_config=IVFFlatConfig(nlist=256), )- ›Adds
ANNIndexConfigwith akindfield to select vector index type:'hnsw','ivfflat', or'flat'. - ›Adds HNSWConfig class for tuning HNSW indices via
m(max connections per layer) andef_construction(dynamic candidate list size). - ›Adds
IVFFlatConfigclass for tuning IVFFlat indices vianlist(number of inverted lists/clusters). - ›Adds automatic vector index creation in
BasePostgresStorebased on the supplied index configuration. - ›Adds
conditionfield to Migration to support conditional migration execution based on store configuration.
- ›Adds
- cli==0.1.61
LangGraph CLI adds
--wait-for-clientflag for blocking debug startup and isolates store config intoLANGGRAPH_STORE.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.61 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.61
└──▷ TRY ITPause the dev server at startup until your IDE debugger attaches, so you can set breakpoints before any graph code runs.$ langgraph dev --debug-port 5678 --wait-for-client
- ›Adds
--wait-for-clientflag to thedevcommand that, combined with--debug-port, pauses server startup until a debugger client connects. - ›Introduces dedicated
LANGGRAPH_STOREenvironment variable for store configuration in Docker environments, replacing the previous embedding insideLANGGRAPH_CONFIG.
└──▷ BREAKING ON UPGRADE- !Store configuration in Docker environments is now passed via
LANGGRAPH_STOREinstead ofLANGGRAPH_CONFIG; any tooling or scripts that read store config fromLANGGRAPH_CONFIGwill no longer receive it there.
- ›Adds
- checkpointpostgres==2.0.5
langgraph-checkpoint-postgres 2.0.5 adds pgvector-powered semantic search to PostgreSQL-backed LangGraph stores.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.5
- ›Adds
PostgresIndexConfigclass to configure pgvector-backed vector search with configurable dimensions, distance metrics (l2, inner_product, cosine), and vector types (vector, halfvec). - ›Enables vector similarity search and embedding-based document indexing and retrieval in
BasePostgresStore. - ›Adds async embedding and vector search support to
AsyncPostgresStorefor non-blocking document indexing and retrieval. - ›Introduces
_row_to_search_itemto surface similarity scores as float values alongside search results.
- ›Adds
- cli==0.1.60
LangGraph CLI 0.1.60 adds vector store configuration with embedding specs, enabling semantic search in LangGraph projects.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.60 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.60
└──▷ USE ITConfigure a vector store with an embedding model in your LangGraph project config to enable semantic search over stored data.from langgraph_cli.config import IndexConfig, StoreConfig store = StoreConfig( index=IndexConfig( dims=1536, embed="openai:text-embedding-3-small", fields=["text", "description"], ) )- ›Adds
IndexConfigandStoreConfigconfiguration types to specify vector embedding dimensions (dims), model selection (embed), and custom field extraction (fields) for semantic search. - ›Enables the
devcommand to pass store configuration fromconfig.jsonto the LangGraph server at runtime. - ›Supports store settings in Docker container deployments via environment variable pass-through.
- ›Adds
python-dotenvas an optional dependency for environment variable management.
- ›Adds
- sdk==0.1.40
LangGraph SDK 0.1.40 adds natural language search to the store with relevance scoring and fine-grained index control.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.40 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.40
└──▷ USE ITRun a natural language query against the store and inspect relevance scores to surface the most pertinent items.results = await client.store.search_items(namespace, query="latest customer complaints about billing") for item in results.items: print(item.score, item.key, item.value)Store an item while limiting indexing to specific fields, reducing noise in semantic search results.await client.store.put_item(namespace, key="user-42", value={"name": "Alice", "notes": "VIP customer", "internal_id": 99}, index=["name", "notes"])Exclude a sensitive item from search indexing entirely so it cannot be surfaced via natural language queries.await client.store.put_item(namespace, key="secret-config", value={"api_key": "s3cr3t"}, index=False)- ›Adds
queryparameter tosearch_items(sync and async) enabling natural language search over stored items. - ›Introduces
SearchItemclass extending Item with an optionalscorefield, so callers can rank results by relevance. - ›Updates
SearchItemsResponseto returnlist[SearchItem]instead oflist[Item], surfacing relevance scores in all search results. - ›Adds
indexparameter toput_item(sync and async) to control per-item indexing: None for default, False to skip indexing, or alist[str]of field paths to index selectively.
└──▷ BREAKING ON UPGRADE- !
SearchItemsResponsenow returnslist[SearchItem]instead oflist[Item]; code that type-checks or pattern-matches on Item from search results will need updating.
- ›Adds
- checkpoint==2.0.7
LangGraph checkpoint 2.0.7 adds vector/semantic search to stores, richer query filters, and embedding utilities.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.7
└──▷ USE ITEnable semantic search on an in-memory store so an agent can retrieve memories by meaning rather than exact key.from langgraph.store.memory import InMemoryStore from langgraph.store.base import IndexConfig from langchain_openai import OpenAIEmbeddings store = InMemoryStore( index=IndexConfig( dims=1536, embed=OpenAIEmbeddings(model="text-embedding-3-small"), fields=["text", "summary"], ) ) # Store an item (indexed by default) await store.aput(("users", "alice"), "mem-1", {"text": "Alice prefers dark mode."}) # Retrieve semantically similar items results = await store.asearch(("users", "alice"), query="UI preferences", limit=5) for item in results: print(item.key, item.score, item.value)Wrap a custom embedding function (e.g. a local model) into LangChain's interface so it works withIndexConfig.from langgraph.store.base.embed import ensure_embeddings import numpy as np def my_embed(texts: list[str]) -> list[list[float]]: # Replace with your local model call return [np.random.rand(768).tolist() for _ in texts] embeddings = ensure_embeddings(my_embed) from langgraph.store.base import IndexConfig config = IndexConfig(dims=768, embed=embeddings)Use comparison-operator filters alongside a semantic query to narrow store search results to recent, high-relevance items.results = await store.asearch( ("projects", "sec-team"), query="privilege escalation techniques", filter={"severity": {"$gt": 7}, "status": {"$eq": "open"}}, limit=10, ) for item in results: print(item.key, item.score, item.value["severity"])- ›Adds semantic similarity search to
BaseStorevia an updatedsearch/asearchinterface that returns rankedSearchIteminstances with ascorefield. - ›Introduces
IndexConfigclass to configure vector search settings — embedding dimensions, embedding function, and which fields to index — per store. - ›Adds
indexparameter toput/aput(andPutOp) to control per-item vector indexing: use default indexing, disable with False, or specify custom field paths. - ›Adds
queryparameter toSearchOpfor natural-language semantic search alongside existing namespace/filter queries. - ›Enhances query filtering in
SearchOpwith comparison operators ($eq,$gt,$lt, and others) including support for nested fields and array path expressions.
+3 moreshow less
- ›Adds
ensure_embeddingsutility to wrap any sync or async embedding function into LangChain's Embeddings interface, plusEmbeddingsFunc/AEmbeddingsFunctype definitions. - ›Adds
get_text_at_pathandtokenize_pathutilities for extracting text from nested objects using path expressions with support for wildcards, array indexing, and multi-field selection. - ›Rewrites
InMemoryStorewith full vector search support and optional NumPy acceleration for vector operations.
└──▷ BREAKING ON UPGRADE- !
NameSpacePathis renamed toNamespacePath; code importing or referencingNameSpacePathwill break. - !
searchandasearchonBaseStorenow returnSearchIteminstances instead of plain Item instances; code that expects Item objects from these methods may break.
- ›Adds semantic similarity search to
- checkpointpostgres==2.0.4
langgraph-checkpoint-postgres 2.0.4 adds connection pooling, pipeline optimization, and last-write-wins deduplication for Postgres stores.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.4
- ›New
PoolConfigTypedDict inlanggraph.store.postgres.baselets you configure min/max connections and extra connection parameters for PostgreSQL connection pools. - ›Adds connection pooling support to both
PostgresStoreandAsyncPostgresStorefor improved throughput under high concurrency. - ›Adds pipelined database operations to
PostgresStoreandAsyncPostgresStore, batching queries for higher throughput. - ›Adds last-write-wins deduplication semantics for concurrent operations on the same key in
PostgresStore. - ›Adds thread locking (
PostgresStore) and async locks (AsyncPostgresStore) for safe concurrent access.
+1 moreshow less
- ›Improves inheritance support in
PostgresSaverandAsyncPostgresSaverby usingclsinstead of hardcoded class names, enabling reliable subclassing.
- ›New
- checkpoint==2.0.6
LangGraph checkpoint 2.0.6 adds async namespace listing and batch operation deduplication to AsyncBatchedBaseStore.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.6
└──▷ USE ITDiscover which namespaces exist in your store, filtered by prefix and bounded by depth — useful for auditing or scoping operations in multi-tenant graphs.namespaces = await store.alist_namespaces(prefix=("user", "alice"), depth=3, limit=50)- ›Adds
alist_namespacesmethod toAsyncBatchedBaseStorefor querying namespaces with filtering by prefix, suffix, depth, and pagination. - ›Improves batch performance in
AsyncBatchedBaseStorevia a new_dedupe_opsfunction that deduplicates identical get/search operations and consolidates multiple puts to the same key. - ›Extends
CheckpointMetadata.sourceto accept"fork"as a valid value, identifying checkpoints created as copies of other checkpoints.
- ›Adds
- cli==0.1.59
LangGraph CLI dev command now auto-loads config-file dependencies onto Python's path
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.59 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.59
- ›Enables the
devcommand to read thedependenciesfield from the config file and add those directories to Python's path automatically. - ›Automatically adds the current working directory to Python's path when running the
devcommand, allowing seamless local module imports.
- ›Enables the
- cli==0.1.58
LangGraph CLI 0.1.58 adds
envparameter to pass environment variables from config file to the dev server.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.58 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.58
└──▷ USE ITSet environment variables in your LangGraph config so they are automatically available when running the dev server — no need to export them separately in your shell.env: OPENAI_API_KEY: "sk-..." MY_CUSTOM_VAR: "value"
- ›Supports passing environment variables from the configuration file to the development server via a new
envparameter.
- ›Supports passing environment variables from the configuration file to the development server via a new
- cli==0.1.56
LangGraph CLI 0.1.56 adds Python 3.13 support and Node.js/package.json compatibility validation.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.56 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.56
└──▷ USE ITProgrammatically load and validate a langgraph config file (replaces separate load + validate calls).from langgraph_cli.config import validate_config_file config = validate_config_file("langgraph.json")- ›Supports Python 3.13 as a valid runtime in langgraph-cli config.
- ›Adds validate_config_file() function that loads and validates config files in a single call.
- ›Validates Node.js version compatibility against
package.jsonwhen present in a project. - ›Introduces
MIN_NODE_VERSIONandMIN_PYTHON_VERSIONconstants for centralized version requirement enforcement.
- cli==0.1.55
LangGraph CLI gains a
langgraph devcommand for running the API server in development mode with hot reloading.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.55 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.55
└──▷ TRY ITSpin up a hot-reloading local LangGraph API server during development without launching a browser, binding to a custom port.$ langgraph dev --port 8123 --no-browser --config langgraph.json
Install the CLI with in-memory API support to runlanggraph devwithout a full backend dependency.$ pip install "langgraph-cli[inmem]"- ›New
langgraph devcommand runs the LangGraph API server in development mode with hot reloading and options for--host,--port,--no-reload,--config,--n-jobs-per-worker,--no-browser, and--debug-port. - ›New
inmemextras entry enables lightweight in-memory API support viapip install "langgraph-cli[inmem]".
- ›New
- 0.2.51
LangGraph 0.2.51 adds checkpoint forking to Pregel via a new
__copy__node.└──▷ GET THIS VERSION$ git clone --branch 0.2.51 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.51
- ›Adds checkpoint forking in Pregel via a new
__copy__special node: whenas_node="__copy__"andvalues=None, creates a copy of the checkpoint with a "fork" source marker and preserved parent metadata.
- ›Adds checkpoint forking in Pregel via a new
- checkpoint==2.0.5
LangGraph checkpoint 2.0.5 adds disk-persistent checkpoints via PersistentDict and a configurable MemorySaver storage backend.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.5
└──▷ USE ITPersist agent checkpoints to disk across process restarts instead of losing state when the process exits.from langgraph.checkpoint.memory import MemorySaver, PersistentDict with MemorySaver(factory=lambda: PersistentDict("/tmp/checkpoints.pkl")) as saver: # compile and run your graph with `saver` as the checkpointer graph = my_graph.compile(checkpointer=saver) graph.invoke({"messages": []}, config={"configurable": {"thread_id": "session-1"}})- ›New
PersistentDictclass provides dictionary-like checkpoint storage backed by disk, using atomic writes for data safety. - ›Adds a
factoryparameter toMemorySaverto swap in custom storage backends, including the newPersistentDict.
- ›New
- 0.2.50
LangGraph 0.2.50 adds the ability to create snapshot checkpoints without modifying graph state.
└──▷ GET THIS VERSION$ git clone --branch 0.2.50 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.50
└──▷ USE ITCapture a mid-execution snapshot of a running graph without altering its state, useful for audit trails or rollback points.await graph.aupdate_state(config, values=None, as_node=None)
- ›Enables creating checkpoint snapshots mid-execution via
aupdate_statewithout applying any state changes (passvalues=None, as_node=None).
- ›Enables creating checkpoint snapshots mid-execution via
- 0.2.49
LangGraph 0.2.49 adds checkpoint copying and a debug parameter to graph execution loops.
└──▷ GET THIS VERSION$ git clone --branch 0.2.49 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.49
└──▷ USE ITSnapshot the current graph checkpoint without modifying state — useful before a risky branch of execution.graph.update_state(config, values=None, as_node=None)
- ›Supports copying the current checkpoint by calling
update_statewith bothvalues=Noneandas_node=None. - ›Adds a
debugparameter to loop creation in Pregel for improved visibility into graph execution.
- ›Supports copying the current checkpoint by calling
- cli==0.1.54
LangGraph CLI gains a
newproject scaffolding command, Docker Compose generation, and five built-in agent templates.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.54 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.54
└──▷ TRY ITBootstrap a new ReAct-style agent project without writing boilerplate — pick a template interactively and start coding immediately.$ langgraph new my-agent-projectGenerate a full local-dev stack (Dockerfile + docker-compose.yml + .env + .dockerignore) in one shot so you candocker compose upright away.$ langgraph dockerfile --add-docker-compose langgraph.json
- ›Adds
newcommand to scaffold LangGraph projects interactively from five built-in templates (minimal chatbot, ReAct Agent, Memory Agent, Retrieval Agent, Data-enrichment Agent). - ›Adds
--add-docker-composeflag to thedockerfilecommand, generating a docker-compose.yml, .env, and .dockerignore alongside the Dockerfile. - ›Adds
--versionflag to display the installed CLI version.
- ›Adds
- checkpoint==2.0.4
langgraph-checkpoint 2.0.4 adds INTERRUPT and RESUME constants to support graph execution interruption and resumption.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.4
└──▷ USE ITReference the new constants when inspecting or filtering checkpoint writes for interrupt/resume events.from langgraph.checkpoint.serde.types import INTERRUPT, RESUME # Check whether a checkpoint write corresponds to an interrupt or resume def is_interrupt_write(write): return write.channel in (INTERRUPT, RESUME)- ›Adds
INTERRUPTandRESUMEconstants tolanggraph.checkpoint.serde.types, enabling interrupt and resume operations in graph execution checkpointing. - ›Reserves checkpoint write index values -3 and -4 for interrupt and resume operation types in
WRITES_IDX_MAP.
└──▷ BREAKING ON UPGRADE- !The
CommandProtocolclass has been removed fromlanggraph.checkpoint.serde.typesand its serialization handling dropped fromJsonPlusSerializer; any code referencingCommandProtocolwill break on upgrade.
- ›Adds
- sdk==0.1.36
LangGraph SDK 0.1.36 adds Command-based graph control, rollback cancellation, and a new messages-tuple stream mode.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.36 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.36
└──▷ USE ITResume a paused run at a specific node or inject a value mid-graph without supplying new top-level input.async for chunk in client.runs.stream( thread_id, assistant_id, command={"resume": "user_approved"}, stream_mode="messages-tuple", ): print(chunk)Roll back all side-effects of a run when cancelling, rather than just interrupting it in place.await client.runs.cancel(thread_id, run_id, action="rollback")
- ›Adds
commandparameter to stream(), create(), and wait() run methods, enabling direct node interaction and state manipulation without requiring input. - ›Adds new Command type with
send,update, andresumeoperations for fine-grained graph execution control. - ›Adds Send typed dictionary to support direct node targeting during runs.
- ›Enhances cancel() with a new
actionparameter supporting"interrupt"(default) or"rollback"modes to control cancellation behavior. - ›Adds
CancelActiontype to the schema to back the new cancellation modes.
+1 moreshow less
- ›Adds
"messages-tuple"as a newStreamModeliteral option.
└──▷ BREAKING ON UPGRADE- !"running" has been removed from
RunStatusliterals, which will break any code that checks for or matches against that status value.
- ›Adds
- 0.2.47
LangGraph 0.2.47 adds resumable interrupts via a new interrupt() function and Command(resume=…) parameter.
└──▷ GET THIS VERSION$ git clone --branch 0.2.47 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.47
└──▷ USE ITPause a node mid-graph for human-in-the-loop approval, then resume it with the reviewer's decision.from langgraph.types import interrupt, Command def review_node(state): # Pause execution and surface data to the caller decision = interrupt({"payload": state["draft"], "prompt": "Approve this draft?"}) # Execution resumes here once Command(resume=...) is issued return {"approved": decision} # From outside the graph, resume after the interrupt: graph.invoke(Command(resume=True), config=config)- ›Adds interrupt() function in
langgraph.typesenabling nodes to pause and later resume with specific values, with namespace tracking for accurate resumption. - ›Adds a
resumeparameter to the Command class to control resumption of graph execution after an interrupt. - ›Adds
RESUMEconstant inlanggraph.constantsto identify values used to resume a node after an interrupt. - ›Adds
NULL_TASK_IDconstant inlanggraph.constantsto handle writes not associated with any specific task, enabling global writes independent of task execution. - ›Supports pushing new tasks during graph execution, improving dynamic task scheduling.
- ›Adds interrupt() function in
- 0.2.46
LangGraph 0.2.46 adds
add_sequencefor linear node chains,GraphCommandclass, and explicit checkpointing opt-out.└──▷ GET THIS VERSION$ git clone --branch 0.2.46 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.46
└──▷ USE ITChain several processing nodes in order without manually adding edges between each pair.graph = StateGraph(MyState) graph.add_sequence([ ("ingest", ingest_node), ("analyze", analyze_node), ("summarize", summarize_node), ]) app = graph.compile()Compile a subgraph with checkpointing explicitly disabled so it inherits no checkpointer from the parent.subgraph = StateGraph(SubState) subgraph.add_node("step", step_node) subgraph.set_entry_point("step") compiled_sub = subgraph.compile(checkpointer=False)UseGraphCommandwithgototo conditionally redirect graph execution to a named node.from langgraph.graph.state import GraphCommand def router_node(state): if state["needs_review"]: return GraphCommand(goto="human_review", update={"routed": True}) return GraphCommand(goto="auto_approve")- ›Adds add_sequence() method to
StateGraphfor declaratively building a linear chain of nodes with edges auto-wired between them. - ›Introduces
GraphCommandclass (replacing deprecated Control) with agotoparameter for directing graph flow and updating state. - ›Supports passing False to StateGraph.compile(checkpointer=False) to explicitly disable checkpointing in a graph or subgraph.
- ›Adds add_sequence() method to
- checkpoint==2.0.3
LangGraph Checkpoint 2.0.3 adds CommandProtocol serialization support in JSON and MessagePack formats.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==2.0.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==2.0.3
- ›New
CommandProtocolinterface inlanggraph.checkpoint.serde.typesenables serialization of command objects (including update and send operations) that mirror the Command type from LangGraph. - ›Extends
JsonPlusSerializerto serializeCommandProtocolobjects in both JSON and MessagePack formats by encoding their attributes.
- ›New
- 0.2.45
LangGraph 0.2.45 adds a Control class so node functions can steer graph flow and send values to destination nodes directly.
└──▷ GET THIS VERSION$ git clone --branch 0.2.45 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.45
└──▷ USE ITRoute to different nodes from within a single node function based on runtime state, without wiring separate conditional edges.from langgraph.types import Control def router_node(state: dict) -> Control: if state["score"] > 0.9: return Control(goto="high_confidence_node", update={"routed": True}) else: return Control(goto="low_confidence_node", update={"routed": True})- ›New Control class lets node functions simultaneously update state and direct graph flow — including triggering specific next nodes or sending values to them.
- ›Nodes can now declare their potential destination nodes via type annotations on their return type, enabling static graph validation of routing paths.
- ›New
SELFconstant represents the implicit branch created to handle Control return values. - ›Metadata is now preserved across
update_state/aupdate_statecalls, so checkpoint metadata survives incremental updates.
- cli==0.1.53
LangGraph CLI 0.1.53 adds JavaScript/TypeScript project templates and arbitrary Docker build argument passthrough.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.53 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.53
- ›Adds a JavaScript/TypeScript project template for scaffolding
LangGraph.jsapplications, including TypeScript config, ESLint, Jest, and sample StateAnnotation-based graph. - ›Enables passing arbitrary Docker build arguments directly to the Docker build process in the
buildcommand. - ›Adds automatic Node.js package manager detection (npm, yarn, pnpm) based on lock files, selecting the correct install and build commands automatically.
└──▷ BREAKING ON UPGRADE- !The
--platformoption has been removed from the build command; use Docker's native passthrough parameters instead. - !The deprecated
testcommand has been removed; use theruncommand instead.
- ›Adds a JavaScript/TypeScript project template for scaffolding
- 0.2.44
LangGraph 0.2.44 adds chat history validation for ReAct agents and messages-tuple stream mode for remote graphs.
└──▷ GET THIS VERSION$ git clone --branch 0.2.44 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.44
└──▷ USE ITCatch incomplete ReAct chat histories early — the agent now raisesINVALID_CHAT_HISTORYif any AIMessage tool call lacks a matching ToolMessage, surfacing the bad call before it hits the LLM.from langgraph.errors import ErrorCode # The validation runs automatically inside create_react_agent; # catch it explicitly to handle incomplete histories gracefully. try: result = agent.invoke({"messages": chat_history}) except ValueError as e: if ErrorCode.INVALID_CHAT_HISTORY in str(e): print("Chat history has unmatched tool calls:", e)Stream a remote LangGraph deployment using the messages-tuple format, now transparently supported by RemoteGraph.from langgraph.pregel.remote import RemoteGraph remote = RemoteGraph(graph_id="my-graph", url="https://my-deployment.example.com") for chunk in remote.stream({"messages": []}, stream_mode="messages-tuple"): print(chunk)- ›Adds
INVALID_CHAT_HISTORYerror code and_validate_chat_historyfunction to catch mismatched tool call / tool response pairs in chat history before they reach the LLM. - ›Supports
messages-tuplestream mode format forRemoteGraph, automatically mapping it to themessagesmode. - ›Improves
RemoteGraphvisualization by resolving meaningful node names from node data instead of falling back to an empty string.
- ›Adds
- 0.2.42
LangGraph 0.2.42 improves nested streaming in RemoteGraph with proper parent-graph stream mode propagation.
└──▷ GET THIS VERSION$ git clone --branch 0.2.42 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.42
└──▷ USE ITStream a remote subgraph from a parent graph, letting the parent's stream modes flow through to the RemoteGraph automatically.from langgraph.pregel.remote import RemoteGraph remote = RemoteGraph("my-remote-graph", url="http://localhost:8000") # When invoked as a subgraph, RemoteGraph now inherits and propagates # the parent graph's stream modes and namespace context automatically. async for chunk in remote.astream( {"input": "hello"}, config={"configurable": {"thread_id": "abc"}}, stream_mode="updates", ): print(chunk)- ›Enables
RemoteGraphto accept stream-mode configuration from parent graphs and propagate it correctly through nested graph hierarchies. - ›Supports namespace information propagation between parent and child graphs during streaming sessions.
- ›Removes
eventsstream mode support in Pregel, as it was never functional.
└──▷ BREAKING ON UPGRADE- !The
eventsstream mode is explicitly no longer supported in Pregel; any working setup that requestedeventsas a stream mode will no longer function.
- ›Enables
- 0.2.40
LangGraph 0.2.40 adds DuckDB checkpointing, richer ToolNode error handling, and concurrency limiting for async executors.
└──▷ GET THIS VERSION$ git clone --branch 0.2.40 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.40
└──▷ USE ITUse a different state key for messages when your graph stores messages under a non-default key (e.g.,chat_history).tool_node = ToolNode(tools, messages_key="chat_history") condition = tools_condition(messages_key="chat_history")
Apply fine-grained ToolNode error handling: catch only specific exception types and format the error dynamically.from langgraph.prebuilt import ToolNode tool_node = ToolNode( tools, handle_tool_errors=(ValueError, KeyError), # only catch these types ) # — or use a callable for dynamic formatting — tool_node = ToolNode( tools, handle_tool_errors=lambda exc: f"Tool failed: {type(exc).__name__}: {exc}", )- ›Adds DuckDB checkpointing support via the new
langgraph-checkpoint-duckdbpackage. - ›Adds
messages_keyparameter toToolNodeandtools_conditionfor flexible integration with non-standard state schemas. - ›Enhances
ToolNodeerror handling: accepts a boolean, custom string, callable, or tuple of exception types to selectively catch and format errors, and attachesstatus="error"to error tool messages. - ›Adds concurrency limiting to
AsyncBackgroundExecutorviamax_concurrencyconfig parameter and semaphore-basedgatedutility. - ›Adds
node_finishedcallback parameter toPregelRunnerviaCONFIG_KEY_NODE_FINISHEDfor node-completion hooks.
+1 moreshow less
- ›Improves schema inference in
StateGraphfor class method node functions via the extracted_get_input_schema_from_type_hinthelper.
- ›Adds DuckDB checkpointing support via the new
- sdk==0.1.35
LangGraph SDK 0.1.35 adds error-handling control to
waitand raises default timeouts to 300 s└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.35 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.35
└──▷ USE ITPoll a long-running graph run without crashing your process on error — inspect the result yourself instead of catching an exception.result = await client.wait(thread_id, run_id, raise_error=False) if "__error__" in result: print("Run failed:", result["__error__"])- ›Adds
raise_errorparameter toLangGraphClient.waitandSyncLangGraphClient.wait, letting callers suppress exception raising and inspect error objects directly. - ›Increases default read/write timeouts from 60 s to 300 s in
get_clientandget_sync_client, enabling reliable use with long-running graph operations.
- ›Adds
- sdk==0.1.34
LangGraph SDK 0.1.34 adds
if_not_existsparameter and new"error"thread status for safer run handling.└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.34 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.34
└──▷ USE ITAuto-provision a thread on first run so a new user session starts without a separate thread-creation step.async for chunk in client.runs.stream( thread_id=user_thread_id, assistant_id="my-assistant", input={"messages": [{"role": "user", "content": "Hello"}]}, if_not_exists="create", ): print(chunk)Gate on thread existence explicitly — raise fast if the thread ID supplied by a client is stale or invalid.result = await client.runs.wait( thread_id=incoming_thread_id, assistant_id="my-assistant", input={"messages": [{"role": "user", "content": "Continue"}]}, if_not_exists="reject", # raises if thread_id not found )- ›Adds
if_not_existsparameter tostream,create, andwaitclient methods, letting callers auto-create a missing thread ("create") or reject the operation ("reject") instead of always raising. - ›Adds
"error"as a validThreadStatusvalue, surfacing when an exception occurred during task processing. - ›Widens type annotations for
stream_mode,interrupt_before,interrupt_after, andfeedback_keysfromlistto Sequence, accepting tuples and other sequences without casting.
- ›Adds
- 0.2.39
LangGraph 0.2.39 adds
TAG_NOSTREAMconstant, structured error codes, and finer streaming control.└──▷ GET THIS VERSION$ git clone --branch 0.2.39 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.39
└──▷ USE ITSuppress a cost-tracking or internal chat model call from appearing in the user-facing stream.from langgraph.constants import TAG_NOSTREAM # When binding or invoking a chat model you want kept off the stream, # pass TAG_NOSTREAM as a tag so StreamMessagesHandler skips it. silent_model = llm.with_config({"tags": [TAG_NOSTREAM]}) # Use silent_model inside a node as normal — its tokens won't be streamed. def my_node(state): result = silent_model.invoke(state["messages"]) return {"messages": [result]}Catch and branch on specific LangGraph error categories in production error handlers.from langgraph.errors import ErrorCode from langgraph.errors import GraphRecursionError try: graph.invoke(inputs) except GraphRecursionError as e: if ErrorCode.GRAPH_RECURSION_LIMIT.value in str(e): # surface a user-friendly message or increase recursion_limit print("Graph hit recursion limit — consider increasing recursion_limit or breaking cycles.")- ›New
TAG_NOSTREAMconstant inlanggraph.constantslets you tag chat models to suppress their output from the stream. - ›New
ErrorCodeenum inlanggraph.errorsprovides standardized codes (GRAPH_RECURSION_LIMIT,INVALID_CONCURRENT_GRAPH_UPDATE,INVALID_GRAPH_NODE_RETURN_VALUE,MULTIPLE_SUBGRAPHS) for programmatic error handling. - ›New
create_error_messagehelper inlanggraph.errorsgenerates consistent error messages with links to troubleshooting documentation. - ›
StreamMessagesHandlernow respectsTAG_NOSTREAMon chat model starts andTAG_HIDDENon chain starts for fine-grained control over what gets streamed.
- ›New
- 0.2.37
LangGraph 0.2.37 adds RemainingSteps managed value and LoopProtocol for finer-grained loop termination control.
└──▷ GET THIS VERSION$ git clone --branch 0.2.37 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.37
└──▷ USE ITGuard an agent node against runaway tool calls by checking how many steps remain — useful when you want to abort gracefully before hitting the recursion limit.from langgraph.managed import RemainingSteps def agent_node(state, remaining_steps: RemainingSteps): if remaining_steps < 2: # Not enough headroom — return a safe fallback instead of calling tools return {"messages": [AIMessage(content="Stopping early: too few steps remaining.")]} # ... normal tool-calling logic return model_with_tools.invoke(state["messages"])- ›Adds
RemainingStepsmanaged value to expose the number of remaining steps during loop execution, usable alongsideIsLastStepfor precise loop control. - ›Introduces
LoopProtocolinterface, giving managed values and channels structured access to loop execution context (config, store, stream, step, stop). - ›Improves checkpointing in nested loops with proper parent configuration propagation via updated
patch_checkpoint_map.
└──▷ BREAKING ON UPGRADE- !The
ManagedValue.__call__signature no longer accepts astepparameter; callers that passedstepexplicitly will break.
- ›Adds
- 0.2.36
LangGraph 0.2.36 adds RemoteGraph for interacting with hosted LangGraph deployments via the LangGraph API.
└──▷ GET THIS VERSION$ git clone --branch 0.2.36 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.36
└──▷ USE ITConnect to a remotely hosted LangGraph deployment and stream results — useful when your graph runs in production and you want to interact with it programmatically from a client.from langgraph.pregel.remote import RemoteGraph remote_graph = RemoteGraph( url="https://my-deployment.langgraph.app", api_key="<your-api-key>", graph_id="my-graph" ) async for chunk in remote_graph.astream({"input": "Hello"}): print(chunk)- ›New
RemoteGraphclass enables invoking, streaming, and inspecting state on remote LangGraph deployments through the LangGraph API. - ›New
PregelProtocoldefines a standard interface for interacting with graphs, providing both sync and async methods for state management, visualization, subgraph traversal, and execution. - ›Adds a
resultfield toPregelTaskto store and access structured task execution results in state snapshots.
- ›New
- sdk==0.1.33
LangGraph SDK 0.1.33 adds wildcard node interrupts, custom stream mode, and richer update_state returns.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.33 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.33
└──▷ USE ITInspect the checkpoint produced after patching thread state, so you can resume from or verify the exact saved point.response = await client.threads.update_state( thread_id=thread_id, values={"messages": [{"role": "assistant", "content": "Corrected reply"}]}, ) print(response) # ThreadUpdateStateResponse with checkpoint infoConsume custom stream events alongside standard ones to handle application-defined data emitted during a run.async for chunk in client.runs.stream( thread_id=thread_id, assistant_id=assistant_id, input={"messages": [{"role": "user", "content": "Hello"}]}, stream_mode=["messages", "custom"], ): print(chunk)- ›Supports passing
"*"tointerrupt_before/interrupt_afterparameters inRunsClientandCronClientto interrupt all nodes without listing them individually. - ›Adds
"custom"option toStreamMode, giving more flexibility in how streams are handled. - ›
update_statenow returns aThreadUpdateStateResponsecontaining checkpoint information instead of None. - ›Expands
update_statevaluesparameter to acceptSequence[dict]in addition to a singledict, enabling multi-dictionary state updates.
└──▷ BREAKING ON UPGRADE- !
update_stateonThreadsClientandSyncThreadsClientnow returnsThreadUpdateStateResponseinstead of None — code that assumes a None return (e.g., ignores or asserts on the return value) will behave differently.
- ›Supports passing
- 0.2.35
LangGraph 0.2.35 adds cross-thread memory for agents and a new
find_subgraph_pregelutility for nested graph introspection.└──▷ GET THIS VERSION$ git clone --branch 0.2.35 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.35
└──▷ USE ITInspect a compiled runnable to find whether it contains a Pregel subgraph, useful before attaching a checkpointer to a nested graph.from langgraph.pregel.utils import find_subgraph_pregel subgraph = find_subgraph_pregel(my_runnable) if subgraph: print("Found Pregel subgraph:", subgraph)- ›Adds cross-thread memory support in agent executors, enabling agents to retain information across separate conversation threads.
- ›Introduces
find_subgraph_pregelutility to recursively locate Pregel subgraphs within runnable components — useful for checkpoint handling and graph introspection. - ›Enhances
map_debug_checkpointto include task state information and properly maintain checkpoint namespaces for nested subgraph debugging.
- checkpointpostgres==2.0.1
AsyncPostgresStore now inherits from AsyncBatchedBaseStore, enabling efficient batched async operations.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==2.0.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==2.0.1
- ›Enables batched async operations in
AsyncPostgresStoreviaAsyncBatchedBaseStoreinheritance, reducing round-trips for high-throughput workloads. - ›Adds explicit
ORDER BY updated_at DESCto search queries inPostgresStore, providing consistent, deterministic result ordering.
└──▷ BREAKING ON UPGRADE- !
BasePostgresStoreis no longer a direct subclass ofBaseStore; code that relied on that inheritance chain (e.g., isinstance checks or super() calls throughBasePostgresStore) will break. - !
_deserializeris now a class attribute onBasePostgresStorerather than an instance attribute set in__init__; subclasses that override or referenceself._deserializerset during__init__may behave differently.
- ›Enables batched async operations in
- 0.2.34
LangGraph 0.2.34 adds a
storeparameter tocreate_react_agentfor cross-thread persistence.└──▷ GET THIS VERSION$ git clone --branch 0.2.34 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.34
└──▷ USE ITPersist memory across multiple user conversations by wiring a store into a ReAct agent at creation time.from langgraph.prebuilt import create_react_agent agent = create_react_agent( model=llm, tools=tools, checkpointer=checkpointer, # single-thread (per-conversation) state store=store, # cross-thread (multi-user) persistence )- ›Adds
storeparameter tocreate_react_agent, enabling data persistence across multiple threads (e.g., different users or conversations) alongside the existingcheckpointerparameter. - ›Adds a warning when
InjectedStoreannotation is used withoutlangchain-core >= 0.3.8, surfacing the dependency requirement at runtime.
- ›Adds
- 0.2.33
LangGraph 0.2.33 adds InjectedStore annotation so tools can read/write the LangGraph store without exposing it to the model.
└──▷ GET THIS VERSION$ git clone --branch 0.2.33 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.33
└──▷ USE ITGive a tool direct access to the LangGraph store (e.g. to look up or persist memory) without surfacing the store parameter to the LLM.from typing import Annotated from langgraph.prebuilt.tool_node import InjectedStore from langgraph.store.base import BaseStore def save_note(note: str, store: Annotated[BaseStore, InjectedStore()]) -> str: """Save a note to the store.""" store.put(("notes",), "latest", {"text": note}) return "Saved."- ›Adds
InjectedStoreannotation to inject LangGraph store objects directly into tool arguments, hiding them from the tool-calling model (similar toInjectedState). - ›Enhances
ToolNodeto automatically detect and inject the store for tools annotated withInjectedStore, with precomputed caching of state and store arguments for efficiency. - ›Enables
RunnableCallablekeyword arguments to override config values ininvokeandainvoke, giving callers finer control over execution.
- ›Adds
- sdk==0.1.32
LangGraph SDK 0.1.32 adds a key-value Store API with namespaced put, get, delete, search, and list operations for both async and sync clients.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.32 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.32
└──▷ USE ITPersist and retrieve agent memory across runs by storing key-value data in a user-scoped namespace.from langgraph_sdk import get_client client = get_client() # Store a user preference await client.store.put_item( namespace=("users", "alice"), key="preferences", value={"theme": "dark", "language": "en"} ) # Retrieve it later item = await client.store.get_item( namespace=("users", "alice"), key="preferences" ) print(item["value"])Search stored items within a namespace prefix to find relevant context for an agent, with filtering.from langgraph_sdk import get_client client = get_client() results = await client.store.search_items( namespace_prefix=("users",), filter={"language": "en"} ) for item in results["items"]: print(item["namespace"], item["key"], item["value"])Use the synchronous client in a non-async script to list all namespaces under a given prefix.from langgraph_sdk import get_sync_client client = get_sync_client() namespaces = client.store.list_namespaces(prefix=("users",)) for ns in namespaces["namespaces"]: print(ns)- ›New
StoreClientandSyncStoreClientclasses provide async and sync key-value storage withput_item,get_item,delete_item,search_items, andlist_namespacesmethods. - ›Adds
storeproperty toLangGraphClientandSyncLangGraphClientfor direct access to the new store API. - ›Exposes
get_sync_clientin module exports for easier access to the synchronous client. - ›New Item,
ListNamespaceResponse, andSearchItemsResponseTypedDicts formalize storage operation schemas. - ›Adds
output_schemafield to theGraphSchemaTypedDict.
+1 moreshow less
- ›
HttpClientandSyncHttpClientnow support JSON payloads in DELETE requests.
- ›New
- checkpointpostgres==1.0.11
LangGraph Postgres store now accepts a custom
deserializerparameter for user-controlled JSON loading.└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.11 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.11
└──▷ USE ITSupply a custom deserializer to handle non-standard JSON types (e.g., dates, decimals) stored in Postgres.import json from decimal import Decimal from langgraph.store.postgres import PostgresStore def my_deserializer(data: str): return json.loads(data, parse_float=Decimal) store = PostgresStore(conn_string="postgresql://user:pass@localhost/db", deserializer=my_deserializer)Use a custom deserializer with the async store in an async LangGraph workflow.import json from langgraph.store.postgres.aio import AsyncPostgresStore def my_deserializer(data: str): return json.loads(data, object_hook=lambda d: {k: v.upper() if isinstance(v, str) else v for k, v in d.items()}) store = AsyncPostgresStore(conn_string="postgresql://user:pass@localhost/db", deserializer=my_deserializer)- ›Adds optional
deserializerparameter toPostgresStoreandAsyncPostgresStore(viaBasePostgresStore), enabling custom JSON deserialization when loading values from the database.
- ›Adds optional
- checkpointpostgres==1.0.10
langgraph-checkpoint-postgres 1.0.10 adds sync and async PostgreSQL store implementations with batch ops, namespace listing, and schema migration.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.10
└──▷ USE ITInitialize the PostgreSQL store schema and persist/retrieve agent state in a synchronous workflow.from langgraph.store.postgres import PostgresStore with PostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb") as store: store.setup() # create tables and run migrations store.put(("agents", "session-42"), "state", {"step": 1, "status": "running"}) item = store.get(("agents", "session-42"), "state") print(item)Use the async store in an asyncio-based LangGraph agent to avoid blocking the event loop on database calls.import asyncio from langgraph.store.postgres.aio import AsyncPostgresStore async def main(): async with AsyncPostgresStore.from_conn_string("postgresql://user:pass@localhost/mydb") as store: await store.setup() await store.put(("sessions", "user-99"), "context", {"history": []}) results = await store.search(("sessions",)) print(results) asyncio.run(main())- ›New
PostgresStoreclass provides a synchronous PostgreSQL-backed store withget,put,search, and namespace-listing operations. - ›New
AsyncPostgresStoreclass mirrorsPostgresStorewith full async/await support via asyncio for non-blocking database access. - ›Both stores expose a from_conn_string() context manager for ergonomic connection management.
- ›Both stores include a setup() method to initialize the database schema and run migrations automatically.
- ›Explicit
__all__exports added to the postgres store modules for cleaner programmatic imports.
- ›New
- 0.2.29
LangGraph 0.2.29 expands create_react_agent to accept any LanguageModelLike and adds custom store support via configuration.
└──▷ GET THIS VERSION$ git clone --branch 0.2.29 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.29
└──▷ USE ITUse a non-BaseChatModel language model (any LanguageModelLike) directly with create_react_agent — useful when wrapping custom or third-party models.from langgraph.prebuilt import create_react_agent # model_like is any LanguageModelLike, not necessarily a BaseChatModel agent = create_react_agent(model=model_like, tools=[my_tool]) result = agent.invoke({"messages": [{"role": "user", "content": "Search for X"}]})- ›Expands
create_react_agentto acceptLanguageModelLikeinstead of onlyBaseChatModel, enabling use with a broader range of model types. - ›Adds support for custom stores via configuration in Pregel, with store parameter propagation through the execution stack.
- ›Migrates store implementation to langgraph-checkpoint, updating namespace representation from strings to tuples and switching methods from
list/puttosearch/batch.
└──▷ BREAKING ON UPGRADE- !The store namespace representation in
SharedValuechanged from strings to tuples; any code relying on string namespaces will need to be updated. - !Store method calls changed from
list/puttosearch/batch; code calling the old store methods directly will break.
- ›Expands
- checkpoint==1.0.13
LangGraph Checkpoint 1.0.13 introduces a namespaced key-value store API with sync/async ops and an in-memory implementation.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.13
└──▷ USE ITPersist and retrieve cross-session user facts in a namespaced store during graph execution.from langgraph.store.memory import InMemoryStore store = InMemoryStore() # Store a user fact under a namespaced key store.put(("users", "alice"), "preference", {"theme": "dark"}) # Retrieve it later item = store.get(("users", "alice"), "preference") print(item.value) # {"theme": "dark"}Search across a namespace prefix to find all items matching a filter — useful for multi-tenant or multi-session lookups.from langgraph.store.memory import InMemoryStore store = InMemoryStore() store.put(("sessions", "s1"), "summary", {"turns": 5}) store.put(("sessions", "s2"), "summary", {"turns": 12}) results = store.search(("sessions",)) for item in results: print(item.namespace, item.key, item.value)- ›Adds
BaseStoreabstract base class with sync and async CRUD operations (get/aget,put/aput,delete/adelete,search/asearch,list_namespaces/alist_namespaces,batch/abatch) for persistent, namespaced key-value storage. - ›Introduces Item as the core storage unit, carrying value data, key, namespace path, and timestamp metadata with equality comparison and dict conversion support.
- ›Ships
InMemoryStore, a fully-featured in-memoryBaseStoreimplementation backed by Python dicts for prototyping and testing without external dependencies. - ›Adds
AsyncBatchedBaseStore, which automatically coalesces async store operations into batches via a background task for higher throughput. - ›Extends
JsonPlusSerializerto serialize Item objects, enabling store items to round-trip correctly through checkpoint persistence.
- ›Adds
- checkpoint==1.0.12
LangGraph checkpoint 1.0.12 adds secret-value serialization support in JsonPlusSerializer.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.12 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.12
- ›Supports serializing objects that implement get_secret_value() in
JsonPlusSerializer, enabling proper handling of secure/secret values during checkpoint serialization and deserialization.
- ›Supports serializing objects that implement get_secret_value() in
- 0.2.27
LangGraph 0.2.27 adds namespace filtering to subgraph traversal and broadens BaseStore value types.
└──▷ GET THIS VERSION$ git clone --branch 0.2.27 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.27
└──▷ USE ITRetrieve only the subgraph matching a specific namespace when inspecting a deeply nested graph, avoiding a full traversal.subgraphs = list(graph.get_subgraphs(namespace="my_agent"))
- ›Adds optional
namespaceparameter toget_subgraphsandaget_subgraphsfor filtering subgraphs by name, improving performance in nested-subgraph graphs. - ›Automatically excludes subgraphs with checkpointing disabled (
checkpointer is False) from subgraph enumeration. - ›Broadens
BaseStorevalue type (V) fromdict[str, Any]to Any, enabling storage of arbitrary value types.
- ›Adds optional
- 0.2.25
LangGraph's ToolNode now supports multimodal tool responses, letting tools return images and structured data alongside text.
└──▷ GET THIS VERSION$ git clone --branch 0.2.25 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.25
└──▷ USE ITReturn an image from a tool so the LLM receives it as a structured content block rather than a stringified blob.from langgraph.prebuilt import ToolNode from langchain_core.tools import tool @tool def capture_screenshot(url: str) -> list: """Capture a screenshot and return it as image content.""" image_bytes = fetch_screenshot(url) # your existing logic return [{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": image_bytes}}] node = ToolNode([capture_screenshot])- ›Enhances
ToolNodeto handle multimodal content in tool responses, preserving image, image_url, text, and json content blocks instead of converting everything to strings.
- ›Enhances
- sdk==0.1.31
LangGraph SDK 0.1.31 adds assistant versioning, subgraph streaming, future run scheduling, and a richer Checkpoint type.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.31 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.31
└──▷ USE ITPin a specific assistant version to active after testing a new prompt configuration in staging.await client.assistants.set_latest(assistant_id="asst_abc123", version=3)
Audit all deployed versions of an assistant to understand what changed between releases.versions = await client.assistants.get_versions(assistant_id="asst_abc123") for v in versions: print(v.version, v.config)Schedule a background run to execute 60 seconds in the future, e.g. for deferred processing after an external webhook.await client.runs.create(thread_id="thread_xyz", assistant_id="asst_abc123", after_seconds=60)
- ›Adds
nameparameter to assistantcreateandupdatemethods for human-readable assistant identification. - ›Adds
get_versionsmethod to retrieve the full version history of an assistant. - ›Adds
set_latestmethod to promote a specific assistant version to active. - ›Adds
subgraphsparameter toget_stateto include subgraph state in thread state responses. - ›Adds
stream_subgraphsparameter to run methods to stream outputs from subgraphs.
+3 moreshow less
- ›Adds
after_secondsparameter to schedule runs for future execution. - ›Introduces new Checkpoint type for richer checkpoint representation across thread and run APIs.
- ›Adds
AssistantVersionclass andThreadTaskmodel to the schema for version history and per-thread task tracking.
└──▷ BREAKING ON UPGRADE- !The
patch_statemethod has been removed from the Thread client in favor of updated state management viaupdate_state. - !The
configfield in thread state responses has been replaced bycheckpoint(using the new Checkpoint type). - !The
checkpoint_idparameter is deprecated inget_stateand run methods; the replacement is the newcheckpointparameter.
- ›Adds
- 0.2.24
LangGraph 0.2.24 adds a new
langgraph.typesmodule and error detection for multiple subgraphs inside a single node.└──▷ GET THIS VERSION$ git clone --branch 0.2.24 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.24
└──▷ USE ITImport Send and Interrupt from the new canonical module instead ofconstantsin new code.from langgraph.types import Send, Interrupt
- ›Introduces
langgraph.typesmodule as the new canonical home for core data types including Send and Interrupt. - ›Adds
MultipleSubgraphsErrorto detect and prevent multiple subgraphs from being invoked inside the same node.
- ›Introduces
- 0.2.23
LangGraph 0.2.23 adds token-by-token message streaming and custom node output streaming via two new stream modes.
└──▷ GET THIS VERSION$ git clone --branch 0.2.23 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.23
└──▷ USE ITSurface LLM tokens as they are generated so a UI can display streamed responses without waiting for the full reply.for chunk in graph.stream(inputs, stream_mode="messages"): print(chunk)Emit structured intermediate results from a node (e.g. progress updates) that consumers can act on before the graph finishes.# Inside a node definition: def my_node(state, *, write): write({"status": "halfway done"}) return state # Consuming the stream: for chunk in graph.stream(inputs, stream_mode="custom"): print(chunk)- ›Adds
stream_mode="messages"to stream LLM output token-by-token in real time. - ›Adds
stream_mode="custom"to emit arbitrary output from nodes via awriteparameter. - ›Enhances
chat_agent_executorwithroute_tool_responsesto support tools configured withreturn_direct, bypassing the agent on return. - ›Introduces
AsyncQueueandSyncQueueutilities for higher-performance concurrent streaming.
└──▷ BREAKING ON UPGRADE- !In
chat_agent_executor,should_continuenow returns"tools"instead of"continue"and"__end__"instead of"end"— code that matches on those string values will break.
- ›Adds
- checkpoint==1.0.10
LangGraph checkpoint 1.0.10 adds MessagePack serialization, scheduled-task tracking, and namedtuple support.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.10
- ›Adds MessagePack integration to
JsonPlusSerializeras a faster alternative to JSON serialization, with pooled encoders for throughput. - ›Adds a
SCHEDULEDspecial channel constant (value-2) inWRITES_IDX_MAPonBaseCheckpointSaverto track scheduled task status in the checkpoint system. - ›Adds
get_next_versionmethod toInMemorySaverto generate consistent, unique version identifiers for channels. - ›Extends
JsonPlusSerializerto serialize objects exposing _asdict() (e.g., namedtuples).
- ›Adds MessagePack integration to
- checkpointpostgres==1.0.7
LangGraph Postgres checkpointer gains custom serializer support and smarter SQL write strategies in v1.0.7
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.7
└──▷ USE ITPlug in a custom serializer when opening an async Postgres checkpoint connection — useful when your graph state contains types the default serializer can't handle.from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver from my_project.serializers import MyCustomSerde async with AsyncPostgresSaver.from_conn_string( "postgresql://user:pass@localhost/mydb", serde=MyCustomSerde(), ) as saver: await saver.setup() # attach saver to your compiled graph graph = workflow.compile(checkpointer=saver)- ›Adds optional
serdeparameter to AsyncPostgresSaver.from_conn_string() for injecting custom serializers. - ›Introduces dynamic SQL query selection for checkpoint writes, choosing between upsert and insert-only operations based on channel types in both
PostgresSaverandAsyncPostgresSaver. - ›Adds new
INSERT_CHECKPOINT_WRITES_SQLconstant enabling insert-only checkpoint write operations alongside the existing upsert path.
- ›Adds optional
- 0.2.22
LangGraph 0.2.22 adds
create_modelPydantic utility and improved subgraph retry resumption.└──▷ GET THIS VERSION$ git clone --branch 0.2.22 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.22
└──▷ USE ITUsecreate_modelto build a Pydantic state schema that works across langchain-core versions when defining aStateGraph.from langgraph.utils.pydantic import create_model from langgraph.graph import StateGraph MyState = create_model('MyState', messages=(list, []), step=(int, 0)) graph = StateGraph(state_schema=MyState)- ›Adds
langgraph.utils.pydantic.create_model, a new utility function that creates Pydantic models compatible with both older and newer versions of langchain-core, supporting normal field definitions and root models through a consistent interface. - ›Adds a deprecation warning when
StateGraphis initialized without an explicitstate_schemaparameter, prompting users to supply one explicitly.
- ›Adds
- 0.2.20
LangGraph 0.2.20 adds dataclass schema support, ToolNode naming, and reduced dependency on langchain-core for config handling.
└──▷ GET THIS VERSION$ git clone --branch 0.2.20 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.20
└──▷ USE ITUse a dataclass as a StateGraph schema so field defaults are automatically resolved without manual annotation workarounds.from dataclasses import dataclass, field from langgraph.graph import StateGraph @dataclass class AgentState: messages: list = field(default_factory=list) step: int = 0 graph = StateGraph(AgentState)Identify a ToolNode by name when inspecting or logging graph structure.from langgraph.prebuilt import ToolNode node = ToolNode(tools=[my_tool]) print(node.name) # "ToolNode"
- ›Adds dataclass support in
get_field_default, enabling field defaults (including default factories) to be retrieved from dataclass-based state schemas. - ›Adds a
nameattribute (default"ToolNode") toToolNodefor better graph node identification. - ›Adds local
ensure_config,get_callback_manager_for_config, andget_async_callback_manager_for_configinlanggraph.utils.config, removing the dependency onlangchain-corefor config handling. - ›Adds
__slots__toBaseChanneland all channel subclasses, reducing per-instance memory overhead at scale.
└──▷ BREAKING ON UPGRADE- !The
from_checkpointAPI on all channel classes now returns instances directly instead of using a context manager pattern — code that usedwith channel.from_checkpoint(...) as ch:will break.
- ›Adds dataclass support in
- 0.2.19
LangGraph 0.2.19 adds Pydantic BaseModel support to ToolNode and improves async/sync runner responsiveness.
└──▷ GET THIS VERSION$ git clone --branch 0.2.19 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.19
└──▷ USE ITUse a Pydantic model as your graph state so ToolNode can extract typed fields directly — no dict conversion needed.from pydantic import BaseModel from langgraph.prebuilt import ToolNode from langchain_core.tools import tool class AgentState(BaseModel): messages: list user_id: str @tool def lookup_user(user_id: str) -> str: """Look up a user by ID.""" return f"User: {user_id}" node = ToolNode([lookup_user]) # AgentState instance is now passed directly — ToolNode reads fields via getattr result = node.invoke(AgentState(messages=[...], user_id="u-123"))- ›Supports Pydantic
BaseModelas an input type inToolNode, alongside existing list and dict inputs, for stronger type safety in tool-calling graphs. - ›Enables
ToolNodeto detect nested tool injections inside Union and Annotated types. - ›Improves
ToolNodestate extraction to work with object attributes viagetattr, enabling object-like states alongside dictionaries. - ›Yields control back to the caller immediately at the start of
PregelRunner.tickandatick, improving responsiveness in async and sync applications.
- ›Supports Pydantic
- 0.2.18
LangGraph 0.2.18 adds scheduled-task tracking, a TaskNotFound exception, and a Pregel.copy() method for cleaner graph customization.
└──▷ GET THIS VERSION$ git clone --branch 0.2.18 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.18
└──▷ USE ITCatch the new TaskNotFound exception when manually driving task execution to handle missing-task edge cases gracefully.from langgraph.errors import TaskNotFound try: result = await pregel_loop.execute_task(task_id) except TaskNotFound: print(f"Task {task_id} no longer exists in the execution graph")- ›Adds
SCHEDULEDconstant ("__scheduled__") to represent scheduled tasks, included in theRESERVEDset of special keys. - ›Introduces
TaskNotFoundexception for explicit error handling when the executor cannot locate a task. - ›Adds Pregel.copy(update) method to create modified Pregel instances without mutating the original graph.
- ›Adds
path: tuple[str, ...]field toPregelExecutableTaskto track a task's execution path through the graph. - ›Adds
scheduled: boolfield toPregelExecutableTaskto indicate whether a task has been scheduled.
+1 moreshow less
- ›Changes
prepare_next_tasksto return adict[str, PregelExecutableTask]keyed by task ID, enabling O(1) task lookup in execution loops.
└──▷ BREAKING ON UPGRADE- !The
tasksattribute ofPregelLoopchanged fromSequence[PregelExecutableTask]todict[str, PregelExecutableTask]; code that iterates or indexestasksas a list will break. - !
prepare_next_tasksnow returns adict[str, PregelExecutableTask]instead of a list; callers that treat the return value as a sequence will break.
- ›Adds
- 0.2.17
LangGraph 0.2.17 adds Pydantic v2 support, a new
get_field_defaultutility, and a newSUBSCRIPTIONSconstant for channel management.└──▷ GET THIS VERSION$ git clone --branch 0.2.17 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.17
└──▷ USE ITInspect the default value for a field in a state schema, e.g. to check whether an optional field has a factory default before graph compilation.from langgraph.utils.fields import get_field_default from typing import Optional from pydantic import BaseModel class MyState(BaseModel): messages: list = [] user_id: Optional[str] = None default = get_field_default(MyState.model_fields["messages"]) print(default) # []- ›Adds Pydantic v2 support across the library while maintaining Pydantic v1 compatibility, including in
ValidationNodewhich now selects the correct validation method (model_validate/model_dump_jsonfor v2,validate/jsonfor v1) automatically. - ›Adds new
get_field_defaultutility inlanggraph.utils.fieldsfor reliably resolving default values for state schema fields, with improved handling of optional fields, Required/NotRequiredannotations, and type hints. - ›Adds new
SUBSCRIPTIONSconstant tolanggraph.constants, included in theRESERVEDset for channel management. - ›Expands
langchain-coredependency range to allow versions up to v0.4.x.
- ›Adds Pydantic v2 support across the library while maintaining Pydantic v1 compatibility, including in
- checkpointpostgres==1.0.6
AsyncPostgresSaver gains synchronous wrapper methods for use in mixed sync/async contexts.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.6
└──▷ USE ITUse AsyncPostgresSaver from a synchronous function — e.g. inside a Django view or a sync test — without spinning up a separate async runtime.from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver async def setup(): saver = await AsyncPostgresSaver.from_conn_string("postgresql://user:pass@localhost/db") return saver # In a synchronous context: import asyncio saver = asyncio.run(setup()) # Now call sync wrappers directly from sync code: checkpoint_tuple = saver.get_tuple(config) all_checkpoints = list(saver.list(config)) saver.put(config, checkpoint, metadata, new_versions)- ›Adds synchronous list(), get_tuple(), put(), and put_writes() methods to
AsyncPostgresSaver, backed by asyncio.run_coroutine_threadsafe(), enabling use from synchronous code without restructuring the async saver. - ›Stores the running event loop on
AsyncPostgresSaverinstances viaself.loopto support the new synchronous dispatch methods.
- ›Adds synchronous list(), get_tuple(), put(), and put_writes() methods to
- checkpointsqlite==1.0.2
AsyncSqliteSaver gains synchronous get_tuple, list, put, and put_writes methods for mixed async/sync use.
└──▷ GET THIS VERSION$ git clone --branch checkpointsqlite==1.0.2 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointsqlite==1.0.2
└──▷ USE ITCall AsyncSqliteSaver synchronously from a non-async context — useful when integrating with sync frameworks or threads that share an async event loop.from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver saver = AsyncSqliteSaver.from_conn_string("checkpoints.db") # Synchronous put now works without wrapping in asyncio.run() saver.put(config, checkpoint, metadata, new_versions) # Synchronous put_writes also available saver.put_writes(config, writes, task_id)- ›Adds synchronous
get_tuple,list, andputmethods toAsyncSqliteSaver, running async equivalents viaasyncio.run_coroutine_threadsafefor mixed-context use. - ›Adds new synchronous
put_writesmethod toAsyncSqliteSaver.
- ›Adds synchronous
- 0.2.16
LangGraph 0.2.16 improves nested subgraph detection for accurate visualization of complex graph structures.
└──▷ GET THIS VERSION$ git clone --branch 0.2.16 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.16
- ›Enhances
get_graphwith pre-computed subgraph resolution when using thexrayparameter, enabling accurate visualization of complex nested graph structures. - ›Expands
get_subgraphsto discover nested Pregel instances insideRunnableSequencesteps,RunnableLambdadependencies, andRunnableCallablefunction nonlocals.
- ›Enhances
- 0.2.15
create_react_agent now accepts a ToolNode instance directly, enabling reuse of tool configurations across agents.
└──▷ GET THIS VERSION$ git clone --branch 0.2.15 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.15
└──▷ USE ITReuse a pre-configured ToolNode across two agents to share tool setup (e.g., auth, retries) without duplicating it.from langgraph.prebuilt import ToolNode, create_react_agent shared_tool_node = ToolNode([search_tool, calculator_tool]) agent_a = create_react_agent(model_a, shared_tool_node) agent_b = create_react_agent(model_b, shared_tool_node)
Wire a StateGraph node directly to END without a prior add_node(END) call, reducing boilerplate in graph definitions.from langgraph.graph import StateGraph, END builder = StateGraph(MyState) builder.add_node("analyze", analyze_fn) builder.add_edge("analyze", END) # No explicit add_node(END) needed graph = builder.compile()- ›Enables passing a
ToolNodeinstance directly tocreate_react_agent, so existing tool configurations can be reused across multiple agents without duplication. - ›Supports connecting
StateGraphedges directly to theENDnode without explicitly adding it first, making graph construction more concise.
- ›Enables passing a
- sdk==0.1.30
LangGraph SDK 0.1.30 adds state-value filtering for thread search and makes runs.join() return final thread state.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.30 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.30
└──▷ USE ITFilter threads to only those whose state contains a specific value — useful for finding active conversations in a given topic or stage.threads = await client.threads.search(values={"topic": "billing", "status": "open"})Block until a run completes and immediately inspect the final thread state without a separate fetch call.final_state = await client.runs.join(thread_id, run_id) print(final_state)
- ›Adds
valuesparameter to client.threads.search() for filtering threads by their state values. - ›Changes client.runs.join() to return a dictionary containing the final thread state instead of None.
- ›Introduces Json type as a replacement for the Metadata type to better reflect its semantic purpose.
└──▷ BREAKING ON UPGRADE- !The Metadata type is renamed to Json; code importing or referencing Metadata will break.
- !client.runs.join() now returns a dictionary containing the final thread state instead of None; code that assumes a None return value will break.
- ›Adds
- checkpoint==1.0.7
LangGraph Checkpoint 1.0.7 adds parent checkpoint references and pending-send tracking across checkpoint operations.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.7
- ›Adds
parentsfield toCheckpointMetadata, mapping checkpoint namespace to checkpoint ID for relationship tracking between checkpoints. - ›Adds pending-send tracking in
InMemorySaver:get_tuplenow includespending_sendsfrom parent checkpoints, andlistgains improved namespace filtering.
└──▷ BREAKING ON UPGRADE- !The
scorefield inCheckpointMetadatais replaced by theparentsfield — any code reading or writingscorewill break.
- ›Adds
- cli==0.1.52
LangGraph CLI 0.1.52 adds Node.js/LangGraphJS deployment support with dedicated Docker configuration.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.52 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.52
└──▷ USE ITConfigure a LangGraphJS project for deployment by specifying the Node.js version in your langgraph config file.{ "node_version": "20", "graphs": { "my_graph": "./src/graph.ts:graph" } }- ›Adds
node_versionfield to the LangGraph config TypedDict, enabling Node.js (LangGraphJS) project deployments alongside existing Python support. - ›Adds
node_config_to_dockerfunction to generate Docker configurations for Node.js projects, automatically selecting thelangchain/langgraphjs-apibase image. - ›Adds validation for the
node_versionconfig field (currently enforces version"20") to catch misconfigured Node.js projects early. - ›Updates
build,prepare, and deployment CLI commands to operate correctly against both Python and Node.js environments.
- ›Adds
- checkpointpostgres==1.0.4
LangGraph Postgres checkpointer now accepts connection pools for high-concurrency deployments.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.4
└──▷ USE ITUse a connection pool with PostgresSaver to handle many concurrent LangGraph checkpoints without exhausting database connections.from psycopg_pool import ConnectionPool from langgraph.checkpoint.postgres import PostgresSaver pool = ConnectionPool("postgresql://user:password@localhost/db", min_size=2, max_size=10) saver = PostgresSaver(pool)Use an async connection pool with AsyncPostgresSaver for high-concurrency async LangGraph applications.from psycopg_pool import AsyncConnectionPool from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver pool = AsyncConnectionPool("postgresql://user:password@localhost/db", min_size=2, max_size=10) saver = AsyncPostgresSaver(pool)- ›Adds
ConnectionPoolsupport toPostgresSaver, enabling psycopg connection pool usage alongside direct connections for high-concurrency scenarios. - ›Adds
AsyncConnectionPoolsupport toAsyncPostgresSaverfor async workflows requiring pooled database connections. - ›Enhances list() and alist() methods to include pending writes in returned checkpoint tuples.
- ›Adds
- sdk==0.1.29
LangGraph SDK 0.1.29 adds disconnect/completion lifecycle controls and a new join_stream() method for live run output.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.29 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.29
└──▷ USE ITAttach to an in-progress run mid-flight to tail its output in real time — useful when a run was started in the background and you want to surface results to a user later.async for chunk in client.runs.join_stream(thread_id, run_id): print(chunk)Start a streaming run that auto-cancels if the user closes the connection, and deletes resources once it completes — keeps infra clean in high-volume deployments.async for chunk in client.runs.stream( thread_id, assistant_id, input=input_data, on_disconnect="cancel", on_completion="delete", ): print(chunk)Create a background run that retains its output after completion so you can inspect results later.run = await client.runs.create( thread_id, assistant_id, input=input_data, on_completion="keep", )- ›Adds
on_disconnectparameter to stream() and wait() — set to"cancel"or"continue"to control what happens to a run when the client disconnects. - ›Adds
on_completionparameter to stream(), create(), and wait() — set to"delete"or"keep"to control resource cleanup after a run finishes. - ›Adds join_stream() method to attach to an already-running run and receive its real-time output without buffering prior output.
- ›Adds
DisconnectModeandOnCompletionBehaviortypes for structured lifecycle control in typed clients.
- ›Adds
- 0.2.13
LangGraph 0.2.13 adds runtime-only managed values and reimplements Context to skip unnecessary serialization.
└──▷ GET THIS VERSION$ git clone --branch 0.2.13 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.13
└──▷ USE ITDeclare a runtime-only managed value to inject a context manager into your graph without it being serialized to checkpoints.from langgraph.managed.base import ManagedValue class MyRuntimeValue(ManagedValue, runtime=True): ...- ›Adds a
runtimeflag toManagedValuethat marks values as created at runtime and excluded from serialization/deserialization. - ›Adds
replace_runtime_valuesandreplace_runtime_placeholdersmethods toManagedValueMappingfor safe handling of runtime placeholders during graph serialization. - ›Reimplements Context as a managed value (
langgraph.managed.context.ContextManagedValue) withruntime=True, integrating it with the managed value system instead of the channel system.
- ›Adds a
- cli==0.1.51
LangGraph CLI 0.1.51 adds Redis 6 to Docker Compose for caching and message queuing.
└──▷ GET THIS VERSION$ git clone --branch cli==0.1.51 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.51
- ›Adds Redis 6 as a managed Docker Compose service with health-check gating, so langgraph-api only starts after Redis is healthy.
- ›Injects
REDIS_URIenvironment variable (redis://langgraph-redis:6379) automatically into the langgraph-api service.
- checkpoint==1.0.4
LangGraph Checkpoint 1.0.4 adds error-write support, an ERROR constant, and exception serialization in JsonPlusSerializer.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.4 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.4
└──▷ USE ITCapture and persist a node error into a checkpoint write so downstream nodes or retry logic can inspect it.from langgraph.checkpoint.serde.types import ERROR # In a custom checkpointer's put_writes, tag a failed write with the ERROR sentinel writes = [(ERROR, exception_value)] await checkpointer.put_writes(config, writes, task_id)
- ›Adds
ERROR = "__error__"constant inlanggraph.checkpoint.serde.typesto represent error types in checkpoint writes. - ›Supports special write types including error handling via
WRITES_IDX_MAPinInMemorySaver.put_writes. - ›Enables
JsonPlusSerializerto serializeBaseExceptionobjects by encoding them using their constructor arguments. - ›Includes pending writes in checkpoint list output from
InMemorySaver.
└──▷ BREAKING ON UPGRADE- !The
current_tasksfield is removed from the Checkpoint TypedDict; any code reading or writingcheckpoint["current_tasks"]will break. - !
empty_checkpoint,copy_checkpoint, andcreate_checkpointno longer includecurrent_tasksin their returned dictionaries.
- ›Adds
- 0.2.10
LangGraph 0.2.10 adds error and interrupt fields to debug task result payloads for richer execution tracing.
└──▷ GET THIS VERSION$ git clone --branch 0.2.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.10
└──▷ USE ITInspect task-level errors and interrupts during a graph run by reading the enriched debug stream.for chunk in graph.stream(inputs, stream_mode="debug"): if chunk["type"] == "task_result": payload = chunk["payload"] if payload["error"]: print("Task error:", payload["error"]) if payload["interrupts"]: print("Interrupts:", payload["interrupts"])- ›Adds
error: Optional[str]andinterrupts: list[dict]fields toTaskResultPayloadfor capturing task-level errors and interrupts in debug output. - ›Enhances
put_writesonPregelLoopto automatically stream updates and debug information without manual wiring. - ›Adds
stream_keysas a class attribute onPregelLoopfor explicit management of streaming outputs. - ›Updates
map_debug_task_resultsto accept task-writes pairs and support both string and sequence stream key formats.
└──▷ BREAKING ON UPGRADE- !The
map_debug_task_resultsfunction signature now accepts task-writes pairs instead of just tasks — callers passing tasks alone will break. - !The
tickmethod onPregelLoophas had parameters removed — code passing those now-removed parameters will break. - !The
SyncPregelLoopandAsyncPregelLoopconstructor signatures have changed to support the new streaming architecture — existing instantiation code may break. - !
map_output_updatesnow expects the new task-writes tuple format — callers using the old format will break. - !ERROR and INTERRUPT keys are now filtered out of regular output streams by
map_output_updates— code relying on seeing those keys in regular output will no longer receive them.
- ›Adds
- sdk==0.1.28
LangGraph SDK 0.1.28 adds custom HTTP headers support and checkpoint namespace field for state configs.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.28 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.28
└──▷ USE ITAttach a tenant ID or trace header to every SDK request when operating in a multi-tenant or instrumented environment.from langgraph_sdk import get_client client = get_client( url="https://your-langgraph-endpoint", headers={"x-tenant-id": "acme-corp", "x-trace-id": "abc123"}, )Retrieve a checkpoint scoped to a specific namespace to isolate state across parallel graph executions.state = await client.threads.get_state( thread_id="<thread_id>", checkpoint_id="<checkpoint_id>", checkpoint_ns="pipeline-a", )- ›Adds a
headersparameter toget_clientfor injecting custom HTTP headers into all API requests, with validation blocking reserved headers likex-api-key. - ›Adds a
checkpoint_nsfield to state configurations inget_stateandcreatefor namespace-scoped checkpoint lookups.
└──▷ BREAKING ON UPGRADE- !The
thread_tsfield is renamed tocheckpoint_idin state configurations forLangGraphClient.get_stateandLangGraphClient.create— any code referencingthread_tswill break.
- ›Adds a
- 0.2.7
LangGraph 0.2.7 adds SharedValue and a pluggable store system for persisting state across graph nodes.
└──▷ GET THIS VERSION$ git clone --branch 0.2.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.7
└──▷ USE ITPersist shared state across nodes in a compiled graph using the built-in in-memory store.from langgraph.graph.state import StateGraph from langgraph.managed.shared_value import SharedValue from langgraph.store.memory import MemoryStore store = MemoryStore() graph = StateGraph(...) # SharedValue field is accessible and writable by all nodes graph.add_node("node_a", node_a_fn) graph.add_node("node_b", node_b_fn) app = graph.compile(store=store)Batch async store operations to reduce round-trips when many nodes read/write shared state concurrently.from langgraph.store.memory import MemoryStore from langgraph.store.batch import AsyncBatchedStore batched_store = AsyncBatchedStore(MemoryStore()) app = graph.compile(store=batched_store)
Check at runtime whether a managed value can be mutated before attempting an update.from langgraph.managed.base import is_writable_managed_value, is_readonly_managed_value if is_writable_managed_value(my_value): await my_value.aupdate(new_data) elif is_readonly_managed_value(my_value): print("This value cannot be updated")- ›New
SharedValueclass enables shared, writable state across graph nodes with optional scoping by configuration. - ›New
WritableManagedValueabstract class extends the managed values system with update() and aupdate() methods for sync/async mutations. - ›New
storeparameter on StateGraph.compile() wires a persistent storage backend into the graph. - ›New
BaseStoreabstract class defines a standard interface (list/update, sync and async) for pluggable storage engines. - ›New
MemoryStoreprovides a ready-to-use in-memory implementation ofBaseStore.
+3 moreshow less
- ›New
AsyncBatchedStorewraps anyBaseStoreto batch async operations for higher-throughput workloads. - ›New utility functions
is_readonly_managed_valueandis_writable_managed_valueallow runtime inspection of managed value types. - ›New
ChannelKeyPlaceholderandChannelTypePlaceholderobjects support dynamic injection of channel key and type metadata.
- ›New
- 0.2.6
LangGraph 0.2.6 adds structured graph interrupts with timing context and a new NodeInterrupt exception for in-node signaling.
└──▷ GET THIS VERSION$ git clone --branch 0.2.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.6
└──▷ USE ITPause a node mid-execution (e.g., to await human approval) and surface structured timing context to the caller.from langgraph.errors import NodeInterrupt def review_node(state): if state["needs_approval"]: raise NodeInterrupt("Waiting for human approval before proceeding") return stateInspect which interrupts fired and when after catching a GraphInterrupt to decide how to resume.from langgraph.errors import GraphInterrupt try: result = graph.invoke(inputs) except GraphInterrupt as e: for interrupt in e.interrupts: print(f"Interrupted {interrupt.when}: {interrupt.value}")- ›New Interrupt dataclass captures structured interruption events with a
whenfield ("before","during","after") and an optionalvalue. - ›New
NodeInterruptexception lets node logic explicitly signal a mid-execution interrupt without raising a generic error. - ›Enhanced
GraphInterruptnow stores a list of Interrupt objects, giving full context on when and how many interrupts occurred. - ›Adds
interruptsfield toPregelTaskfor per-task interrupt visibility useful in debugging and flow control. - ›Adds
CONFIG_KEY_TASK_IDconstant to track task identifiers through the configuration system.
+1 moreshow less
- ›
should_interruptnow returns the list of executable tasks to be interrupted instead of a boolean, enabling precise per-task interrupt control.
└──▷ BREAKING ON UPGRADE- !
langgraph.pregel.algo.should_interruptreturn type changed fromboolto a list of executable tasks — any code that checks the return value as a boolean will behave incorrectly.
- ›New Interrupt dataclass captures structured interruption events with a
- 0.2.5
LangGraph 0.2.5 adds task-level error tracking in state snapshots and a new ERROR constant for consistent failure visibility.
└──▷ GET THIS VERSION$ git clone --branch 0.2.5 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.5
└──▷ USE ITInspect task-level errors after a graph run to understand which node failed and why.snapshot = await graph.aget_state(config) for task in snapshot.tasks: if task.error is not None: print(f"Task {task.id} failed with: {task.error}")- ›Adds
ERROR = "__error__"constant (reserved key) for consistent error tracking and propagation across graph execution. - ›Enhances
StateSnapshotwith a newtasksfield that surfaces task-level error details in state history. - ›Introduces enhanced
PregelTaskclass withidand optionalerrorfields to uniquely identify tasks and capture exceptions. - ›Adds
tasks_w_writesdebug function to associate tasks with their writes and any errors for richer checkpoint debug output. - ›Extends
get_state/aget_stateon Pregel to include proper step numbers and task error information in returned snapshots.
└──▷ BREAKING ON UPGRADE- !The
__call__method ofManagedValuehas its signature changed from __call__(self, step: int, task: PregelTaskDescription) to __call__(self, step: int) — any customManagedValuesubclass that accepts ataskparameter will break. - !The
__call__method ofIsLastStepManagerhas its signature changed from __call__(self, step: int, task: PregelExecutableTask) to __call__(self, step: int) — any code calling this with ataskargument will break. - !
PregelTaskDescriptionis replaced by the newPregelTaskclass — code that references or type-hintsPregelTaskDescriptiondirectly will break.
- ›Adds
- checkpoint==1.0.3
JsonPlusSerializer gains native support for pathlib, regex, decimal, deque, IP address, and time types.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.3 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.3
- ›Supports serialization of
pathlib.Path,re.Pattern,decimal.Decimal,deque, IPv4/IPv6 address types,date,time, andZoneInfoinJsonPlusSerializer. - ›Deserialization now returns None gracefully when a module or attribute is missing, instead of raising an exception.
- ›Supports serialization of
- checkpointpostgres==1.0.1
LangGraph PostgreSQL checkpointer gains versioned schema migrations and JSON+Plus metadata serialization.
└──▷ GET THIS VERSION$ git clone --branch checkpointpostgres==1.0.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpointpostgres==1.0.1
└──▷ USE ITRun versioned schema migrations on an existing PostgreSQL checkpoint database so it stays in sync after upgrading.from langgraph.checkpoint.postgres import PostgresSaver with PostgresSaver.from_conn_string("postgresql://user:pass@localhost/db") as saver: saver.setup() # applies all pending MIGRATIONS instead of recreating tablesUse the async saver with the same versioned migration support in an async workflow.from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver async with AsyncPostgresSaver.from_conn_string("postgresql://user:pass@localhost/db") as saver: await saver.setup() # applies MIGRATIONS for the async variant- ›Adds versioned database migrations (
MIGRATIONSlist) for bothPostgresSaverandAsyncPostgresSaver, replacing one-shot static table creation. - ›Introduces
JsonPlusSerializer-backed_load_metadataand_dump_metadatamethods for consistent, richer metadata serialization across sync and async savers.
└──▷ BREAKING ON UPGRADE- !The
is_setupflag has been removed fromPostgresSaverandAsyncPostgresSaverin favor of the new versioned setup method; any code that reads or setsis_setupwill break.
- ›Adds versioned database migrations (
- 0.2.0
LangGraph 0.2 ships dedicated checkpointer libraries for SQLite and Postgres, including the previously cloud-only PostgresSaver.
└──▷ GET THIS VERSION$ git clone --branch 0.2.0 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.2.0
└──▷ USE ITUse the SQLite checkpointer for local development with persistent state across runs without standing up a database server.from langgraph.checkpoint.sqlite import SqliteSaver with SqliteSaver.from_conn_string("./local_state.db") as checkpointer: graph = app.compile(checkpointer=checkpointer) result = graph.invoke( {"messages": ["Hello"]}, config={"configurable": {"thread_id": "dev-session-1"}} )- ›New
langgraph-checkpointpackage exposesBaseCheckpointSaver,SerializationProtocol, andMemorySaveras a standalone base library. - ›New
langgraph-checkpoint-sqlitepackage providesSqliteSaver/AsyncSqliteSaverfor local and experimental workflows. - ›New
langgraph-checkpoint-postgrespackage open-sources the production-gradePostgresSaverpreviously available only in LangGraph Cloud. - ›New
new_versionsparameter inBaseCheckpointSaver.putenables further optimization of custom checkpointer implementations. - ›Graph stream output now includes outputs from all nodes, including nodes that return no state writes (previously silent nodes were omitted).
└──▷ BREAKING ON UPGRADE- !
thread_tsandparent_tsare renamed tocheckpoint_idandparent_checkpoint_idrespectively (vialanggraph_checkpoint==1.0.0). - !Re-exported imports like
from langgraph.checkpoint import BaseCheckpointSaverno longer work; usefrom langgraph.checkpoint.base import BaseCheckpointSaverinstead. - !SQLite checkpointers have been moved to a separate library —
pip install langgraph-checkpoint-sqliteis now required to use them. - !The
.from_conn_stringmethod ofSqliteSaver/AsyncSqliteSaveris now a context manager. - !Graph stream output now emits
{'node_1': None}for nodes that return no state writes, changing the shape of streamed output for graphs with such nodes.
- ›New
- checkpoint==1.0.1
LangGraph checkpoint 1.0.1 adds binary serialization, channel-version API, and context-manager support for MemorySaver.
└──▷ GET THIS VERSION$ git clone --branch checkpoint==1.0.1 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout checkpoint==1.0.1
└──▷ USE ITUse MemorySaver as a context manager to ensure clean resource teardown in tests or short-lived scripts.from langgraph.checkpoint.memory import MemorySaver with MemorySaver() as saver: # saver is fully initialised; resources released on exit checkpoints = list(saver.list(config))Persist raw binary blobs (e.g. embeddings or serialised models) directly in checkpoint state — now round-trippable through JsonPlusSerializer.from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer serde = JsonPlusSerializer() type_tag, encoded = serde.dumps_typed(b"\x89PNG\r\n") restored = serde.loads_typed((type_tag, encoded)) assert isinstance(restored, bytes)
- ›Adds
bytesandbytearrayserialization support toJsonPlusSerializer, enabling binary data in checkpointed state. - ›Introduces
ChannelVersionstype alias (dict[str, Union[str, int, float]]) for type-safe channel version handling. - ›Extends
BaseCheckpointSaver.putandaputwith a newnew_versions: ChannelVersionsparameter exposing channel version info at write time. - ›Implements sync and async context manager interfaces (
__enter__/__exit__/__aenter__/__aexit__) onMemorySaverfor explicit resource management.
└──▷ BREAKING ON UPGRADE- !The
putandaputmethods onBaseCheckpointSaver(andMemorySaver) now require anew_versions: ChannelVersionsparameter — any custom subclass that overrides these methods without the new parameter will break.
- ›Adds
- sdk==0.1.27
LangGraph SDK 0.1.27 adds optional URL client init, ASGI transport support, thread copy, and assistant if_exists dedup control.
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.27 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.27
└──▷ USE ITConnect to a local LangGraph server without specifying a URL — useful in dev environments where defaults are sufficient.from langgraph_sdk import get_client client = get_client() # url is now optional
Create an assistant idempotently — safe to run in setup scripts without worrying about duplicate errors.assistant = await client.assistants.create( graph_id="my_graph", config={"configurable": {"model": "gpt-4o"}}, if_exists="return_existing", )Duplicate a thread to branch off a conversation without modifying the original.new_thread = await client.threads.copy(thread_id="<thread_id>")
- ›Makes the
urlparameter optional inget_client, with intelligent defaults so local dev requires no explicit URL. - ›Adds ASGI transport support in
get_clientwith correct root path configuration. - ›Adds
if_existsparameter toAssistantsAPI.createfor controlling behavior on duplicate assistant creation. - ›Adds a new
ThreadsAPI.copymethod for duplicating existing threads. - ›Makes
GraphSchemafields (input_schema,state_schema,config_schema) optional for better TypeScript interoperability.
- ›Makes the
- 0.1.17
LangGraph 0.1.17 lets update_state() accept None values to preserve configuration without changing state.
└──▷ GET THIS VERSION$ git clone --branch 0.1.17 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.17
└──▷ USE ITPreserve checkpoint configuration between steps without overwriting any state values — useful when you need to advance step count or merge configurable fields mid-graph.graph.update_state(config, values=None)
- ›Supports None as a valid
valuesargument in Pregel.update_state(), enabling configuration-only state updates that leave channel values unchanged.
- ›Supports None as a valid
- 0.1.10
LangGraph 0.1.10 adds InjectedState for automatic graph-state injection into tools and improves parallel tool execution in ToolNode.
└──▷ GET THIS VERSION$ git clone --branch 0.1.10 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.10
└──▷ USE ITGive a tool access to the current graph state (e.g., conversation history) without asking the LLM to supply it — useful for retrieval or policy tools that need context the model shouldn't fabricate.from typing import Annotated from langgraph.prebuilt.tool_node import InjectedState from langchain_core.tools import tool class AgentState(TypedDict): messages: list user_id: str @tool def lookup_policy( topic: str, state: Annotated[AgentState, InjectedState()], ) -> str: """Look up company policy, scoped to the current user.""" user_id = state["user_id"] # injected automatically; model never sees it return fetch_policy(topic, user_id)- ›Adds
InjectedStateannotation to automatically inject graph state into tool arguments insideToolNode, so tools can access state fields without the model generating them. - ›Improves parallel execution of tools in
ToolNodeusing config lists viaget_config_listfrom langchain-core. - ›Adds
GraphInterrupterror class for structured handling of interruptions in nested graphs. - ›Adds
EmptyInputErrorerror class for clearer reporting when graphs receive empty inputs. - ›Enhances checkpoint parent-child relationship tracking and includes parent configuration data in checkpoint tuples, improving support for nested graphs.
- ›Adds
- 0.1.9
LangGraph 0.1.9 adds
state_modifiertocreate_react_agent, custom state schemas, retry policies, and new background executor classes.└──▷ GET THIS VERSION$ git clone --branch 0.1.9 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.9
└──▷ USE ITUsestate_modifierto prepend a system prompt from the full agent state, giving you access to state fields beyond just messages.from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI def modify_state(state): # state is the full graph state, not just messages return [{"role": "system", "content": "You are a helpful security analyst."}] + state["messages"] agent = create_react_agent( model=ChatOpenAI(model="gpt-4o"), tools=[...], state_modifier=modify_state, )Define a custom state schema with extra fields so the agent graph carries domain-specific context alongside messages.from typing import TypedDict, Annotated from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI import operator class MyAgentState(TypedDict): messages: Annotated[list, operator.add] user_role: str # custom field session_id: str # custom field agent = create_react_agent( model=ChatOpenAI(model="gpt-4o"), tools=[...], state_schema=MyAgentState, )- ›Adds
state_modifierparameter tocreate_react_agentfor finer control over LLM inputs, replacing the now-deprecatedmessages_modifier. - ›Adds
state_schemaparameter tocreate_react_agent, enabling custom graph state definitions beyond the defaultAgentState. - ›Adds
BackgroundExecutorandAsyncBackgroundExecutorclasses inlanggraph.pregelfor structured background task management and cancellation. - ›Adds retry policies for nodes in
StateGraph. - ›Adds custom input and output type support to
StateGraph.
+3 moreshow less
- ›Adds equality comparison (
__eq__) to all channel classes (AnyValue,LastValue, Topic, and others), enabling channel state comparisons. - ›Improves graph visualization to include type-hint hints for conditional edges and to create END nodes only when needed.
- ›Adds node-existence validation in
update_state, surfacing clear errors when a nonexistent node is targeted.
└──▷ BREAKING ON UPGRADE- !The
messages_modifierparameter ofcreate_react_agentis deprecated; migrate tostate_modifier.
- ›Adds
- cli==0.1.49
LangGraph CLI 0.1.49 adds a
dockerfilecommand to generate customized Dockerfiles for the LangGraph API server.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.49 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.49
└──▷ TRY ITGenerate a ready-to-build Dockerfile from your LangGraph config so you can version-control or customize it before pushing to a registry.$ langgraph dockerfile --config langgraph.json --output Dockerfile
- ›New
dockerfileCLI command generates a Dockerfile for the LangGraph API server, accepting a save path and configuration file for customization. - ›Docker image generation now sets
PYTHONDONTWRITEBYTECODE=1and passes--no-cache-dirto pip installs, producing smaller images.
- ›New
- sdk==0.1.26
LangGraph SDK 0.1.26 adds batch run creation, cron job scheduling, and thread conflict handling
└──▷ GET THIS VERSION$ git clone --branch sdk==0.1.26 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout sdk==0.1.26
└──▷ USE ITList all scheduled cron jobs for a specific assistant to audit or manage recurring runs.crons = await client.crons.search(assistant_id="asst-abc", limit=20, offset=0)
- ›New
RunCreateTypedDict enables structured background run creation with fields for thread_id, assistant_id, input, metadata, and run configuration options. - ›New
create_batchmethod onLangGraphClientsubmits multiple runs in a single API call for more efficient batch operations. - ›New Cron class and
searchmethod support scheduled job management, with filtering by assistant_id and thread_id and pagination. - ›New
OnConflictBehaviortype ("raise"or"do_nothing") controls what happens when a thread is created that already exists, via the newif_existsparameter onThreads.create.
- ›New
- 0.1.8
LangGraph 0.1.8 adds node-level metadata support via
add_node's newmetadataparameter and theNodeSpecclass.└──▷ GET THIS VERSION$ git clone --branch 0.1.8 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.8
└──▷ USE ITTag a node with metadata (e.g. owner or risk label) so it appears in graph visualisations and downstream tooling.graph.add_node("my_agent", my_runnable, metadata={"team": "red-team", "criticality": "high"})- ›Adds an optional
metadataparameter toGraph.add_nodeto attach arbitrary metadata to graph nodes, surfaced throughNodeSpecinstances. - ›Introduces
langgraph.graph.graph.NodeSpec, a new class that stores a runnable alongside optional metadata for a node. - ›Propagates node
metadatathroughPregelNode.__init__into the node's configuration. - ›Exposes node metadata in graph visualizations via the updated
CompiledGraph.get_graphmethod.
- ›Adds an optional
- 0.1.7
LangGraph 0.1.7 adds persistent task-write checkpointing via new
put_writes/aput_writesmethods, enabling resilient interrupted-workflow recovery.└──▷ GET THIS VERSION$ git clone --branch 0.1.7 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.7
└──▷ USE ITPersist mid-run task writes so that an interrupted graph can resume without re-executing completed tasks.from langgraph.checkpoint.sqlite import SqliteSaver checkpointer = SqliteSaver.from_conn_string('checkpoints.db') # During a custom checkpointer integration, flush task writes explicitly: checkpointer.put_writes(config, writes, task_id)- ›Adds
put_writesandaput_writesmethods toBaseCheckpointer(implemented across Memory, SQLite, andAioSQLitecheckpointers) for storing task-specific writes mid-execution. - ›Adds
pending_writesfield toCheckpointTupleto carry per-task write state that is restored when a checkpoint is reloaded. - ›Tasks with pre-loaded
pending_writesare skipped on restart, avoiding redundant re-execution when resuming interrupted workflows.
- ›Adds
- 0.1.6
LangGraph 0.1.6 adds
RemoveMessagesupport for message deletion by ID andhandle_tool_errorsparameter inToolNode.└──▷ GET THIS VERSION$ git clone --branch 0.1.6 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout 0.1.6
└──▷ USE ITDisable automatic tool-error suppression in aToolNodeso exceptions propagate directly — useful when you want strict failure semantics in CI or testing.from langgraph.prebuilt import ToolNode tool_node = ToolNode(tools=[my_tool], handle_tool_errors=False)
Prune a specific message from a running message graph by its ID — handy for trimming context or removing a malformed turn mid-conversation.from langchain_core.messages import RemoveMessage # Return a RemoveMessage from a node to delete the message with the given ID def cleanup_node(state): return {"messages": [RemoveMessage(id="msg-abc123")]}- ›Adds
handle_tool_errorsparameter (defaults to True) toToolNodeinlanggraph.prebuilt.tool_node, returning a friendly error message instead of raising an exception when a tool fails, so agents can continue the conversation after tool errors. - ›Adds support for
RemoveMessagefromlangchain-coreinlanggraph.graph.message.add_messages, enabling deletion of specific messages by ID from message graphs, with validation that raises an error if the target message ID does not exist.
- ›Adds
- cli==0.1.48
LangGraph CLI 0.1.48 adds
--debugger-base-urlto point the debugger at a custom LangGraph API URL└──▷ GET THIS VERSION$ git clone --branch cli==0.1.48 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.48
└──▷ TRY ITPoint the LangGraph debugger at a remotely accessible API URL so teammates on other machines can use the Studio UI against your local server.$ langgraph dev --debugger-base-url https://my-dev-server.example.com:8123
- ›Adds
--debugger-base-urlCLI option to specify a custom URL for the debugger to access the LangGraph API, overriding the defaulthttp://127.0.0.1:[PORT]; also setsVITE_STUDIO_LOCAL_GRAPH_URLin the debugger container when the option is used. - ›Makes Docker base image pulls verbose during build to provide better visibility into the build process.
- ›Adds
- cli==0.1.45
LangGraph CLI 0.1.45 adds a
testcommand to validate graphs locally before deploying to LangGraph Cloud.└──▷ GET THIS VERSION$ git clone --branch cli==0.1.45 https://github.com/langchain-ai/langgraph.git # already have the repo? check out this version: $ git checkout cli==0.1.45
└──▷ TRY ITValidate that your graph works with the LangGraph API server before pushing to LangGraph Cloud.$ langgraph test- ›Adds
langgraph testsubcommand to start a local test server that validates graph compatibility with the LangGraph API server before deploying to LangGraph Cloud. - ›Improves environment variable handling in
config.config_to_composeto support both string (env file) and dictionary formats, with proper quoting of values in Docker Compose configuration. - ›Enhances watch functionality in
config.config_to_composefor better dependency tracking during development.
└──▷ BREAKING ON UPGRADE- !The
langgraph-api-pathoption has been removed from CLI commands.
- ›Adds