Skip to main content

Workflow Class

The Workflow class enables you to create state machines for complex sequences of operations with conditional branching and data validation.

import { LegacyWorkflow } from "@mastra/core/workflows/legacy";

const workflow = new LegacyWorkflow({ name: "my-workflow" });

API ReferenceDirect link to API Reference

ConstructorDirect link to Constructor

name:

string
Identifier for the workflow

logger?:

Logger<WorkflowLogMessage>
Optional logger instance for workflow execution details

steps:

Step[]
Array of steps to include in the workflow

triggerSchema:

z.Schema
Optional schema for validating workflow trigger data

Core MethodsDirect link to Core Methods

step()Direct link to step

Adds a Step to the workflow, including transitions to other steps. Returns the workflow instance for chaining. Learn more about steps.

commit()Direct link to commit

Validates and finalizes the workflow configuration. Must be called after adding all steps.

execute()Direct link to execute

Executes the workflow with optional trigger data. Typed based on the trigger schema.

Trigger SchemasDirect link to Trigger Schemas

Trigger schemas validate the initial data passed to a workflow using Zod.

const workflow = new LegacyWorkflow({
name: "order-process",
triggerSchema: z.object({
orderId: z.string(),
customer: z.object({
id: z.string(),
email: z.string().email(),
}),
}),
});

The schema:

  • Validates data passed to execute()
  • Provides TypeScript types for your workflow input

ValidationDirect link to Validation

Workflow validation happens at two key times:

1. At Commit TimeDirect link to 1. At Commit Time

When you call .commit(), the workflow validates:

workflow
.step('step1', {...})
.step('step2', {...})
.commit(); // Validates workflow structure
  • Circular dependencies between steps
  • Terminal paths (every path must end)
  • Unreachable steps
  • Variable references to non-existent steps
  • Duplicate step IDs

2. During ExecutionDirect link to 2. During Execution

When you call start(), it validates:

const { runId, start } = workflow.createRun();

// Validates trigger data against schema
await start({
triggerData: {
orderId: "123",
customer: {
id: "cust_123",
email: "invalid-email", // Will fail validation
},
},
});
  • Trigger data against trigger schema
  • Each step's input data against its inputSchema
  • Variable paths exist in referenced step outputs
  • Required variables are present

Workflow StatusDirect link to Workflow Status

A workflow's status indicates its current execution state. The possible values are:

CREATED:

string
Workflow instance has been created but not started

RUNNING:

string
Workflow is actively executing steps

SUSPENDED:

string
Workflow execution is paused waiting for resume

COMPLETED:

string
All steps finished executing successfully

FAILED:

string
Workflow encountered an error during execution

Example: Handling Different StatusesDirect link to Example: Handling Different Statuses

const { runId, start, watch } = workflow.createRun();

watch(async ({ status }) => {
switch (status) {
case "SUSPENDED":
// Handle suspended state
break;
case "COMPLETED":
// Process results
break;
case "FAILED":
// Handle error state
break;
}
});

await start({ triggerData: data });

Error HandlingDirect link to Error Handling

try {
const { runId, start, watch, resume } = workflow.createRun();
await start({ triggerData: data });
} catch (error) {
if (error instanceof ValidationError) {
// Handle validation errors
console.log(error.type); // 'circular_dependency' | 'no_terminal_path' | 'unreachable_step'
console.log(error.details); // { stepId?: string, path?: string[] }
}
}

Passing Context Between StepsDirect link to Passing Context Between Steps

Steps can access data from previous steps in the workflow through the context object. Each step receives the accumulated context from all previous steps that have executed.

workflow
.step({
id: "getData",
execute: async ({ context }) => {
return {
data: { id: "123", value: "example" },
};
},
})
.step({
id: "processData",
execute: async ({ context }) => {
// Access data from previous step through context.steps
const previousData = context.steps.getData.output.data;
// Process previousData.id and previousData.value
},
});

The context object:

  • Contains results from all completed steps in context.steps
  • Provides access to step outputs through context.steps.[stepId].output
  • Is typed based on step output schemas
  • Is immutable to ensure data consistency