[PR #5243] feat(langgraph): new context api (replacing config['configurable'] and config_schema) #4327

Closed
opened 2026-02-20 17:50:01 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langchain-ai/langgraph/pull/5243

State: closed
Merged: Yes


Overview

This PR introduces a new API that provides a cleaner, more type-safe way to pass runtime context to LangGraph nodes/tasks. It replaces the current pattern of using config['configurable'] and config_schema with a dedicated context parameter and wrapper Runtime object.

What's Changed

Before/After: Basic Context Usage

Before (Old Pattern)

from langchain_core.runnables import RunnableConfig

def node(state: State, config: RunnableConfig):
    user_id = config.get("configurable", {}).get("user_id")
    return {"result": f"Hello {user_id}"}

graph.invoke(input_data, config={"configurable": {"user_id": "123"}})

After (New Pattern)

from dataclasses import dataclass
from langgraph.runtime import Runtime

@dataclass
class ContextSchema:
    user_id: str

def node(state: State, runtime: Runtime[ContextSchema]):
    user_id = runtime.context.user_id
    return {"result": f"Hello {user_id}"}

graph.invoke(input_data, context={"user_id": "123"})

OR, you can use the get_runtime method:

from langgraph.runtime import get_runtime

def node(state: State):
    user_id = get_runtime(ContextSchema).context.user_id
    return {"result": f"Hello {user_id}"}
Before/After: Store and Stream Writer Access

Before (Old pattern)

from langgraph.store.base import BaseStore
from langchain_core.runnables import RunnableConfig

def update_memory(state: MessagesState, config: RunnableConfig, *, store: BaseStore):
    user_id = config.get("configurable", {}).get("user_id")
    namespace = (user_id, "memories")
    memory_id = str(uuid.uuid4())
    store.put(namespace, memory_id, {"memory": memory})

After (new pattern)

from langgraph.runtime import Runtime

def update_memory(state: MessagesState, runtime: Runtime[ContextSchema]):
    user_id = runtime.context.user_id
    namespace = (user_id, "memories")
    memory_id = str(uuid.uuid4())
    runtime.store.put(namespace, memory_id, {"memory": memory})

Key Benefits

  • Type Safety: Type checked context input to invoke / stream, plus typed access to Runtime attributes
  • Cleaner API: Direct context parameter instead of nested config['configurable']
  • Better DX: IDE autocomplete for context fields and Runtime attributes
  • Unified Runtime: Single Runtime object provides access to context, store, and stream writer, with room for expanding to streamlined config/checkpoint information in the near future.

Breaking Changes & Migration

Deprecated APIs

  • StateGraph(..., config_schema=X) -> StateGraph(..., context_schema=X)
  • Pregel.config_schemaPregel.get_context_jsonschema() - this is largely meant to be external and we don't anticipate this affecting many users

Migration Details

  • Maintains backward compatibility with existing config['configurable'] usage
  • Deprecation warnings guide users to the new API

Future Work

  • Deprecate injection pattern for store, stream_writer, maybe previous, update docs to recommend popping from runtime.
  • Support Runtime injection for tools, right now only get_runtime is supported
  • LangGraph style guide with recommended best practices

Eventually, I think we should move away from storing and popping things from config["configurable"], which can be a fully internal refactor. Though I would love to do this pre v1, it should largely be internal, so can be done afterwards. Config changes should be in a different PR than this one to keep things reasonably scoped. This PR is already pretty big. Lots of plumbing.

Related Issues

Closes #5023

**Original Pull Request:** https://github.com/langchain-ai/langgraph/pull/5243 **State:** closed **Merged:** Yes --- ## Overview This PR introduces a new API that provides a cleaner, more type-safe way to pass runtime context to LangGraph nodes/tasks. It replaces the current pattern of using `config['configurable']` and `config_schema` with a dedicated `context` parameter and wrapper `Runtime` object. ## What's Changed ### Before/After: Basic Context Usage ### Before (Old Pattern) ```python from langchain_core.runnables import RunnableConfig def node(state: State, config: RunnableConfig): user_id = config.get("configurable", {}).get("user_id") return {"result": f"Hello {user_id}"} graph.invoke(input_data, config={"configurable": {"user_id": "123"}}) ``` ### After (New Pattern) ```python from dataclasses import dataclass from langgraph.runtime import Runtime @dataclass class ContextSchema: user_id: str def node(state: State, runtime: Runtime[ContextSchema]): user_id = runtime.context.user_id return {"result": f"Hello {user_id}"} graph.invoke(input_data, context={"user_id": "123"}) ``` OR, you can use the `get_runtime` method: ```python from langgraph.runtime import get_runtime def node(state: State): user_id = get_runtime(ContextSchema).context.user_id return {"result": f"Hello {user_id}"} ``` <details> <summary>Before/After: Store and Stream Writer Access</summary> ### Before (Old pattern) ```py from langgraph.store.base import BaseStore from langchain_core.runnables import RunnableConfig def update_memory(state: MessagesState, config: RunnableConfig, *, store: BaseStore): user_id = config.get("configurable", {}).get("user_id") namespace = (user_id, "memories") memory_id = str(uuid.uuid4()) store.put(namespace, memory_id, {"memory": memory}) ``` ### After (new pattern) ```py from langgraph.runtime import Runtime def update_memory(state: MessagesState, runtime: Runtime[ContextSchema]): user_id = runtime.context.user_id namespace = (user_id, "memories") memory_id = str(uuid.uuid4()) runtime.store.put(namespace, memory_id, {"memory": memory}) ``` </details> ## Key Benefits - **Type Safety**: Type checked `context` input to `invoke` / `stream`, plus typed access to `Runtime` attributes - **Cleaner API**: Direct `context` parameter instead of nested `config['configurable']` - **Better DX**: IDE autocomplete for context fields and `Runtime` attributes - **Unified Runtime**: Single `Runtime` object provides access to context, store, and stream writer, with room for expanding to streamlined config/checkpoint information in the near future. ## Breaking Changes & Migration ### Deprecated APIs - `StateGraph(..., config_schema=X)` -> `StateGraph(..., context_schema=X)` - `Pregel.config_schema` → `Pregel.get_context_jsonschema()` - this is largely meant to be external and we don't anticipate this affecting many users ### Migration Details - Maintains backward compatibility with existing `config['configurable']` usage - Deprecation warnings guide users to the new API ## Future Work - [ ] Deprecate injection pattern for `store`, `stream_writer`, maybe `previous`, update docs to recommend popping from runtime. - [ ] Support `Runtime` injection for tools, right now only `get_runtime` is supported - [ ] LangGraph style guide with recommended best practices Eventually, I think we should move away from storing and popping things from `config["configurable"]`, which can be a fully internal refactor. Though I would love to do this pre v1, it should largely be internal, so can be done afterwards. Config changes should be in a different PR than this one to keep things reasonably scoped. This PR is already pretty big. Lots of plumbing. ## Related Issues Closes #5023
yindo added the pull-request label 2026-02-20 17:50:01 -05:00
yindo closed this issue 2026-02-20 17:50:01 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#4327