Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

checkpoint
A saved copy of the state after a step, stored under a thread so a run can resume or rewind.
compile
The step that checks a graph's connections and turns it into something that can be run.
conditional edge
A rule that reads the state and names which node runs next.
edge
A rule saying which node runs after the current one finishes.
entry point
The declared first node of a graph, marked by an edge from the start.
graph
A workflow drawn as nodes joined by edges, where the path can branch and loop.
interrupt
A planned pause before a node runs, so a person can approve, reject or edit first.
node
A function that reads the state and returns only the keys it changed.
reducer
A function that decides how an update is combined with the old value of one state key.
state
The shared record passed between nodes, holding every value the workflow needs to continue.
subgraph
A graph mounted inside another as a single node, with its own slice of state.
supervisor
A node that reads the state and chooses which specialist worker runs next, rather than answering itself.
thread
A named run whose checkpoints are stored together, so it can be listed, resumed or branched.

LangGraph from the ground up

Capstone: a writer-critic graph

A draft, a critique, a revision loop with a cap, a checkpoint after every step, and an approval before anything is published. Every idea in the course, once.

Part 10 of 10

Advanced22 min readBack to Courses

The shape of the workflow

The writer produces a draft. The critic scores it and writes down what is wrong. A router decides: revise, publish, or give up. The revise edge goes back to the writer with the critique in the state, and the attempt counter goes up.

That is a graph with one loop and two routes out. Everything the course covered has a place in it: state and reducers, a conditional edge, a counter, a checkpoint, and an interrupt before the action that cannot be undone.

A trace of one run: write produces draft one, attempts one. Critique scores 0.6 and says “needs an example”. The router returns revise. Write produces draft two with the note in the state, attempts two. Critique scores 0.8. The router returns publish, and the interrupt stops before it. Four steps, one loop.

The cap is the design

The cap is not a safety feature bolted on at the end; it is what makes the loop predictable. Three attempts and then a decision — publish the best draft, or escalate — is a workflow. “Revise until good” is not, because “good” may never arrive.

When the cap is reached, the state should say so and carry the best attempt. A caller can then decide to accept it, hand it to a person, or fail. The graph’s job is to make that decision visible.

A worked cap: attempts one and two score 0.6 and 0.75; attempt three scores 0.78. The router checks the cap first, so it returns give_up even though the score is close. The state carries status “gave up” and the best draft, which is the one with the highest score. A caller can publish it with a warning, send it to a person, or fail the request. The cap also makes the cost predictable: at most three writer and three critic calls per request.

The same workflow in LangGraph

builder.add_node("write", write)
builder.add_node("critique", critique)
builder.add_node("publish", publish)

builder.add_edge(START, "write")
builder.add_edge("write", "critique")
builder.add_conditional_edges("critique", route, {
    "revise": "write",
    "publish": "publish",
    "give_up": END,
})

graph = builder.compile(checkpointer=checkpointer, interrupt_before=["publish"])

The loop with a cap

Run it and read the trace. Then make the critic impossible to satisfy and confirm the graph gives up with the best attempt instead of looping.

Output
Click "Run" to execute your code

Where the state earns its keep

The critic needs the draft. The writer, on the second pass, needs the critique and the previous draft. The router needs the attempt count and the score. All of it is state, and all of it is inspectable when something goes wrong.

The one thing that should not be in the state is the model’s reasoning. A long chain of thought re-sent on every node costs tokens and rarely helps the next step. Keep the conclusion and the critique, drop the transcript.

The state keys are the workflow: topic, draft, critique, attempts, score, and history. History lets give-up choose the best draft. The model’s reasoning is not in the state, because it is re-sent on every node and rarely changes the next step. A state with six keys is readable; one with thirty is a debugging project.

Log the attempt count and the final score for every run. The distribution of attempts tells you whether the critic is calibrated long before anyone reads a single draft.

Score the critic, not only the writer

The loop is only as good as the critic. If the critic passes everything, the writer never revises; if it passes nothing, every run hits the cap. Both look like a writer problem and are not.

Label a sample of drafts by hand and compare the critic’s scores with your labels. If the critic is too generous, the rubric is missing a clause; if it is too harsh, the bar is above what the writer can reach. Calibrate the critic before tuning the writer.

Adding the human

The approval goes before publish, not after. The checkpoint holds the final draft and the critique, a person reads both, and their decision is a key in the state. Approve, edit, or reject with a note that routes back to the writer.

The graph does not change shape. It gains one edge and one key, which is the test of whether the earlier chapters were built correctly.

The approval screen should show the draft and the critique together, because the critique is the reason the draft looks the way it does. An edit should store both versions, and a rejection should carry a note that reaches the writer. That note is the only way the next attempt can be different.

Approve before publishing

Run to the gate, inspect the draft, then resume with approval. Then run a second thread, reject it with a note, and confirm the note reaches the writer.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What are the nodes in the writer-critic graph?