I’m using LangGraph to execute multi-step logic inside a single node — where each step resolves part of the state. Sometimes execution is interrupted mid-node due to HITL (GraphInterrupt), and the graph resumes later.
Currently, LangGraph only persists state after the node completes, unless the node is implemented as an async generator AND executed in streaming mode AND all fields are explicitly registered with reducers.
The problem:
- A node executes multiple internal sub-steps.
- We need idempotent execution on resume.
- We want to persist partial state updates mid-node so progress is not lost.
- But refactoring the logic into multiple smaller nodes is either not natural for the workflow or adds unnecessary graph complexity.
Today, achieving this requires workarounds like:
- Using async generator nodes + yield
- Ensuring checkpointers + stream execution
- Ensuring reducers are configured correctly
- Or manually storing partial state in Redis/Postgres
This makes resumability fragile and easy to misconfigure.
Requested Feature:
Add native mid-node state persistence support, such as:
await state.save_partial({"resolved_params": {...}})
or an equivalent function that:
- Applies reducers
- Merges into state store
- Writes to the checkpointer immediately
- Does NOT require converting the node into a streaming async generator
Why this matters:
This enables clean, reliable, resumable execution for patterns like:
- Param resolution workflows
- ETL pipelines
- Long-running LLM reasoning loops
- HITL / approval-gated execution steps
- Agent planning/execution cycles
Example Use Case:
for step in resolution_plan:
resolved_params = state.get("resolved_params")
if resolved_params.param is resolved:
continue
result = run_step(step)
state.save_partial({"resolved_params": {step.name: result}})
if result.requires_human_input:
raise GraphInterrupt()
After HITL, the node will resume execution from start but because mid node executions are persisted and node is made idempotent so already resolved steps would be skipped.