Skip to content

LangGraph config.configurable -> context API -- feedback wanted! #5023

Description

TL;DR

We're proposing a cleaner, more intuitive API for passing immutable context to graph runs, addressing one of the most common sources of developer confusion in LangGraph today.

The Problem: Context Management Complexity

One of LangGraph's core value propositions is making it easy to pass the right context to your LLMs so that your agents work effectively. This is crucial for building production-ready AI applications. Here's an in-depth explanation of why context engineering matters.

Currently, LangGraph supports 3 levels of context management:

Context Management Levels

However, users consistently express confusion about the config level context. The current approach requires nested configuration:

class StateSchema(TypedDict):
    messages: Annotated[list[str], add_messages]

class ConfigSchema(TypedDict):
    user_id: str
    
builder = StateGraph(state_schema=StateSchema, config_schema=ConfigSchema)
agent = builder.compile()
agent.invoke(
    {"messages": [{"role": "user", "content": "hi!"}]},
    config={"configurable": {"user_id": "user_123"}}  # ← Confusing nesting, what even is "configurable"?
)

The core issue: Specifying immutable dependencies for a graph run via config["configurable"] is unintuitive and unnecessarily nested. This deserves a top-level argument, like state currently has.

Proposed Solution: Three-Part API Redesign

All changes maintain full backwards compatibility unless explicitly noted.

1. Cleaner StateGraph Initialization

Replace config_schema with the more descriptive context_schema:

# Current (still supported)
builder = StateGraph(state_schema, config_schema)

# New (recommended)
builder = StateGraph(state_schema, context_schema)

context_schema is typed as ContextT, enabling proper type checking throughout StateGraph usage. config_schema will route to context_schema automatically.

2. Simplified Graph Invocation

.invoke() and related methods now accept a top-level context argument, plus we're extracting commonly-used config values:

# Current (still supported)
agent.invoke(
    state,
    config={"configurable": {"user_id": "user_123", "thread_id": "12345"}}
)

# New (recommended)
agent.invoke(
    state,
    config={"thread_id": "12345"},
    context={"user_id": "user_123"},
)

3. Enhanced Node Function Signatures

Introduce a Runtime object that bundles context with other execution metadata:

# Current approach
def my_node(state: StateSchema, config: RunnableConfig):
    user_id = config["configurable"]["user_id"]  # Deep nesting
    # ...

# New approach
class Runtime(Generic[ContextT]):
    context: ContextT
    config: LangGraphConfig  # Cleaner config with top-level properties
   
    @property
    def stream_writer(self) -> StreamWriter:
        """Access streaming utilities without complex injection into node signatures."""

def my_node(state: StateSchema, runtime: Runtime):
    user_id = runtime.context.user_id  # Clean, typed access
    thread_id = runtime.config.thread_id  # No more nesting under "configurable"
    # ...

Migration Path & Backwards Compatibility

  • Zero Breaking Changes: All existing code continues to work
  • Gradual Migration: Teams can adopt the new API incrementally
  • Clear Documentation: Migration guide with side-by-side examples
  • Deprecation Timeline: Old patterns marked as deprecated but remain functional - this is TBD, we might not do a hard deprecation of config_schema yet, but a soft deprecation for v1...

Why This Matters for v1

This change addresses the #1 developer pain point we hear about in community feedback. By making context management intuitive, we improve readability, set a strong API foundation for v1, and reduce confusion with onboarding.

We Want Your Feedback!

This API will be central to LangGraph v1, so your input is crucial:

Naming & Design:

  • Do the names context_schema, context, and Runtime feel intuitive?
  • What alternative names would you suggest?
  • Does the Runtime object feel like the right abstraction?

Functionality:

  • What other utilities would you like to see in Runtime?
  • Are there additional config values that should be promoted to top-level?
  • What migration concerns do you have?

Please share your thoughts, especially if you have concerns about the migration path or suggestions for making this transition smoother!

[UPDATE]: This is a really big change, I don't think we should rush this. Would love to collect more feedback over time.

Metadata

Metadata

Labels

changesomething needs to work differentlymaintainerIssue created by library maintainer

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions