.do
Execution

workflows

Multi-step process orchestration with automatic retries and state management

workflows

Workflows ARE Code Functions with triggers (every for time-based, on for event-based) and durable execution for multi-step business processes.

Overview

The workflows primitive is fundamentally a Code Function (see functions) enhanced with two critical features:

  1. Triggers - every (time-based) and on (event-based) for automatic execution
  2. Durable Execution - Automatic state persistence, retries, and error handling

This makes workflows perfect for orchestrating complex business processes that span multiple steps, services, and systems.

SDK Object Mapping

This primitive maps to the every and on SDK objects - two of the 8 core platform objects:

import { every, on, workflow, workflows } from 'sdk.do'

// EVERY - Schedule workflows (every is one of 8 core SDK objects)
every('daily at 9am', async () => {
  await workflow('daily-report', async () => {
    const data = await gatherData()
    const report = await generateReport(data)
    await sendReport(report)
  })
})

every('5 minutes', async () => {
  await workflow('health-check', async () => {
    await checkSystemHealth()
  })
})

// ON - Event-driven workflows (on is one of 8 core SDK objects)
on('order.created', async ({ order }) => {
  await workflow('process-order', async () => {
    await validateOrder(order)
    await chargePayment(order)
    await createShipment(order)
    await sendConfirmation(order)
  })
})

// Direct workflow definition
workflow('onboarding', async ({ user }) => {
  await send('welcome-email', { user })
  await createDefaultProject(user)
  await assignOnboardingTasks(user)
})

Subdomain Architecture

The workflows primitive uses infinite free subdomains for workflow types:

workflows.do                       # Root - Workflow orchestration
├── scheduled.workflows.do         # Scheduled workflows (via every)
├── event.workflows.do             # Event-driven workflows (via on)
├── manual.workflows.do            # Manual workflow execution
└── {custom}.workflows.do          # Custom workflow types

Durable Execution

What makes workflows different from regular code functions:

State Persistence

Workflow state is automatically persisted between steps, allowing long-running processes to survive restarts and failures.

workflow('process-order', async ({ order }) => {
  // Step 1: Validate (state persisted)
  await validateOrder(order)

  // If process crashes here, workflow resumes from step 2
  // Step 2: Process payment (state persisted)
  const payment = await processPayment(order)

  // Step 3: Create shipment (state persisted)
  await createShipment(order, payment)
})

Automatic Retries

Failed steps automatically retry with exponential backoff.

workflow('send-email', async ({ email }) => {
  // Automatically retries on failure
  await sendEmail(email) // Retries: 0s, 1s, 2s, 4s, 8s, 16s, 32s, 64s

  // Custom retry configuration
  await sendEmail(email, {
    retry: {
      maxAttempts: 5,
      backoff: 'exponential',
      maxDelay: { seconds: 60 },
    },
  })
})

Human-in-the-Loop

Workflows can wait indefinitely for human decisions.

workflow('approve-purchase', async ({ purchase }) => {
  // Validate purchase
  await validatePurchase(purchase)

  // Wait for human approval (workflow pauses here)
  const approval = await user.requestApproval({
    type: 'purchase-approval',
    data: { purchaseId: purchase.id },
    timeout: { hours: 48 },
  })

  if (approval.approved) {
    await processPurchase(purchase)
  }
})

Long-Running Processes

Workflows can run for days, weeks, or months.

workflow('employee-onboarding', async ({ employee }) => {
  // Day 1: Send welcome email
  await sendWelcomeEmail(employee)

  // Wait 7 days
  await sleep({ days: 7 })

  // Day 8: Schedule first review
  await scheduleReview(employee)

  // Wait 30 days
  await sleep({ days: 30 })

  // Day 38: Complete onboarding
  await completeOnboarding(employee)
})

Child Primitives

  • tasks - Task management within workflows

Quick Example

import { workflow } from 'sdk.do'

workflow('process-order', async ({ order }) => {
  await validateOrder(order)
  await chargePayment(order)
  await createShipment(order)
  await sendConfirmation(order)
  return { success: true }
})

await workflow.execute('process-order', { order: { id: '123' } })

Core Capabilities

  • Multi-Step - Coordinate complex processes
  • State Management - Automatic state persistence
  • Error Recovery - Automatic retries with backoff
  • Human Approvals - Wait for human decisions
  • Observability - Track progress and performance

Access Methods

SDK

TypeScript/JavaScript library for workflow definition

await workflow('process-order', async ({ order }) => {
  /* steps */
})

SDK Documentation

CLI

Command-line tool for workflow execution

do workflow execute process-order --input '{"order":{"id":"123"}}'

CLI Documentation

API

REST/RPC endpoints for workflow management

curl -X POST https://api.do/v1/workflows/process-order/execute -d '{"order":{"id":"123"}}'

API Documentation

MCP

Model Context Protocol for AI assistant integration

Execute workflow "process-order" with order id "123"

MCP Documentation

Parent Concept

  • functions - Workflows ARE code functions with triggers and durable execution

Child Primitives

  • tasks - Task management within workflows

SDK Object Mappings (Triggers)

  • every - Time-based workflow triggers (SDK object - 1 of 8 core)
  • on - Event-based workflow triggers (SDK object - 1 of 8 core)
  • agents - AI agent orchestration in workflows
  • events - Event system for triggering workflows
  • user - Human-in-the-loop workflow steps