02 · Resolve
Do not guess
what the crash did.
If the previous transition is not proven terminal or safely recoverable, Mycelium will not redispatch. Ambiguous payments stay blocked until reconciliation.
Start with a concrete example: prevent duplicate tool calls in LangGraph.
Invariant
Proven terminal,
or do not fire again.
Tracers explain the incident afterward. Resolution decides whether a retry is a second side effect. An operator can later mycelium transitions release a blocked record. That is not a gate that re-runs the tool.
ALLOWNo prior transition, or policy permits a safe retry. The tool may run.
RETURNThe transition already completed. Replay the stored result.
POLLA valid lease is still held. Wait instead of executing.
REPAIRThe durable record is incomplete but healable. Fix it and re-resolve. No second side effect.
SOFT_BLOCKRead-only UNKNOWN. Retry by default; mutating tools never use this gate.
HARD_BLOCKAmbiguous mutating transition. Stop. Reconcile if an external_operation_ref exists, else fail closed.
After a crash
Claim again.
Then ask the ledger.
The second attempt is not a new payment. It is a question: did the first one finish?
The answer comes from the same authoritative Python ledger whether the application uses Python directly or connects from TypeScript, Go, or another language through a self-hosted sidecar.
charge:ORD-42return · poll · repair · hard-blockcompleted ↳ stored result
ambiguous mutate ↳ hard-block
only if unrecoveredAdapter trust
Challenge the code
that answers “did it run?”
A false NOT_EXECUTED authorizes another attempt and can duplicate the side effect. The provider conformance kit tests lag, ambiguity, duplicate matches, malformed handles, false negatives, and forbidden writes before an adapter is trusted.
The signed report is synthetic and source-bound. It does not prove that a live provider token has read-only scopes. Gmail is the only adapter currently shipped; developers add a fixture for every other provider.
adapter verification
export MYCELIUM_ADAPTER_REPORT_SIGNING_KEY='from-your-secret-manager'
mycelium providers verify gmail \
--key-id provider-ci-2026-01 \
--output gmail-adapter-report.json
mycelium providers verify-report gmail-adapter-report.json
Python workflow recovery
Resume agent workflows
with Redis or PostgreSQL.
A workflow may finish one external action and crash before the next. Mycelium's @composite decorator supports recovery for bounded Python functions whose consequential child calls already use ledger or ledger_sync. Supported shapes include straight-line steps, one boolean branch, or one fixed-count loop.
Retry with the same host-owned operation ID. Completed child calls return stored results; previously unattempted children can execute. Ambiguous outcomes still require reconciliation or remain blocked.
A loop must be one top-level for index in range(N) with a literal count from 1 to 32. Each iteration has a distinct ledger identity; use a distinct provider idempotency key for each iteration too. File and SQLite storage support local recovery. Redis and PostgreSQL share parent leases, fences, and step evidence across workers. Variable-length or nested loops, combined branches and loops, hidden provider calls, and general workflow graphs remain outside the Python decorator's scope. The experimental HTTP sidecar offers a separate API for explicitly declared composite steps.
Set up durable composite recovery or read the Python API and recovery limits.
Next