Workflow Definition
A template written in TypeScript using the SDK, describing the steps, logic, and rules of a specific process.
This guide will walk you through creating, configuring, and managing automated processes using the @identity-flow/sdk.
IdentityFlow provides a powerful, code-first engine for defining and executing complex business processes. At its core, it leverages several key principles:
@identity-flow/sdk. This gives you the full power and expressiveness of a familiar programming language to model complex logic.Workflow Definition
A template written in TypeScript using the SDK, describing the steps, logic, and rules of a specific process.
Workflow Instance
A single, live execution of a Workflow Definition, triggered with specific input parameters. Each instance has its own state and event history.
Steps / Activities
Individual units of work within a workflow (e.g., calling an API, waiting for input, running custom logic). They are atomic and can be retried independently.
Events
Immutable records representing every state change or action that occurs during a workflow instance’s lifecycle. This underpins event sourcing.
State
The current status of a workflow instance (e.g., ACTIVE, SLEEPING, PENDING, COMPLETED, FAILED).
To follow the guides, you should have:
http://localhost:4000/graphql for local development).Ready to build your first workflow? Let’s start with the Quick Start Guide!
A workflow is a series of steps executed in a specific order, defined as an async function.
import { defineWorkflow } from '@identity-flow/sdk';
export default defineWorkflow('order-processing', async (flow) => { // Step 1: Validate Order const validatedOrder = await flow.do('validate order', async () => { return validateOrder(flow.params); });
// Step 2: Process Payment const payment = await flow.do('process payment', async () => { return processPayment(validatedOrder); });
// Step 3: Fulfill Order await flow.do('fulfill order', async () => { return fulfillOrder(payment); });});export default defineWorkflow( 'payment-processing', { retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' }, timeout: '5 minutes' }, async (flow) => { await flow.do('process payment', async () => { return processPayment(flow.params); }); },);Steps are atomic units of work within a workflow that can be retried independently.
Atomic Operations
Each step performs a single, cohesive unit of work.
Independent Retries
Steps can be retried individually on failure.
State Management
Steps maintain state through their return values.
await flow.do( 'process payment', { // Retry configuration retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' },
// Maximum execution time timeout: '5 minutes',
// Unique key for idempotency idempotencyKey: orderId,
// Step-level validation schema: PaymentSchema, }, async () => { return processPayment(flow.params); },);All state changes are recorded as events, providing transparency and audit trails.
export default defineWorkflow('document-approval', async (flow) => { // Each action creates an event await flow.do('submit document', async () => { await submitDocument(flow.params); // Event: DocumentSubmitted });
await flow.do('request approval', async () => { await requestApproval(flow.params); // Event: ApprovalRequested });});// Events can be replayed to reconstruct stateconst events = await getWorkflowEvents(workflowId);const state = events.reduce((state, event) => { switch (event.type) { case 'DocumentSubmitted': return { ...state, submitted: true }; case 'ApprovalRequested': return { ...state, approvalPending: true }; default: return state; }}, {});For more details, see the Event Sourcing feature page.
Given the same input, workflows always execute the same way. This ensures predictable outcomes and reliable replay for debugging.
export default defineWorkflow('order-processing', async (flow) => { // Given the same input, this will always execute the same way const validationResult = await flow.do('validate order', async () => { return await validateOrder(flow.params); });
// Conditional paths are predictable based on input if (validationResult.approved) { await flow.do('process order', async () => { await processOrder(flow.params); }); } else { await flow.do('reject order', async () => { await rejectOrder(flow.params, validationResult.reason); }); }});For more details, see the Deterministic Execution feature page.
Continue your learning journey: