Three implementation families
Vendors blur this. The difference determines your failure modes, so establish it first about any engine.
There are three genuinely different ways to make execution survive a crash, and knowing which one you are looking at tells you more than any feature list.
| Family | Mechanism | You pay in |
|---|---|---|
| Replay in a worker | Engine holds a history. A worker runs your function from the top, intercepting every engine call: matched events return recorded values, unmatched ones become real commands. | Determinism constraints your users must learn |
| Memoise + re-invoke | Each step executes as a separate HTTP request. Results are hashed by step ID, persisted, and injected on the next invocation. | A network round trip per step, state serialised in and out |
| Workflow as data | The workflow is a JSON state machine, not your code. No user code to replay, so determinism is not a user-facing concern. | Expressiveness — every real computation is an external call |
The replay family forbids a specific list, and it is worth memorising because violations are silent until a deploy: wall clock, random UUIDs, random numbers, any IO, environment variables, statics and globals, blocking sleeps, arbitrary async, threading. Two more that bite and are rarely documented: iteration order over unordered collections, and any dependency-injected value that varies by deploy.
A long-running agent loop on a replay-family engine dies abruptly after a few hundred turns, with an error about history rather than about the task. Why?
The rest of this lesson unlocks when you commit above.