Suspend and Resume in Workflows
Complex workflows often need to pause execution while waiting for external input or resources.
Mastra’s suspend and resume features let you pause workflow execution at any step, persist the workflow snapshot to storage, and resume execution from the saved snapshot when ready. This entire process is automatically managed by Mastra. No config needed, or manual step required from the user.
Storing the workflow snapshot to storage means that the workflow state is permanently preserved across sessions, deployments, and server restarts. This persistence is crucial for workflows that might remain suspended for minutes, hours, or even days while waiting for external input or resources.
When to Use Suspend/Resume
Common scenarios for suspending workflows include:
- Waiting for human approval or input
- Pausing until external API resources become available
- Collecting additional data needed for later steps
- Rate limiting or throttling expensive operations
- Handling event-driven processes with external triggers
How to suspend a step
// Create a step that handles human input with suspend/resume capabilities
const humanInputStep = createStep({
id: "human-input",
inputSchema: z.object({
suggestions: z.array(z.string()),
vacationDescription: z.string(),
}),
// Define the structure of data needed to resume the step
resumeSchema: z.object({
selection: z.string(),
}),
// Define the structure of data when suspending (empty in this case)
suspendSchema: z.object({}),
outputSchema: z.object({
selection: z.string().describe("The selection of the user"),
vacationDescription: z.string(),
}),
execute: async ({ inputData, resumeData, suspend }) => {
// If no resume data is provided, suspend the step and wait for user input
if (!resumeData?.selection) {
await suspend({});
return {
selection: "",
vacationDescription: inputData?.vacationDescription,
};
}
return {
selection: resumeData.selection,
vacationDescription: inputData?.vacationDescription,
};
},
});
How to resume step execution
Identifying suspended state
When running a workflow, its state can be one of the following:
running
- The workflow is currently runningsuspended
- The workflow is suspendedsuccess
- The workflow has completedfailed
- The workflow has failed
When the state is suspended
, you can identify any and all steps that have been suspended by looking at the suspended
property of the workflow.
const run = counterWorkflow.createRun();
const result = await run.start({ inputData: { startValue: 0 } });
// Check if the workflow is in suspended state
if (result.status === "suspended") {
// Resume the first suspended step with new data
const resumedResults = await run.resume({
step: result.suspended[0],
resumeData: { newValue: 0 },
});
}
In this case, the logic resumes whatever is the first step reported as suspended.
The suspended
property is of type string[][]
, where every array is a path to a step that has been suspended, the first element being the step id on the main workflow. If that step is a workflow itself, the second element is the step id on the nested workflow that was suspended, unless it is a workflow itself, in which case the third element is the step id on the nested workflow that was suspended, and so on.
Resume
// Resume a suspended workflow with user input
const result = await workflowRun.resume({
step: userInputStep, // or 'myStepId' as a string
resumeData: {
userSelection: "User's choice",
},
});
To resume a suspended nested workflow:
// Resume a suspended nested workflow with user input
const result = await workflowRun.resume({
step: [nestedWorkflow, userInputStep], // or ['nestedWorkflowId', 'myStepId'] as a string array
resumeData: {
userSelection: "User's choice",
},
});