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 Reference​

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 Methods​

step()​

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

commit()​

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

execute()​

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

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

Validation​

Workflow validation happens at two key times:

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 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 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 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 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 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