# Step Configuration

Steps are the building blocks of a workflow. Each step defines an action to execute and how to handle its data.

We are adding explicit OpenTelemetry tracing to each step, so that you can see the inputs and outputs of each step in your observability platform.

## API Reference

### Creating Steps

Steps are created using the `Step` class:

```ts showLineNumbers copy
const step = new Step({
  id: "stepId",
  payload: {
    /* ... */
  },
  inputSchema: z.object({
    /* ... */
  }),
  outputSchema: z.object({
    /* ... */
  }),
  action: async ({ data, runId }) => {
    /* ... */
  },
});
```

### Step Configuration Options

<PropertiesTable
  content={[
    {
      name: "id",
      type: "string",
      description: "Unique identifier for the step",
      required: true,
    },
    {
      name: "inputSchema",
      type: "z.ZodSchema",
      description: "Zod schema to validate input data before execution",
      required: false,
    },
    {
      name: "outputSchema",
      type: "z.ZodSchema",
      description: "Zod schema to infer output data type",
      required: false,
    },
    {
      name: "payload",
      type: "Partial<Record<string, any>>",
      description: "Static data to be merged with variables",
      required: false,
    },
    {
      name: "action",
      type: "(data: TInput) => Promise<TOutput>",
      description: "Async function that executes the step logic",
      required: false,
    },
  ]}
/>

### Adding Steps to Workflows

When adding steps to a workflow, you can configure additional behavior using the `step()` method:

### step()

```ts showLineNumbers copy
workflow.step("stepId", {
  variables: {
    // Map data from previous steps or trigger
    userId: { stepId: "trigger", path: "user.id" },
    orderData: { stepId: "processOrder", path: "result" },
  },
  transitions: {
    // Define conditional transitions to other steps
    nextStep: {
      condition: {
        ref: { stepId: "stepId", path: "status" },
        query: { $eq: "success" },
      },
    },
  },
});
```

### Step Configuration in Workflow

<PropertiesTable
  content={[
    {
      name: "variables",
      type: "Record<string, VariableReference>",
      description:
        "Maps data from previous steps or trigger data into the step input",
      required: false,
    },
    {
      name: "transitions",
      type: "Record<string, TransitionConfig>",
      description: "Defines conditional transitions to other steps",
      required: false,
    },
  ]}
/>

## Examples

### Basic Step

```ts showLineNumbers copy
const processOrder = new Step({
  id: "processOrder",
  action: async ({ data, runId }) => {
    return {
      status: "processed",
      orderId: data.id,
    };
  },
});

// Configure step in workflow
workflow.step("processOrder");
```

### With Schema Validation

```ts showLineNumbers copy
const validateUser = new Step({
  id: "validateUser",
  inputSchema: z.object({
    userId: z.string(),
    email: z.string().email(),
  }),
  outputSchema: z.object({
    isValid: z.boolean(),
  }),
  action: async ({ data, runId }) => {
    const { userId, email } = data;
    return { isValid: true };
  },
});

// Configure step in workflow
workflow.step("validateUser");
```

### With Variables

```ts showLineNumbers copy
const sendEmail = new Step({
  id: "sendEmail",
  inputSchema: z.object({
    userId: z.string(),
    orderDetails: z.object({
      orderId: z.string(),
      status: z.string(),
    }),
  }),
  action: async ({ data, runId }) => {
    const { userId, orderDetails } = data;
    return { sent: true };
  },
});

// Configure step in workflow
workflow.step("sendEmail", {
  variables: {
    userId: { stepId: "trigger", path: "user.id" },
    orderDetails: { stepId: "processOrder", path: "result" },
  },
});
```

### With Static Payload

```ts showLineNumbers copy
const createInvoice = new Step({
  id: "createInvoice",
  inputSchema: z.object({
    orderId: z.string(),
    currency: z.string(),
    taxRate: z.number(),
  }),
  action: async ({ data, runId }) => {
    const { orderId, currency, taxRate } = data;
    return { invoiceId: "INV-123" };
  },
});

workflow.step("createInvoice", {
  variables: {
    orderId: { stepId: "processOrder", path: "orderId" },
  },
  payload: {
    currency: "USD",
    taxRate: 0.2,
  },
});
```
