PRACTICAL AI & AUTOMATION

LangGraph for Practical Workflows: State, Approval and Recovery

Build a runnable LangGraph workflow in Python with explicit state, human approval, conditional routing and verification, then plan durable recovery.

Manabi Kōbō··12 min·775 words
AI AutomationLangGraphPythonAgent Workflows
LangGraph for Practical Workflows: State, Approval and Recovery
ENNATURAL ARTICLE

Build a runnable LangGraph workflow in Python with explicit state, human approval, conditional routing and verification, then plan durable recovery.

Step 1: Decide whether your task needs a graph

A single script is often enough for a linear task. LangGraph becomes useful when work has explicit state, branches, pauses and resumable steps. Think of a file report that must be prepared, reviewed, written and checked: the route matters as much as the model’s answer.

We will build that flow without an LLM first. This makes the control behavior easy to inspect and costs no model API calls. Later you can replace the preparation node with an Ollama or Codex-backed adapter while preserving the same review and verification boundaries.

The Graph API overview explains state, nodes and edges. A node performs one step; an edge chooses what follows; state contains the information passed between them.

Step 2: Create an isolated Python environment

On Ubuntu install python3-venv if needed, create a fresh lab directory and activate a virtual environment. Install LangGraph there and check its installed version. Save the resulting dependencies when you have a working example so another machine can reproduce the same package set.

The official quickstart shows the core graph construction. This article’s file-report example is deliberately small and does not require LangSmith or a model-provider key.

Open the complete copyable example — example-01.txt

# Open full code above.

Step 3: Define the state and approval boundary

Our state contains the input note, proposed report, approval decision and verification flag. The flow is START → prepare → approve → write → verify → END. Rejection goes from approve directly to END and never reaches the writer.

The approval node calls interrupt, which pauses the graph. Resume it with Command(resume=...) using the same thread_id. Keep file writes after the approval node: an interrupted node can run again when resumed. See interrupts and resuming for these semantics.

The report output is a fixed lab path. It replaces an earlier lab report when approved. Run the example in its dedicated directory, rather than placing an existing important report at that path.

Step 4: Run a complete review-and-write flow

Save this code as flow.py. Run python flow.py and first answer n. Run it again and answer y. The first run stops without writing; the second writes output/report.txt and verifies its exact contents.

The in-memory checkpointer supports this pause and resume within one running process. It does not survive process exit. This is a complete local teaching example, not a production persistence configuration.

Open the complete copyable example — flow.py

# Open full code above.

Step 5: Verify both branches and add a model carefully

Test rejection in a fresh directory and confirm no output file appears. Test approval and compare the file with the displayed proposal. Test an empty input note and expect failure before approval. If a previous report exists, rejection should leave it unchanged; checking only for file existence would be the wrong test.

When adding an LLM, make prepare return a proposed report in the same state field. Validate its type, size and allowed content before approval. Treat retrieved documents as data and leave the writer deterministic. A generated claim that a write succeeded cannot replace the verify node’s file read.

For the KVM project, the graph can organize observe → propose one action → approve → operate → observe again. That requires your own tested bridge adapter. LangGraph does not supply a GL-RM10 driver or make coordinates reliable. Limit the action count and route unexpected screens to a stop state.

Step 6: Add durable recovery and bounded retries

For a service, replace InMemorySaver with a supported durable checkpointer and use a unique thread ID per job. Protect stored state and define retention. State checkpoints preserve workflow progress; they do not guarantee that external side effects happened exactly once. See the persistence guide.

Retry transient reads with a small attempt limit and delay. Before retrying a write or remote action, check whether the prior attempt already happened and use an idempotency key where possible. A recursive loop without a stop condition can repeat clicks, duplicate messages or overwrite files.

Keep a simple run record: job ID, input source, approved proposal, executed step, verification and error. Prefer inspecting those facts over trusting a fluent final summary. The right starting flow is one you can explain, reject and recover—not the largest graph you can draw.

Japanese practice: the marked verb is ‘approve’. Read the sentence alongside the approval node and notice how を marks the action being approved.

Continue the series

JP日本語

LangGraphで実用フロー:状態、承認、回復

SubjectObjectVerbParticleTechnicalConnectorAdjectiveTime / context
CONTINUE IN MANABI KŌBŌ

Put this idea into practice

Reading Nook

Practice bilingual reading with Japanese scaffolding.

Open tool →
Guided Japanese Course

Continue with structured lessons and practice.

Open tool →
Adaptive Recall

Turn useful phrases into spaced practice.

Open tool →
RELATED NOTES
← Back to all articles
Share this note Email