# Data Mapping with Workflow Variables (Legacy)
[EN] Source: https://mastra.ai/examples/workflows_legacy/workflow-variables

This example demonstrates how to use workflow variables to map data between steps in a Mastra workflow.

## Use Case: User Registration Process

In this example, we'll build a simple user registration workflow that:

1. Validates user input
1. Formats the user data
1. Creates a user profile

## Implementation

```typescript showLineNumbers title="src/mastra/workflows/user-registration.ts" copy
import { LegacyStep, LegacyWorkflow } from "@mastra/core/workflows/legacy";
import { z } from "zod";

// Define our schemas for better type safety
const userInputSchema = z.object({
  email: z.string().email(),
  name: z.string(),
  age: z.number().min(18),
});

const validatedDataSchema = z.object({
  isValid: z.boolean(),
  validatedData: z.object({
    email: z.string(),
    name: z.string(),
    age: z.number(),
  }),
});

const formattedDataSchema = z.object({
  userId: z.string(),
  formattedData: z.object({
    email: z.string(),
    displayName: z.string(),
    ageGroup: z.string(),
  }),
});

const profileSchema = z.object({
  profile: z.object({
    id: z.string(),
    email: z.string(),
    displayName: z.string(),
    ageGroup: z.string(),
    createdAt: z.string(),
  }),
});

// Define the workflow
const registrationWorkflow = new LegacyWorkflow({
  name: "user-registration",
  triggerSchema: userInputSchema,
});

// Step 1: Validate user input
const validateInput = new LegacyStep({
  id: "validateInput",
  inputSchema: userInputSchema,
  outputSchema: validatedDataSchema,
  execute: async ({ context }) => {
    const { email, name, age } = context;

    // Simple validation logic
    const isValid = email.includes("@") && name.length > 0 && age >= 18;

    return {
      isValid,
      validatedData: {
        email: email.toLowerCase().trim(),
        name,
        age,
      },
    };
  },
});

// Step 2: Format user data
const formatUserData = new LegacyStep({
  id: "formatUserData",
  inputSchema: z.object({
    validatedData: z.object({
      email: z.string(),
      name: z.string(),
      age: z.number(),
    }),
  }),
  outputSchema: formattedDataSchema,
  execute: async ({ context }) => {
    const { validatedData } = context;

    // Generate a simple user ID
    const userId = `user_${Math.floor(Math.random() * 10000)}`;

    // Format the data
    const ageGroup = validatedData.age < 30 ? "young-adult" : "adult";

    return {
      userId,
      formattedData: {
        email: validatedData.email,
        displayName: validatedData.name,
        ageGroup,
      },
    };
  },
});

// Step 3: Create user profile
const createUserProfile = new LegacyStep({
  id: "createUserProfile",
  inputSchema: z.object({
    userId: z.string(),
    formattedData: z.object({
      email: z.string(),
      displayName: z.string(),
      ageGroup: z.string(),
    }),
  }),
  outputSchema: profileSchema,
  execute: async ({ context }) => {
    const { userId, formattedData } = context;

    // In a real app, you would save to a database here

    return {
      profile: {
        id: userId,
        ...formattedData,
        createdAt: new Date().toISOString(),
      },
    };
  },
});

// Build the workflow with variable mappings
registrationWorkflow
  // First step gets data from the trigger
  .step(validateInput, {
    variables: {
      email: { step: "trigger", path: "email" },
      name: { step: "trigger", path: "name" },
      age: { step: "trigger", path: "age" },
    },
  })
  // Format user data with validated data from previous step
  .then(formatUserData, {
    variables: {
      validatedData: { step: validateInput, path: "validatedData" },
    },
    when: {
      ref: { step: validateInput, path: "isValid" },
      query: { $eq: true },
    },
  })
  // Create profile with data from the format step
  .then(createUserProfile, {
    variables: {
      userId: { step: formatUserData, path: "userId" },
      formattedData: { step: formatUserData, path: "formattedData" },
    },
  })
  .commit();

export default registrationWorkflow;
```

## How to Use This Example

1. Create the file as shown above
2. Register the workflow in your Mastra instance
3. Execute the workflow:

```bash
curl --location 'http://localhost:4111/api/workflows/user-registration/start-async' \
     --header 'Content-Type: application/json' \
     --data '{
       "email": "user@example.com",
       "name": "John Doe",
       "age": 25
     }'
```

## Key Takeaways

This example demonstrates several important concepts about workflow variables:

1. **Data Mapping**: Variables map data from one step to another, creating a clear data flow.

2. **Path Access**: The `path` property specifies which part of a step's output to use.

3. **Conditional Execution**: The `when` property allows steps to execute conditionally based on previous step outputs.

4. **Type Safety**: Each step defines input and output schemas for type safety, ensuring that the data passed between steps is properly typed.

5. **Explicit Data Dependencies**: By defining input schemas and using variable mappings, the data dependencies between steps are made explicit and clear.

For more information on workflow variables, see the [Workflow Variables documentation](/docs/workflows-legacy/variables).

## Workflows (Legacy)

The following links provide example documentation for legacy workflows:

- [Creating a Simple Workflow (Legacy)](/examples/workflows_legacy/creating-a-workflow)
- [Workflow (Legacy) with Sequential Steps](/examples/workflows_legacy/sequential-steps)
- [Parallel Execution with Steps](/examples/workflows_legacy/parallel-steps)
- [Branching Paths](/examples/workflows_legacy/branching-paths)
- [Workflow (Legacy) with Conditional Branching (experimental)](/examples/workflows_legacy/conditional-branching)
- [Calling an Agent From a Workflow (Legacy)](/examples/workflows_legacy/calling-agent)
- [Tool as a Workflow step (Legacy)](/examples/workflows_legacy/using-a-tool-as-a-step)
- [Workflow (Legacy) with Cyclical dependencies](/examples/workflows_legacy/cyclical-dependencies)
- [Human in the Loop Workflow (Legacy)](/examples/workflows_legacy/human-in-the-loop)
- [Workflow (Legacy) with Suspend and Resume](/examples/workflows_legacy/suspend-and-resume)


---
title: "Guide: Building an AI Recruiter | Mastra Workflows | Guides"
description: Guide on building a recruiter workflow in Mastra to gather and process candidate information using LLMs.
---

import Steps from "@site/src/components/Steps";
import StepItem from "@site/src/components/StepItem";