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>:
Marker tag used internally to identify workflow definitions.
execute
(input: Input) => Effect<Output, Error | PauseSignal | StorageError, Requirements>
The wrapped execution function. Called by the engine — do not invoke directly.
Type witness for the input type. Used for inference only; has no runtime value.
Type witness for the output type. Used for inference only; has no runtime value.
Type witness for the error type. Used for inference only; has no runtime value.
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 ),
});
})
);
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)