Core Concepts
Invariant is built on eight foundational building blocks. Understanding these concepts will help you build reliable, event-sourced AI applications that scale without infrastructure brittleness.
1. workflow
A Workflow is a compiled, directed acyclic or looping graph that defines a business process or AI agent pipeline.
- Immutability: Workflows compile down to an Invariant IR (Intermediate Representation) JSON schema v2.1. Once compiled, workflow logic cannot mutate mid-flight.
- Identifiable: Identified by a unique string name (e.g.,
"customer-onboarding").
2. .step() (Deterministic Transformation)
A .step() represents pure, deterministic data manipulation.
- Semantics: Must be pure functions (transforming state or input).
- Execution Boundary: Evaluated directly in memory during
ExecutionEngine.transition(). - Constraint: Zero I/O allowed. No network calls, no database mutations, no random numbers or system clocks.
- Replay Safety: Because
.step()is pure, it can be re-evaluated 1,000 times during event log replay without side effects.
workflow.step("calculate-total", async ({ state }) => {
const subtotal = state.items.reduce((sum, item) => sum + item.price, 0);
const tax = subtotal * 0.08;
return { total: subtotal + tax };
});3. .reason() (Probabilistic AI Boundary)
A .reason() step delegates a decision or structured generation to an LLM.
- Semantics: Probabilistic computation.
- Execution Boundary: The runtime emits a
ReasonCommand. The LLM is invoked outside the state machine, and its structured JSON output re-enters as a durableCAPABILITY_COMPLETEDevent. - Schema Validation: Outputs are strictly validated against a Zod / TypeBox schema before state reduction occurs.
workflow.reason("classify-sentiment", {
prompt: ({ state }) => `Analyze customer message: "${state.userMessage}"`,
schema: z.object({
sentiment: z.enum(["POSITIVE", "NEUTRAL", "NEGATIVE"]),
urgencyScore: z.number().min(1).max(5),
}),
});4. .capability() (Durable Side Effect Boundary)
A .capability() executes external I/O (Stripe API, SendGrid emails, SQL writes, vector searches, MCP tools).
- Semantics: Imperative side effect crossing an execution boundary.
- Execution Boundary: Transactional Outbox. Commands are written to
workflow_outboxin the exact same DB transaction as the state update. - Idempotency: Every capability specifies an
idempotencyKeyformula (execution.id + step.id) to guarantee at-least-once execution safety.
workflow.capability("send-slack-alert", {
idempotencyKey: ({ execution }) => `slack-alert:${execution.id}`,
handler: async ({ state }) => {
return await slack.postMessage({
channel: "#vip-alerts",
text: `VIP User ${state.userId} requested assistance.`,
});
},
});5. .wait() (Durable Suspension)
A .wait() step pauses workflow execution until an external condition or RuntimeEvent is received.
- Semantics: Durable suspension boundary.
- Execution Boundary: The engine sets run status to
'suspended'and releases all memory and CPU resources. - Resume Mechanism: Re-activated when an external event (webhook, user action, timer) matches the wait condition.
workflow.wait("await-approval", {
timeout: "48h", // Auto-triggers TIMER_FIRED if timeout expires
});6. RuntimeEvent
An immutable record of something that happened in the world.
- Durable Event Log: Events are appended sequentially with a monotonic integer
seqper workflow run. - Public Domain Events: Examples include
RUN_CREATED,INPUT_RECEIVED,CAPABILITY_COMPLETED,CAPABILITY_FAILED,TIMER_FIRED. - Note:
RuntimeEvents are distinct from internal reducer operations (SET,MERGE,DELETE).
7. ExecutionState
The complete, accumulated state of a workflow run at a specific revision.
- Derived: State is not arbitrarily edited; it is derived by reducing
RuntimeEvents sequentially throughstate-reducer.ts. - Versioned: Every state commit increments
revisionmonotonically (revision = expectedRevision + 1).
8. Execution (Workflow Run)
An active or completed instance of a workflow.
- Run ID: Unique UUID (
runId) identifying the single execution instance. - Lease Managed: Controlled by
LeaseStore(worker_id,lease_expires_at) to guarantee single-worker concurrency and crash recovery.