Implementation:Langchain ai Langgraph Internal Config
| Knowledge Sources | |
|---|---|
| Domains | Internal, Configuration |
| Last Updated | 2026-02-11 16:00 GMT |
Overview
The internal config module provides core utilities for creating, merging, patching, and ensuring `RunnableConfig` objects throughout the LangGraph execution pipeline.
Description
This module is a foundational piece of LangGraph's internal machinery, responsible for managing the `RunnableConfig` dictionaries that flow through every node and step of a graph execution. It extends LangChain's configuration system with LangGraph-specific features such as checkpoint namespace management, configurable key handling, and metadata enrichment.
The `merge_configs()` function combines multiple `RunnableConfig` objects with intelligent merging strategies: metadata dictionaries are shallow-merged, tags are concatenated, callbacks are merged using LangChain's callback manager system (handling lists, managers, and mixed combinations), configurable dictionaries are shallow-merged, and recursion limits use a special rule where non-default values take precedence. The `patch_config()` function creates a modified copy of a config with selectively updated fields (callbacks, recursion limit, max concurrency, run name, configurable), taking care to clear `run_name` and `run_id` when callbacks are replaced to avoid stale tracing associations.
The `ensure_config()` function guarantees a fully populated config by starting with sensible defaults (empty tags, ChainMap metadata, default recursion limit from the `LANGGRAPH_DEFAULT_RECURSION_LIMIT` environment variable), overlaying any active context variable config, and then merging provided configs. It also automatically populates metadata from configurable values, excluding keys that start with `__`, contain sensitive substrings (key, token, secret, password, auth), or are non-primitive types.
Additional utilities include `patch_configurable()` for targeted updates to the configurable section, `recast_checkpoint_ns()` for stripping task IDs from checkpoint namespaces, `get_callback_manager_for_config()` and `get_async_callback_manager_for_config()` for obtaining properly configured callback managers with inherited tags and metadata.
Usage
Use `patch_config` when you need to create a child configuration with modified callbacks or run parameters for a sub-step. Use `merge_configs` when combining user-provided config with system defaults. Use `ensure_config` at the entry points of graph execution to guarantee a valid, fully-populated configuration. These functions are used pervasively throughout LangGraph's internal runtime.
Code Reference
Source Location
- Repository: Langchain_ai_Langgraph
- File: libs/langgraph/langgraph/_internal/_config.py
Signature
DEFAULT_RECURSION_LIMIT = int(getenv("LANGGRAPH_DEFAULT_RECURSION_LIMIT", "10000"))
def recast_checkpoint_ns(ns: str) -> str: ...
def patch_configurable(
config: RunnableConfig | None, patch: dict[str, Any]
) -> RunnableConfig: ...
def patch_checkpoint_map(
config: RunnableConfig | None, metadata: CheckpointMetadata | None
) -> RunnableConfig: ...
def merge_configs(*configs: RunnableConfig | None) -> RunnableConfig: ...
def patch_config(
config: RunnableConfig | None,
*,
callbacks: Callbacks = None,
recursion_limit: int | None = None,
max_concurrency: int | None = None,
run_name: str | None = None,
configurable: dict[str, Any] | None = None,
) -> RunnableConfig: ...
def get_callback_manager_for_config(
config: RunnableConfig, tags: Sequence[str] | None = None
) -> CallbackManager: ...
def get_async_callback_manager_for_config(
config: RunnableConfig, tags: Sequence[str] | None = None
) -> AsyncCallbackManager: ...
def ensure_config(*configs: RunnableConfig | None) -> RunnableConfig: ...
Import
from langgraph._internal._config import patch_config, merge_configs
I/O Contract
| Function | Input | Output | Description |
|---|---|---|---|
| `merge_configs` | None` | `RunnableConfig` | Merge multiple configs with intelligent field-level strategies |
| `patch_config` | None`, keyword args | `RunnableConfig` | Create a modified copy with selectively updated fields |
| `ensure_config` | None` | `RunnableConfig` | Return a fully populated config with defaults and context |
| `patch_configurable` | None`, `patch: dict` | `RunnableConfig` | Update only the configurable section of a config |
| `patch_checkpoint_map` | None`, `metadata: CheckpointMetadata | None` | `RunnableConfig` | Patch config with parent checkpoint mappings |
| `recast_checkpoint_ns` | `ns: str` | `str` | Strip task IDs from a checkpoint namespace string |
| `get_callback_manager_for_config` | `config: RunnableConfig`, optional `tags` | `CallbackManager` | Get a sync callback manager with inherited settings |
| `get_async_callback_manager_for_config` | `config: RunnableConfig`, optional `tags` | `AsyncCallbackManager` | Get an async callback manager with inherited settings |
| Merge Strategies by Key | ||
|---|---|---|
| Config Key | Strategy | Details |
| `metadata` | Shallow merge | Later values override earlier ones |
| `tags` | Concatenate | All tags are preserved in order |
| `callbacks` | Manager merge | Handles lists, managers, and mixed combinations |
| `configurable` | Shallow merge | Later values override earlier ones |
| `recursion_limit` | Non-default wins | Only overridden if value differs from `DEFAULT_RECURSION_LIMIT` |
| Other keys | Last write wins | Simple replacement |
Usage Examples
from langgraph._internal._config import (
merge_configs,
patch_config,
ensure_config,
patch_configurable,
)
# Merge multiple configs
base_config = {"metadata": {"source": "api"}, "tags": ["prod"]}
override_config = {"metadata": {"user": "alice"}, "tags": ["v2"]}
merged = merge_configs(base_config, override_config)
# Result: {"metadata": {"source": "api", "user": "alice"}, "tags": ["prod", "v2"], ...}
# Patch a config for a child step
child_config = patch_config(
merged,
callbacks=child_callback_manager,
run_name="process_step",
max_concurrency=5,
)
# Ensure a valid config with defaults
config = ensure_config(user_provided_config)
# Guarantees tags=[], metadata=ChainMap(...), recursion_limit=10000, configurable={}
# Patch only the configurable section
config = patch_configurable(config, {"thread_id": "abc123"})