Lifecycle, Pause/Resume, and Save/Load
Visualization boundary: the state machine explains runtime semantics; exported config still requires named handlers and conditions.
1. Execution state machine
How to read this diagram
cancelledalready exists as an explicit status constant, but there is no publiccancel()API yet.waitingmeans “waiting for an external continuation”, not a blocked thread.
2. start() vs start_execution()
flow.start(...)good for directly waiting for a resultflow.start_execution(..., wait_for_result=False)better for long-lived executions
3. Pause, save, restore, continue
Design rationale
save()/load()restore workflow semantics, not the Python coroutine stack.- The reliable recovery pattern is always “pause, persist, wait, continue with an external event”.
4. Interrupts and resume
python
interrupt = await data.async_pause_for(
type="human_input",
payload={"question": "approve?"},
resume_event="UserFeedback",
)Later you can use:
get_interrupt(interrupt_id)get_pending_interrupts()continue_with(interrupt_id, value)
to resume execution.
5. What save() stores
save() stores:
execution_idstatusruntime_dataflow_datainterruptslast_signalresource_keysresult
It does not store:
- runtime dependency objects themselves
- the Python coroutine stack
6. get_last_signal()
last_signal records the most recently dispatched signal and is useful for:
- debugging
- auditing
- locating the resume point after
save()/load()
7. Best practices
- prefer
start_execution(..., wait_for_result=False)for long tasks - prefer
pause_for()over busy loops when waiting for outside input - keep recoverable state in
stateand runtime dependencies inresources