Skip to content

Quick Start Guide

Installation

Install IdentityFlow using your preferred package manager.

First Workflow

Create your first workflow with step-by-step guidance.

Best Practices

Learn essential patterns for reliable workflows.

Install IdentityFlow using your preferred package manager:

Terminal window
npm i @identity-flow/sdk
  1. Create a new workflow file:

    import * as v from '@identity-flow/sdk/valibot';
    import { defineWorkflow } from '@identity-flow/sdk';
    // Define input schema
    const OrderSchema = v.object({
    orderId: v.string(),
    items: v.array(v.object({ productId: v.string(), quantity: v.number([v.positive()]) })),
    });
  2. Define the workflow with validation:

    export default defineWorkflow(
    'order-processing',
    {
    // Validate input against schema
    schema: OrderSchema,
    // Configure default retry policy
    retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' },
    },
    async (flow) => {
    // Workflow implementation
    },
    );
  3. Add workflow steps:

    // Validate order
    const validatedOrder = await flow.do('validate order', async () => {
    return validateOrder(flow.params);
    });
    // Process payment and check inventory in parallel
    const [payment, inventory] = await Promise.all([
    flow.do('process payment', async () => {
    return processPayment(validatedOrder);
    }),
    flow.do('check inventory', async () => {
    return checkInventory(validatedOrder.items);
    }),
    ]);
    // Fulfill order
    await flow.do('fulfill order', async () => {
    return fulfillOrder({ order: validatedOrder, payment, inventory });
    });
  4. Add error handling:

    try {
    await flow.do('process payment', async () => {
    return processPayment(validatedOrder);
    });
    } catch (error) {
    if (error.code === 'INSUFFICIENT_FUNDS') {
    throw new NonRetryableError(error);
    }
    throw error;
    }
  5. Return workflow result:

    return {
    orderId: validatedOrder.orderId,
    status: 'COMPLETED',
    payment: payment.id
    };

Here’s a complete workflow that processes orders:

import * as v from '@identity-flow/sdk/valibot';
import { NonRetryableError, defineWorkflow } from '@identity-flow/sdk';
// Input schema
const OrderSchema = v.object({
orderId: v.string(),
items: v.array(v.object({ productId: v.string(), quantity: v.number([v.positive()]) })),
});
// Result type
interface OrderResult {
orderId: string;
status: 'COMPLETED' | 'failed';
payment?: string;
}
export default defineWorkflow<typeof OrderSchema, OrderResult>(
'order-processing',
{ schema: OrderSchema, retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' } },
async (flow) => {
try {
// Validate order
const validatedOrder = await flow.do('validate order', async () => {
return validateOrder(flow.params);
});
// Process payment and check inventory in parallel
const [payment, inventory] = await Promise.all([
flow.do('process payment', async () => {
try {
return await processPayment(validatedOrder);
} catch (error) {
if (error.code === 'INSUFFICIENT_FUNDS') {
throw new NonRetryableError(error);
}
throw error;
}
}),
flow.do('check inventory', async () => {
return checkInventory(validatedOrder.items);
}),
]);
// Fulfill order
await flow.do('fulfill order', async () => {
return fulfillOrder({ order: validatedOrder, payment, inventory });
});
// Return success result
return { orderId: validatedOrder.orderId, status: 'COMPLETED', payment: payment.id };
} catch (error) {
// Return failure result
return { orderId: flow.params.orderId, status: 'failed' };
}
},
);
  1. Input Validation

    • Always validate workflow input using schemas
    • Define clear input and output types
    • Handle validation errors appropriately
  2. Error Handling

    • Configure retry policies for transient failures
    • Use NonRetryableError for permanent failures
    • Log errors with context for debugging
  3. Step Design

    • Keep steps focused and atomic
    • Use parallel execution for independent operations
    • Maintain idempotency for reliability