Blog

Introducing vNext Workflows: the next generation of Mastra Workflows

In case you missed it in our changelog from last week, we’ve given workflows a major overhaul based on user feedback. On Wednesday we released vNext workflows in alpha; today, we’re releasing vNext in stable (0.10.0).

While people really appreciated the fluent workflow syntax, they had two issues.

First, it was too difficult to reason about and manage complex control flows.

Second, many users had existing workflow engines like Temporal or Inngest they wanted to integrate with.

So today, we’re excited to share vNext: a better, faster, stronger version of Mastra workflows. (We’d have started that with “harder”, but in this case it’s actually easier.)

What we’ve changed: better control flow, stronger type safety, and multi-engine support

vNext will feature several improvements that largely address 3 big needs: stronger control flow, better type safety, and multi-engine support.

Here’s a code sample that shows the new syntax:

workflow
  .then(fetchWeather)
  .branch([
    // could use .parallel()
    [
      async ({ inputData }) => {
        return inputData?.rainChance > 0.5;
      }, // conditional
      planIndoorActivities, // step or workflow
    ],
    [
      async ({ inputData }) => {
        return inputData?.rainChance <= 0.5;
      },
      planActivities, // step or workflow
    ],
  ])
  .commit();

Control flow

Here are some of the biggest improvements we’ve made around control flows:

  • Nested Workflows are now first-class citizens and the first primitive to reach for when composing any nested control flows or circular execution structures
  • Looping (while or until) accepts a single Step or Workflow and repeats until conditions are met
  • .branch() replaces if/else, providing clearer conditional paths. Each truthy condition executes in parallel. And .parallel() for condition-less parallel execution path branching.
    • Branching creates a visual mental model of forking paths in a tree, which accurately represents workflow conditions
  • .then() is now the universal connector (.step() has been retired)
  • Mastra primitives, like agents and tools, can be transformed to workflow steps using createStep()
  • We no longer have the .after() command; users reported the loop-back syntax was hard to reason about. Now, in vNext, branching and dependencies are encapsulated in child workflows and explicit control flow changes.

Type safety

Here are some of the biggest improvements we’ve made around type safety:

  • All steps require input and output schemas
  • A step's input is:
    • For the first step: the input provided to the workflow
    • For subsequent steps: the output of the previous step
  • Parallel and branching operations return a union of the step results { [stepId]: output }
  • Workflow outputs are defined as the final executed step's output
  • You can pass a resumeSchema argument for type safety when resuming a step
    • The payload is passed into the execute function as resumeData
    • Makes it easier to identify when a step is being resumed
    • Helps separate inputs from previous steps and the resume context

Multi-engine workflows

Besides having access to Mastra’s native, built-in workflows, soon you’ll also be able to swap-in other workflow engines — all while using the same top-level Mastra syntax.

Many users came to Mastra with pre-existing workflows built on external engines. We’ve made it easy to plug those right into your projects or even switch between engines to see which works best.

Transitioning to vNext workflows

Next week, we’ll be switching over to vNext during our next official release on May 6th, 2025. That means importing from @mastra/core/workflows will give you the vNext workflows.

If you’re using the legacy workflow system, and you want to upgrade Mastra versions but you’re not yet ready to switch over, you can use the legacy import and prefix, eg:

import { Step, Workflow } from '@mastra/core/workflows/legacy'
import { Mastra } from '@mastra/core/mastra'
const step1 = new Step(...)
const workflow = new Workflow(...).step(step1).commit();

const mastra = new Mastra({
  // registering legacy workflows
  legacy_workflows: {
    myWorkflow: workflow
  }
})

// accessing the workflow through the mastra class:
mastra.legacy_getWorkflow('myWorkflow')

What’s Next

We’ll be working with counterpart teams over vNext will support TemporalInngest, and Cloudflare workers. We plan to add additional engines in the future.

We’re excited to see how vNext helps you build better workflows. Do share any sample projects and demos with us on Discord. And ping us anytime if you need help with the transition.

Share

Stay up to date