DS DevShelfHub Projects · AI tools
Tutorials / LangChain / Reference / Methods / .compile()
Method StateGraph

.compile(): Reference Guide

By DevShelfHub

Compile the graph for execution.

What is .compile()?

.compile() is the final step in building a LangGraph StateGraph: it validates the graph structure, resolves the state type, and returns a CompiledStateGraph — a Runnable you can invoke, stream, or batch like any other LangChain component. Until .compile() is called, the graph is a mutable builder object; modifying it after compilation raises an error.

Compilation performs several structural checks: it verifies that all edge targets are registered nodes, that START has at least one outgoing edge, that END is reachable from every branch, and that the state schema is a valid TypedDict or Pydantic model. These checks surface configuration mistakes at startup rather than mid-execution. The checkpointer parameter is where multi-turn state persistence lives: passing a MemorySaver() stores graph state in memory between invocations keyed by a thread_id; passing a PostgresSaver or SqliteSaver persists state across process restarts. Without a checkpointer, every graph.invoke() call starts with a fresh state.

The interrupt_before and interrupt_after parameters let you pause execution mid-graph for human-in-the-loop approval workflows. The graph saves a checkpoint at the interrupt point and waits for a resume call — graph.invoke(None, config) — with the same thread_id. Compiled graphs are reusable and thread-safe: compile once at application startup, then invoke concurrently from multiple threads or async tasks without rebinding.

Use Cases

  • Finalize workflows
  • Enable checkpointing
  • Create executable graphs
  • Prepare for invocation
  • Add persistence
  • State management

Key Features

  • Graph finalization
  • Checkpointing support
  • Runnable interface
  • Invoke-able
  • State persistence
  • Flexible backends

When NOT to Use

You must compile before invoking any StateGraph — there is no alternative. Rebuild and recompile if you need to change graph structure after compilation.

Notes

Compile once at startup — not inside request handlers

.compile() validates the entire graph structure and is comparatively expensive. Do it at module level or in an application startup hook. Calling it inside a request handler adds latency to every request and negates the thread-safety benefit of reusing a single compiled graph.

thread_id is required when using a checkpointer

Passing a checkpointer without a thread_id in the invocation config raises a ValueError at runtime. Always include config={"configurable": {"thread_id": "some-unique-id"}} in every invoke/stream call when the graph was compiled with a checkpointer.

interrupt_before pauses — it does not cancel

After an interrupt_before, the graph checkpoint is saved and execution halts. To resume, call graph.invoke(None, config) with the same thread_id — passing None as input resumes from the saved checkpoint. Passing a new input dict restarts the graph from the beginning.

Subgraphs must be compiled before adding as nodes

Each subgraph (a nested StateGraph) must be independently compiled before being registered as a node in the parent graph. Passing an uncompiled StateGraph as a node raises a validation error at parent compile time, not at runtime.

Method Signature

python
graph = builder.compile(
    checkpointer=None,
    interrupt_before=None,
    interrupt_after=None,
)

Parameters

Parameter Type Required Purpose
checkpointer BaseCheckpointSaver | None No Checkpoint storage for state persistence across turns
interrupt_before list[str] | None No Node names to pause before for human-in-the-loop
interrupt_after list[str] | None No Node names to pause after execution

Return Value

Type:

CompiledStateGraph

Description:

Compiled graph as a Runnable

Example Output:

graph = builder.compile()

Code Examples

Compile with MemorySaver for multi-turn memory

python
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from typing import TypedDict

class State(TypedDict):
    messages: list

def chat_node(state):
    return {"messages": state["messages"] + ["response"]}

builder = StateGraph(State)
builder.add_node("chat", chat_node)
builder.add_edge(START, "chat")
builder.add_edge("chat", END)

checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)

config = {"configurable": {"thread_id": "user-42"}}
result = graph.invoke({"messages": ["Hello"]}, config)

Human-in-the-loop with interrupt_before

python
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from typing import TypedDict

class State(TypedDict):
    draft: str
    approved: bool

def write_draft(state):
    return {"draft": "This is my draft content"}

def publish(state):
    return {"draft": state["draft"] + " [PUBLISHED]"}

builder = StateGraph(State)
builder.add_node("write", write_draft)
builder.add_node("publish", publish)
builder.add_edge(START, "write")
builder.add_edge("write", "publish")
builder.add_edge("publish", END)

# Pause before publish for human review
graph = builder.compile(
    checkpointer=MemorySaver(),
    interrupt_before=["publish"],
)
config = {"configurable": {"thread_id": "draft-1"}}
graph.invoke({"draft": "", "approved": False}, config)
# Graph paused — human reviews state["draft"] here
# Resume after approval:
graph.invoke(None, config)

Persistent state with SqliteSaver across restarts

python
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.sqlite import SqliteSaver
from typing import TypedDict

class State(TypedDict):
    count: int

def increment(state):
    return {"count": state["count"] + 1}

builder = StateGraph(State)
builder.add_node("inc", increment)
builder.add_edge(START, "inc")
builder.add_edge("inc", END)

# Persist state across process restarts
with SqliteSaver.from_conn_string("checkpoints.db") as saver:
    graph = builder.compile(checkpointer=saver)
    config = {"configurable": {"thread_id": "session-1"}}
    result = graph.invoke({"count": 0}, config)
    print(result["count"])  # 1
    result = graph.invoke(None, config)  # resume
    print(result["count"])  # 2

Common Mistakes

❌ builder.invoke(input) # Must compile first

✅ graph = builder.compile(); graph.invoke(input)

Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with .compile() and the wider framework.

.compile() FAQ

What does .compile() do in LangChain?

Compile the graph for execution. .compile() is the final step in building a LangGraph StateGraph: it validates the graph structure, resolves the state type, and returns a CompiledStateGraph — a Runnable you can invoke, stream, or batch like any other LangChain component. Until .compile() is called, the graph is a mutable builder object; modifying it after compilation raises an error. Compilation performs several structural checks: it verifies that all edge targets are registered nodes, that START has at lea…

Which LangChain classes support .compile()?

.compile() is available on StateGraph. Pin your installed LangChain version and verify the method exists in that release before deploying.

When should I use .compile()?

Use .compile() when your LangChain chains, agents, or pipelines need the behavior described in this guide.

What does .compile() return?

.compile() returns a CompiledStateGraph. Compiled graph as a Runnable

Does .compile() have an async equivalent?

.compile() does not have a documented async variant. Avoid .compile() You must compile before invoking any StateGraph — there is no alternative. Rebuild and recompile if you need to change graph structure after compilation.

Where can I explore more LangChain API reference pages?

Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.