Skip to content

LangGraph, from state to durable workflow

  • Book chapter
  • Intermediate
  • 30 min read
  • Checked 16 Aug 2026

Imagine a customer asks:

Why was invoice 1042 charged twice?

The first step classifies the request. The next step may read billing records. A policy check may pause the case for approval. A temporary billing API failure may retry. If the process stops overnight, it may need to resume tomorrow without starting again.

That is the kind of workflow LangGraph helps make visible.

Chapter Question you will be able to answer
1. Graph model How do state, nodes, and edges fit together?
2. Concepts Which LangGraph object owns each behavior?
3. Runtime words What is Python async, and what is LangGraph durability?
4. Execution What happens from START to END?
5. Failure How should tools retry, stop, or ask for help?
6. Production review Which questions expose unsafe workflow design?

Chapter 1: Build the workflow from five parts

Section titled “Chapter 1: Build the workflow from five parts”
  1. 01Define state
  2. 02Add nodes
  3. 03Connect edges
  4. 04Compile
  5. 05Run and observe
Part Question to ask Start here
1. State What facts must survive the next step? State schema
2. Work Which small function owns this operation? Nodes
3. Route What must run next, and who chooses it? Edges
4. Runtime How will this run, stream, pause, or resume? Compile
5. Failure Which error retries, stops, or needs a person? Retries and tool failures

StateGraph is the builder. State is the shared record. Nodes return updates. Edges schedule the next work. compile() produces the runnable graph.1

Read the first ten in order once. Use the remaining nine when the workflow needs tools, persistence, parallel work, or recovery.

# Concept Keep this sentence
1 StateGraph The builder that holds the workflow definition.
2 State schema The contract for data moving through the graph.
3 Reducers and Annotated The rule for combining two updates to one state key.
4 Nodes Python functions that do one unit of work.
5 Edges Static transitions between nodes.
6 Conditional edges A routing function chooses the next node.
7 START and END Virtual markers for entry and termination.
8 compile() Validate the definition and create a runnable graph.
9 invoke() and ainvoke() Run to a final result, synchronously or asynchronously.
10 stream() and astream() Observe updates while the graph runs.
11 Command Return a state update and route together, or resume an interrupt.
12 Send and fan-out Create parallel node calls with different inputs.
13 ToolNode and tools_condition Execute model-requested tools and route the tool loop.
14 Checkpoints and thread_id Save state snapshots under one run or conversation identity.
15 Durability modes Choose when checkpoint writes must finish.
16 Interrupt and resume Persist a pause and continue later with external input.
17 Subgraphs Put a smaller graph behind a clear parent interface.
18 RetryPolicy and tool failures Retry classified transient failures at the node boundary.
19 Async waiting and timeouts await is Python; durable waiting needs LangGraph state and policy.

Chapter 3: Keep runtime words in the correct layer

Section titled “Chapter 3: Keep runtime words in the correct layer”
Word Owned by What it means
async def Python Define a coroutine function.
await Python Yield control until an awaitable completes.
asyncio.sleep() Python Keep an in-memory coroutine paused for a duration.
ainvoke() / astream() LangGraph runnable API Run or stream the graph asynchronously.
RetryPolicy LangGraph Re-run a failed node attempt with bounded backoff.
TimeoutPolicy LangGraph Cancel an async node attempt that exceeds its limit.
interrupt() LangGraph Save a pause and wait for an external resume value.

sleep, await, and asyncio.sleep are not LangGraph keywords. Sleeping inside a node does not create a durable timer or checkpoint. Use RetryPolicy for short transient retries and interrupt() plus a checkpointer for a pause that must survive process restarts.2

Chapter 4: Read one graph from beginning to end

Section titled “Chapter 4: Read one graph from beginning to end”

The example below keeps the work deliberately small. It classifies a support question and drafts the next response.

Read it in this order:

  1. SupportState defines the fields that move through the workflow.
  2. classify reads the question and returns only the category update.
  3. draft_response reads the updated category and returns the response.
  4. The builder registers both nodes.
  5. Edges connect START → classify → draft_response → END.
  6. compile() creates the runnable graph.
  7. invoke() supplies the initial state and waits for the final state.
src/examples/langgraph/support_graph.py
"""A minimal LangGraph workflow with explicit, inspectable state."""
from typing import Literal, TypedDict
from langgraph.graph import END, START, StateGraph
class SupportState(TypedDict):
question: str
category: Literal["invoice", "general"]
response: str
def classify(state: SupportState) -> dict:
category = "invoice" if "invoice" in state["question"].lower() else "general"
return {"category": category}
def draft_response(state: SupportState) -> dict:
if state["category"] == "invoice":
response = "I will look up the invoice and cite the matching record."
else:
response = "I will search the support knowledge base before answering."
return {"response": response}
builder = StateGraph(SupportState)
builder.add_node("classify", classify)
builder.add_node("draft_response", draft_response)
builder.add_edge(START, "classify")
builder.add_edge("classify", "draft_response")
builder.add_edge("draft_response", END)
graph = builder.compile()
result = graph.invoke(
{"question": "Why is invoice 1042 duplicated?", "category": "general", "response": ""}
)
print(result["response"])

This example does not need an agent. The path is known. LangGraph can still help because the state and sequence are explicit. Add conditional edges only when the next node truly depends on state.

Chapter 5: Decide what happens when a tool fails

Section titled “Chapter 5: Decide what happens when a tool fails”
  1. 01Model requests a tool
  2. 02ToolNode validates arguments
  3. 03Tool executes
  4. 04Exception is handled or escapes
  5. 05RetryPolicy retries the node or recovery takes over
Failure Normal owner Result
Malformed model arguments ToolNode default handler Error ToolMessage; the model may correct its call.
Temporary upstream failure Node RetryPolicy Exception must escape ToolNode; LangGraph retries the node.
Missing permission or bad user input Application rule Stop, return a safe error, or ask the user. Do not retry blindly.
Retries exhausted Node error handler or caller Route to fallback/human review, or let the run fail visibly.
Unknown exception Developer Let it bubble, trace it, and fix the defect.

Retries happen around the whole node attempt, not around one line inside a tool. Any side-effecting tool in that node needs an idempotency key or a check-before-write rule.

Chapter 6: Review the workflow before production

Section titled “Chapter 6: Review the workflow before production”
  1. Which state keys may receive parallel updates, and what reducer merges them?
  2. Which node owns each network call and timeout?
  3. Which exceptions are transient, user-fixable, policy failures, or defects?
  4. Can a retry send the same email, payment, or ticket twice?
  5. Which checkpoint and tenant boundary does thread_id identify?
  6. Where does a person approve, reject, or correct the run?
  7. What stops every loop and caps every fan-out?

LangGraph is a runtime for stateful workflows. I define a state schema, write small Python nodes, connect them with fixed or conditional edges, compile the graph, and invoke or stream it. A checkpointer can persist state under a thread so the workflow can pause and resume. RetryPolicy retries classified node failures, while interrupt() creates a durable human or external-input boundary. I keep side effects idempotent because a retry repeats the node attempt, and I put a stop rule on every loop and fan-out.

Next: see how checkpoints and threads preserve state, how interrupt and resume pauses work, or how tool failures and retries should behave.

  1. LangChain, Graph API overview.

  2. LangChain, Fault tolerance and Interrupts.