[PR #6381] fix(langgraph): merge CONF sections and preserve runtime in subgraphs #5005

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

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

State: closed
Merged: No


Description:

Fixes issue where runtime (store and context) is lost when manually invoking a subgraph with a config parameter.

Users need to pass custom configs when invoking subgraphs (e.g., to set thread_id for checkpointing). However, this caused the runtime configuration to be overwritten instead of merged, losing access to store and context.

The fix changes ensure_config() to merge CONF sections instead of replacing them.

Minimum reproducible example:

from dataclasses import dataclass
from langchain_core.runnables import RunnableConfig
from langgraph.graph.state import StateGraph
from langgraph.runtime import Runtime
from typing_extensions import TypedDict
from langgraph.store.memory import InMemoryStore

@dataclass
class Context:
    username: str

class State(TypedDict):
    foo: str

# Subgraph
def subgraph_node_1(state: State, runtime: Runtime[Context]):
    assert runtime.store is not None, "Store is required"
    assert runtime.context is not None, "Context is required"
    username = state['foo']
    runtime.store.put(('subgraph', '1'), 'foo', {'value': 'hi! ' + username})
    return {'foo': 'hi! ' + username}

subgraph_builder = StateGraph(State, context_schema=Context)
subgraph_builder.add_node(subgraph_node_1)
subgraph_builder.set_entry_point('subgraph_node_1')
subgraph = subgraph_builder.compile()

# Parent graph
def main_node(state: State, runtime: Runtime[Context]):
    last_foo = runtime.store.get(('subgraph', '1'), 'foo')
    if last_foo:
        last_foo = last_foo.value['value']
    else:
        last_foo = runtime.context.username
    return {'foo': 'hello ' + str(last_foo)}

def invoke_subgraph(state: State, runtime: Runtime[Context], config: RunnableConfig):
    new_config = {
        **config,
        'configurable': {
            **config.get('configurable', {}),
            'thread_id': '1'
        },
    }
    return subgraph.invoke(input=state, config=new_config)

store = InMemoryStore()
builder = StateGraph(State, context_schema=Context)
builder.add_node(main_node)
builder.add_node(invoke_subgraph)
builder.set_entry_point('main_node')
builder.add_edge('main_node', 'invoke_subgraph')
graph = builder.compile(store=store)

context = Context(username='Alice')
result = graph.invoke(input={'foo': 'world'}, context=context)
print(result)  # Before fix: AssertionError. After fix: {'foo': 'hi! hello Alice'}
**Original Pull Request:** https://github.com/langchain-ai/langgraph/pull/6381 **State:** closed **Merged:** No --- **Description:** Fixes issue where runtime (store and context) is lost when manually invoking a subgraph with a config parameter. Users need to pass custom configs when invoking subgraphs (e.g., to set `thread_id` for checkpointing). However, this caused the runtime configuration to be overwritten instead of merged, losing access to store and context. The fix changes `ensure_config()` to merge CONF sections instead of replacing them. **Minimum reproducible example:** ```python from dataclasses import dataclass from langchain_core.runnables import RunnableConfig from langgraph.graph.state import StateGraph from langgraph.runtime import Runtime from typing_extensions import TypedDict from langgraph.store.memory import InMemoryStore @dataclass class Context: username: str class State(TypedDict): foo: str # Subgraph def subgraph_node_1(state: State, runtime: Runtime[Context]): assert runtime.store is not None, "Store is required" assert runtime.context is not None, "Context is required" username = state['foo'] runtime.store.put(('subgraph', '1'), 'foo', {'value': 'hi! ' + username}) return {'foo': 'hi! ' + username} subgraph_builder = StateGraph(State, context_schema=Context) subgraph_builder.add_node(subgraph_node_1) subgraph_builder.set_entry_point('subgraph_node_1') subgraph = subgraph_builder.compile() # Parent graph def main_node(state: State, runtime: Runtime[Context]): last_foo = runtime.store.get(('subgraph', '1'), 'foo') if last_foo: last_foo = last_foo.value['value'] else: last_foo = runtime.context.username return {'foo': 'hello ' + str(last_foo)} def invoke_subgraph(state: State, runtime: Runtime[Context], config: RunnableConfig): new_config = { **config, 'configurable': { **config.get('configurable', {}), 'thread_id': '1' }, } return subgraph.invoke(input=state, config=new_config) store = InMemoryStore() builder = StateGraph(State, context_schema=Context) builder.add_node(main_node) builder.add_node(invoke_subgraph) builder.set_entry_point('main_node') builder.add_edge('main_node', 'invoke_subgraph') graph = builder.compile(store=store) context = Context(username='Alice') result = graph.invoke(input={'foo': 'world'}, context=context) print(result) # Before fix: AssertionError. After fix: {'foo': 'hi! hello Alice'} ```
yindo added the pull-request label 2026-02-20 17:51:05 -05:00
yindo closed this issue 2026-02-20 17:51:05 -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#5005