Skip to main content
Workflow.make creates a WorkflowDefinition — the typed container for your workflow’s execution logic. The workflow is registered by name when passed to createDurableWorkflows, not inside the definition itself.

Signature

function make<Input, Output, Error, Requirements>(
  execute: (input: Input) => Effect.Effect<Output, Error, Requirements>
): WorkflowDefinition<Input, Output, Error, Requirements>

Parameters

execute
(input: I) => Effect<O, E, R>
required
The workflow logic function. Receives the workflow input and returns an Effect containing all the workflow steps, sleeps, and business logic. The Effect’s type parameters become the type parameters of the returned WorkflowDefinition.

Return type

Workflow.make returns a WorkflowDefinition<Input, Output, Error, Requirements>:
WorkflowDefinition
object
The workflow name is determined by the registry key you provide to createDurableWorkflows, not by anything inside the definition. This avoids name duplication.

Examples

Basic order workflow

import { Effect } from "effect";
import { Workflow } from "@durable-effect/workflow";

const processOrderWorkflow = Workflow.make((orderId: string) =>
  Effect.gen(function* () {
    const order = yield* Workflow.step({
      name: "Fetch order",
      execute: fetchOrder(orderId),
    });

    yield* Workflow.sleep("5 seconds");

    yield* Workflow.step({
      name: "Process order",
      execute: processOrder(order),
    });

    yield* Workflow.step({
      name: "Send confirmation",
      execute: sendEmail(order.email),
    });
  })
);

Workflow with object input

import { Effect } from "effect";
import { Workflow } from "@durable-effect/workflow";

const subscriptionWorkflow = Workflow.make(
  (input: { userId: string; plan: string }) =>
    Effect.gen(function* () {
      yield* Workflow.step({
        name: "Provision account",
        execute: provisionAccount(input.userId, input.plan),
      });

      // Sleep for 30 days before renewal
      yield* Workflow.sleep("30 days");

      yield* Workflow.step({
        name: "Renew subscription",
        execute: renewSubscription(input.userId),
      });
    })
);

Registering workflows

The registry key becomes the workflow name. Pass the registry to createDurableWorkflows:
import { createDurableWorkflows, Workflow } from "@durable-effect/workflow";
import { Effect } from "effect";

const workflows = {
  processOrder: processOrderWorkflow,
  subscription: subscriptionWorkflow,
} as const;

export const { Workflows, WorkflowClient } = createDurableWorkflows(workflows);

Workflow returning a value

const reportWorkflow = Workflow.make((reportId: string) =>
  Effect.gen(function* () {
    const data = yield* Workflow.step({
      name: "Fetch data",
      execute: fetchReportData(reportId),
    });

    const processed = yield* Workflow.step({
      name: "Process data",
      execute: processData(data),
    });

    return { reportId, rowCount: processed.length };
  })
);

Type utilities

Three utility types extract type information from a WorkflowDefinition:
import type {
  WorkflowInput,
  WorkflowOutput,
  WorkflowError,
  WorkflowRequirements,
} from "@durable-effect/workflow";

type OrderInput = WorkflowInput<typeof processOrderWorkflow>;
// string

type OrderOutput = WorkflowOutput<typeof processOrderWorkflow>;
// void

type OrderError = WorkflowError<typeof processOrderWorkflow>;
// never (or your typed errors)

Build docs developers (and LLMs) love