Workik.

Mastra Tutorial for Beginners: Build AI Agents in TypeScript

Building Mastra Workflows

Build Mastra workflows with createWorkflow and createStep. Chain steps with .then, run them in parallel, branch on conditions, and start runs.

Learn how to build deterministic, multi-step business pipelines in Mastra using steps, chains, parallel branches, and workflow runs.

Previous lesson: Structured Output with Mastra | Next lesson: Using Agents and Tools Inside Mastra Workflows


Understanding Workflows in Mastra

An AI agent decides its own path dynamically by selecting tools in a loop. A workflow, by contrast, follows a fixed sequence of steps that you specify in advance.

Think of a workflow like an assembly line in a factory. Raw materials enter at one end, pass through dedicated stations in an exact order, and emerge as a finished product. Every station performs a precise task, validates the materials it receives, and passes its output to the next station.

Workflows give you complete predictability for business operations such as ticket triage, payment processing, and customer onboarding. You get schema validation at every transition, full execution traces, and built-in error handling.

Mastra workflows are directed graphs composed of steps. You can run steps in series, trigger multiple steps in parallel, or branch down conditional paths based on runtime data.


Defining Steps with createStep

A step is the fundamental building block of any Mastra workflow. Every step is an isolated unit of execution created using the createStep function from @mastra/core/workflows.

To build a valid step, you must supply four properties:

  1. id: A unique string identifier.
  2. inputSchema: A Zod schema validating incoming data.
  3. outputSchema: A Zod schema validating outgoing data.
  4. execute: An asynchronous function that receives an object containing inputData and returns the output matching outputSchema.

In the next section you will write three steps for the support ticket pipeline: one that cleans up the message, one that classifies it, and one that formats the final ticket. Each step's outputSchema must match the next step's inputSchema.

Common Mistake: Forgetting to match the output schema of one step with the input schema of the next step. Mastra validates data schemas between transitions. If step A returns an object that step B cannot parse, the workflow halts with a validation error.


Chaining Steps with createWorkflow, .then, and .commit

You chain steps together by calling createWorkflow. You define the overall workflow input and output schemas, attach steps using the .then method, and finish the definition by calling .commit.

Create the file src/mastra/workflows/ticket-workflow.ts and add the following complete implementation:

ts
Copy

Pro Tip: Always call .commit() at the very end of your workflow builder chain. Omitting .commit() leaves the workflow in a mutable drafting state, which prevents Mastra from compiling its execution graph.


Branching and Parallel Execution

Real-world support pipelines frequently need to perform multiple checks at the same time or make conditional routing choices.

Running Steps in Parallel

Use .parallel to run two or more steps concurrently. When steps run in parallel, the step that immediately follows receives an object containing the outputs of all parallel steps keyed by their individual step IDs.

ts
Copy

Conditional Branching

When you need conditional logic, use .branch. The .branch method accepts an array of tuples. Each tuple contains a condition predicate function and the destination step.

ts
Copy

After .branch(), the next step receives an object keyed by the id of the step that ran, for example { "manual-review": { "action": "..." } }. Only the branch that ran appears in that object. The .map() call turns it back into a flat { action } object so it matches the workflow outputSchema.


Executing Workflows with createRun and start

Once registered on the main Mastra instance, you run a workflow programmatically by creating a run instance and calling start.

Register the workflow in src/mastra/index.ts, next to the support agent you already registered:

ts
Copy

Create a script named run-workflow.ts at the root of your project to test execution:

ts
Copy

Run this file with tsx:

bash
Copy

Your terminal outputs the formatted ticket summary and the team route produced by the sequence of steps. You can also view this execution visually by opening Mastra Studio at http://localhost:4111. Studio tracks step execution times, input payloads, and outputs.

Quick Challenge: Open Mastra Studio at http://localhost:4111 while running your dev server. Locate ticket-workflow under the Workflows tab, enter a test JSON payload containing { "message": "My item arrived damaged" }, and inspect each step in the visual run graph.

Try This: Add a fourth step to ticketWorkflow named log-audit. Have it accept the output from formatTicket, record a timestamp using new Date().toISOString(), and return { ticketSummary: string, routeTo: string, loggedAt: string }. Update the workflow output schema accordingly.


In the next lesson, Using Agents and Tools Inside Mastra Workflows, you will integrate the support agent and order status tool directly into workflow steps using mastra.getAgent, createStep(agent), and .map.

Was this lesson helpful?