Skip to content

Execution Model

Invariant execution is a durable, event-driven loop.

External input enters as a durable event. The Runtime derives current state, evaluates the next transition, atomically persists the result and outbox intents, then waits for external work results to re-enter as durable events.


The Fundamental Execution Loop

The diagram below illustrates the strict boundary between the Durable Storage Transaction and the External World:

text
                Durable Storage Boundary
┌────────────────────────────────────────────────────────┐
│                                                        │
│  Runtime Event (Webhook / Input / Timer)               │
│       │                                                │
│  Load & Reduce State                                   │
│       │                                                │
│  Evaluate Transition (Pure Function)                   │
│       │                                                │
│  Atomic Storage Commit                                 │
│   ├── State Update                                     │
│   ├── Emitted Events                                   │
│   └── Outbox Intents                                   │
│                                                        │
└───────────────────────────┬────────────────────────────┘


                     Outbox Worker


                     External Systems
                  (Stripe / LLM / APIs)


                     Result Event

                            └────────────────↺

Core Boundary Principle: External systems and AI models never mutate the workflow state machine directly. Every external output re-enters the state machine as a durable event.


Detailed Execution Phases

Phase 1: Event Arrival

External signals (API requests, user messages, webhooks, or timer expirations) enter the system as RuntimeEvents. The storage layer appends them to the execution event stream with gapless sequence numbers (seq = 1, 2, 3...).

Phase 2: State Materialization

The Runtime reads the ordered event stream or loads the latest state snapshot. The state reducer computes the exact current state of the workflow execution in memory.

Phase 3: Transition Evaluation

The execution kernel (ExecutionEngine.transition()) evaluates the compiled workflow graph against the current state and incoming event. This evaluation is a pure function—it computes state mutations, emitted events, and capability intents without performing network I/O or mutating global variables.

Phase 4: Atomic Storage Commit

The Runtime atomically commits three artifacts within a single storage transaction:

  1. Materialized State Update (The new execution status and payload)
  2. Emitted Events (e.g. STEP_COMPLETED, EXECUTION_SUSPENDED)
  3. Outbox Intents (Requests for external side-effects or model evaluations)

If the database or worker crashes during this step, the transaction rolls back cleanly without leaving orphan states or lost intents.

Phase 5: Outbox Dispatch

An independent Outbox Worker polls committed intents from durable storage and dispatches them asynchronously. This separates database transaction commits from external network latency or API failures.

Phase 6: Event Re-entry

When an external capability finishes executing or a model finishes generating a response, the outbox worker writes the result back into storage as a new durable event (CAPABILITY_COMPLETED, REASON_COMPLETED). This triggers the next turn of the execution loop.


How Primitives Map to Engine Semantics

The authoring primitives in Invariant (.step(), .reason(), .capability(), .wait()) map directly to distinct execution engine behaviors:

text
.step()

Evaluated synchronously inside the transition boundary.
Result immediately becomes part of the committed state update.

.reason()

Runtime emits a model work intent.
LLM executes outside the transition boundary.
Structured result re-enters as a durable REASON_COMPLETED event.

.capability()

Runtime emits an outbox capability intent.
Outbox worker executes the external effect with an idempotency key.
Result re-enters as a durable CAPABILITY_COMPLETED event.

.wait()

Execution enters a suspended state (`waiting`).
The storage lock & worker lease drop cleanly.
Execution resumes only when external input arrives as a durable event.

Storage Layer Abstraction

The Runtime atomically commits state updates, generated events, and outbox intents through a storage adapter interface.

To see how the PostgreSQL adapter implements row-level locking (FOR UPDATE), optimistic lease expiration, and outbox table polling, inspect the PostgreSQL Adapter.


Go Deeper

Invariant Durable Execution Engine.