e071084ebe
govulncheck / govulncheck (push) Waiting to run
Harness (E2E) / Harnesses (mock LLM) (push) Waiting to run
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Run Tests / Unit Tests (push) Waiting to run
Run Tests / Etcd Integration Tests (push) Waiting to run
Durable Flow
A workflow that survives a crash and resumes where it stopped.
A flow can be an ordered list of steps — a task with stages —
instead of a single LLM turn. Each step is checkpointed before and after
through a pluggable Checkpoint (store-backed by default), so if the
process dies mid-run, the run resumes at the step it stopped on, without
re-running the steps that already completed (and already had their side
effects).
What this shows
A three-step checkout (reserve → charge → confirm) whose charge step
fails the first time, simulating a transient outage / crash:
first run:
reserve → inventory reserved
charge → payment dependency unavailable (crash)
run failed: payment gateway timeout
checkpoint: run 70643f61 is at step "charge" (status failed)
resume:
charge → payment captured
confirm → order confirmed
reserve ran 1 time(s) total — completed steps are not repeated on resume
no pending runs — the workflow completed durably
The key line is the last pair: on Resume, reserve does not run
again — its result was checkpointed — and the run finishes.
The pieces
f := micro.NewFlow("checkout",
micro.FlowSteps(
micro.FlowStep{Name: "reserve", Run: reserve},
micro.FlowStep{Name: "charge", Run: charge},
micro.FlowStep{Name: "confirm", Run: confirm},
),
micro.FlowWithCheckpoint(micro.StoreCheckpoint(nil, "checkout")), // nil store = default; "checkout" = key scope
)
f.Execute(ctx, `{}`) // runs; crashes at charge
pending, _ := f.Pending(ctx) // the run, checkpointed at "charge"
f.Resume(ctx, pending[0].ID) // continues from charge to the end
Statecarries a typed payload (Set/Scan) plus aStagemarker — the resume point.Checkpointpersists eachRun. The built-in is store-backed and keeps each flow's runs in their own store table (databaseflow, tablecheckout) viastore.Scope, so one flow's runs don't share a table with another's — or with agent or service state. Point the default store at Postgres or NATS KV and a run survives a real process restart, or implement the interface to plug in Temporal, Restate, etc.- A real step would be
flow.Call(service, endpoint)(an RPC),flow.Dispatch(agent)(hand off to an agent), orflow.LLM(prompt)(one model turn). Here they're plain funcs so durability is the only thing on display.
Run
go run main.go
No LLM key required.