DocsWorkflowsOverview

Handling Complex LLM Operations with Workflows

Workflows in Mastra help you orchestrate complex sequences of operations with features like branching, parallel execution, resource suspension, and more.

When to use workflows

Most AI applications need more than a single call to a language model. You may want to run multiple steps, conditionally skip certain paths, or even pause execution altogether until you receive user input. Sometimes your agent tool calling is not accurate enough.

Mastra’s workflow system provides:

  • A standardized way to define steps and link them together.
  • Support for both simple (linear) and advanced (branching, parallel) paths.
  • Debugging and observability features to track each workflow run.

Example

To create a workflow, you define one or more steps, link them, and then commit the workflow before starting it.

Breaking Down the Workflow

Let’s examine each part of the workflow creation process:

1. Creating the Workflow

Here’s how you define a workflow in Mastra. The name field determines the workflow’s API endpoint (/workflows/$NAME/), while the triggerSchema defines the structure of the workflow’s trigger data:

src/mastra/workflow/index.ts
const myWorkflow = new Workflow({
  name: 'my-workflow',
  triggerSchema: z.object({
    inputValue: z.number(),
  }),
});

2. Defining Steps

Now, we’ll define the workflow’s steps. Each step can have its own input and output schemas. Here, stepOne doubles an input value, and stepTwo increments that result if stepOne was successful. (To keep things simple, we aren’t making any LLM calls in this example):

src/mastra/workflow/index.ts
const stepOne = new Step({
  id: 'stepOne',
  outputSchema: z.object({
    doubledValue: z.number(),
  }),
  execute: async ({ context }) => {
    const doubledValue = context.triggerData.inputValue * 2;
    return { doubledValue };
  },
});
 
const stepTwo = new Step({
  id: "stepTwo",
  execute: async ({ context }) => {
    if (context.steps.stepOne.status !== "success") {
      return { incrementedValue: 0 };
    }
    return {
      incrementedValue: context.steps.stepOne.output.doubledValue + 1,
    };
  },
});

3. Linking Steps

Now, let’s create the control flow, and “commit” (finalize the workflow). In this case, stepOne runs first and is followed by stepTwo.

src/mastra/workflow/index.ts
myWorkflow
  .step(stepOne)
  .then(stepTwo)
  .commit();

Register the Workflow

Register your workflow with Mastra to enable logging and telemetry:

src/mastra/index.ts
import { Mastra } from "@mastra/core";
 
export const mastra = new Mastra({
  workflows: { myWorkflow },
});

Executing the Workflow

Execute your workflow programmatically or via API:

src/mastra/run-workflow.ts
import { mastra } from "./index";
 
// Get the workflow
const myWorkflow = mastra.getWorkflow('myWorkflow');
const { runId, start } = myWorkflow.createRun();
 
// Start the workflow execution
await start({ triggerData: { inputValue: 45 } });

Or use the API (requires running mastra dev):

curl --location 'http://localhost:4111/api/workflows/myWorkflow/execute' \
     --header 'Content-Type: application/json' \
     --data '{
       "triggerData": {
         "inputValue": 45
       }
     }'

This example shows the essentials: define your workflow, add steps, commit the workflow, then execute it.

Defining Steps

The basic building block of a workflow is a step. Steps are defined using schemas for inputs and outputs, and can fetch prior step results.

Control Flow

Workflows let you define a control flow to chain steps together in with parallel steps, branching paths, and more.

Suspend and Resume

When you need to pause execution for external data, user input, or asynchronous events, Mastra supports suspension at any step, persisting the state of the workflow so you can resume it later.

Observability and Debugging

Mastra workflows automatically log the input and output of each step within a workflow run, allowing you to send this data to your preferred logging, telemetry, or observability tools.

You can:

  • Track the status of each step (e.g., success, error, or suspended).
  • Store run-specific metadata for analysis.
  • Integrate with third-party observability platforms like Datadog or New Relic by forwarding logs.

More Resources