Runtime context and configuration

LangGraph · Practical · 10 min

Separating configuration from state keeps state clean and lets one compiled graph serve many users and settings.

Some information is needed by nodes but isn't part of the evolving state: the current user's ID, which model to use, a database connection, feature flags. LangGraph calls this runtime context.

1. Declare its shape, usually with a dataclass, and give it to the builder: StateGraph(State, context_schema=Context). 2. Pass a value per run: graph.invoke(inputs, context=Context(user_id="42")). 3. In a node, add a parameter runtime: Runtime[Context] and read runtime.context.user_id. LangGraph injects it automatically.

The Runtime object also gives nodes access to the store (long-term memory, later lesson) and the stream writer.

Why not put it in state? State is saved in every checkpoint and can be changed by nodes; context is read-only for the run and isn't saved. That makes it the right place for secrets-adjacent or per-request settings.

The older way to pass such values was config["configurable"]. That dict still carries LangGraph's own keys such as thread_id, but for your own settings context is now the recommended, type-checked route.

Other useful config keys: recursion_limit, max_concurrency (cap on parallel tasks), and tags/metadata that show up in traces.

Example

from dataclasses import dataclass
from langgraph.graph import StateGraph, START, END, MessagesState
from langgraph.runtime import Runtime


@dataclass
class Context:
    user_id: str
    tone: str = "friendly"


def greet(state: MessagesState, runtime: Runtime[Context]) -> dict:
    ctx = runtime.context
    return {"messages": [{"role": "assistant", "content": f"Hi user {ctx.user_id} ({ctx.tone})"}]}


b = StateGraph(MessagesState, context_schema=Context)
b.add_node(greet)
b.add_edge(START, "greet")
b.add_edge("greet", END)
graph = b.compile()

out = graph.invoke({"messages": [{"role": "user", "content": "hello"}]},
                   context=Context(user_id="42", tone="formal"))
print(out["messages"][-1].content)     # Hi user 42 (formal)

Remember

  • context_schema + invoke(..., context=...) passes run-wide settings
  • Nodes read it via a runtime: Runtime[Context] parameter
  • Context is read-only and not checkpointed, unlike state
  • thread_id still goes in config['configurable']

Check yourself

  1. Where should the current user's ID for a run live?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langgraph/graph-api