# Workflows in Mastra

Workflows are graph-based state machines that can execute complex sequences of operations. They provide a structured way to handle multi-step processes, parallel operations, and (soon) suspend-and-resume for human interactions.

Workflows are defined in a dedicated directory. The directory path is configured in your Mastra config file. When you use workflows with cloud observability providers, you can see the inputs and outputs of each step.

## Building a Workflow

Here's an simple example of a workflow that uses predefined tools to crawl a website, uses an LLM to structure the data, and then analyzes the sentiment of the content.

```ts filename="src/workflows/index.ts" showLineNumbers copy
import { Step, Workflow, Mastra } from "@mastra/core";
import { z } from "zod";
import { integrations } from "../../integrations";
import * as tools from "../../tools";
import * as syncs from "../../syncs";
import { PostgresEngine } from "@mastra/engine";

// Import your Mastra instance with registered tools and integrations
export const mastra = new Mastra<
  typeof integrations,
  typeof tools,
  typeof syncs
>({
  integrations,
  syncs,
  agents: [agentOne],
  tools,
  engine: new PostgresEngine({
    url: process.env.DB_URL!,
  }),
});

// Define steps
const crawlStep = new Step({
  id: "crawl",
  // Define the input schema for the step
  inputSchema: z.object({
    url: z.string().url(),
  }),
  // Define the output schema for the step
  outputSchema: z.object({
    rawText: z.string(),
  }),
  action: async ({ data, runId }) => {
    // Get the crawl tool from the Mastra instance
    const crawlTool = mastra.getTool("crawlWebpage");
    // Execute the tool with the input data
    const result = await crawlTool.execute({ url: data.url });
    // Return the result of the tool execution
    return { rawText: result.text };
  },
});

const structureStep = new Step({
  id: "structure",
  inputSchema: z.object({
    rawText: z.string(),
  }),
  outputSchema: z.object({
    reviews: z.array(z.string()),
  }),
  action: async ({ data, runId }) => {
    // Get the structure tool from the Mastra instance
    const structureTool = mastra.getTool("structureReviews");
    // Execute the tool with the input data
    const result = await structureTool.execute({ rawText: data.rawText });
    // Return the result of the tool execution
    return { reviews: result };
  },
});

// Define workflow
export const contentWorkflow = new Workflow({
  name: "content-review",
  triggerSchema: z.object({
    url: z.string().url(),
  }),
  steps: [crawlStep, structureStep],
});

contentWorkflow
  .step("crawl", {
    transitions: {
      structure: {
        condition: {
          ref: { stepId: "crawl", path: "rawText" },
          query: { $exists: true },
        },
      },
    },
  })
  .step("structure", {
    variables: {
      rawText: { stepId: "crawl", path: "rawText" },
    },
  })
  .commit();
```

### Execute the workflow

```ts filename="src/actions.ts" showLineNumbers copy
"use server";

import { contentWorkflow } from "./workflows";

export async function getReviews({ url }: { url: string }) {
  try {
    // Execute the workflow
    const { results, runId } = await contentWorkflow.execute({
      url,
    });

    return { results, runId };
  } catch (error) {
    console.error(error);
    return { error: "Failed to get reviews" };
  }
}
```

## Reference Documentation

More detailed documentation on transitions, conditions, variables, steps, and validation can be found in the reference docs:

- [Workflows](../reference/workflows/workflow.mdx)
- [Steps](../reference/workflows/step.mdx)
- [Transitions](../reference/workflows/transition.mdx)
