Mastra workflows have suspend/resume functionality enabling to wait for humans in the loop. That works in playground now!
Here’s a demo:
We also shipped an API for automatically closing streams when a workflow suspends, allowing them to be resumed later
resumeStream
The default behavior of suspend() is to leave the stream open. We shipped a closeOnSuspend option to close a stream automatically when a workflow suspends.
Now, when you’re ready to resume, use resumeStream to pick up your stream exactly where the workflow left off.
As an example:
// 1. Initial execution with closeOnSuspend enabled
const run = await workflow.createRunAsync();
const output = run.stream({
inputData: { task: "approval_needed" },
closeOnSuspend: true, // 🔑 Stream will close when workflow suspends
});
// Stream events until suspension
for await (const chunk of stream.fullStream) {
console.log(chunk.type, chunk.payload);
// Stream automatically closes when workflow suspends
}
const result = await stream.result;
console.log(result.status); // 'suspended'
// --- Time passes, user provides input ---
// 2. Resume and get a NEW stream for the continuation
const resumedOutput = await run.resumeStream({
resumeData: { userInput: "approved" },
step: "approval-step", // Optional - auto-detected if omitted
});
// Stream remaining events from the new stream
for await (const chunk of resumedStream.fullStream) {
console.log("Resumed:", chunk.type, chunk.payload);
}
const finalResult = await resumedStream.result;
console.log(finalResult.status); // 'success' or 'failed'We hope this helps you build more human-in-the-loop workflows in Mastra. Happy building! 🚀
