Workflow state

Trust: ★★★☆☆ (0.90) · 0 validations · developer_reference

Published: 2026-05-10 · Source: crawler_authoritative

Tình huống

Mastra workflow guide for developers configuring shared state management across workflow steps, enabling progress tracking, result accumulation, and configuration sharing throughout workflow execution

Insight

Workflow state is a shared store accessible to all steps in a workflow via state and setState parameters in the execute function. Unlike step input/output which flows sequentially between steps, state persists across the entire workflow run including suspend/resume cycles. The stateSchema is defined on both the workflow (master schema) and individual steps (subset they need). Each step receives inputData from the previous step’s output, can read the current state, and call setState to update shared values for subsequent steps. The state object is typed according to the stateSchema definitions. State automatically persists when workflows suspend and resume - all updates made before suspension are preserved and available after resume. When nested workflows are used, state propagates from parent to child workflows; parent workflow state modifications are visible to steps inside nested workflows.

Hành động

Define a stateSchema property on createStep using Zod to declare the state values the step reads or modifies. Access current state via the state parameter in the execute function and update it by awaiting setState({ ...updatedValues }). For the workflow level, add stateSchema to createWorkflow containing all possible state values across all steps. When starting a run, pass initialState object matching the stateSchema to set starting values. Each step’s stateSchema declares only the subset it needs while the workflow’s stateSchema is the master definition. For suspend/resume patterns, state persists automatically across the resume cycle. For nested workflows, ensure parent workflow state modifications occur before the nested workflow step runs so the changes are visible inside the nested workflow.

Kết quả

State values updated via setState are available to all subsequent steps in the workflow. State persists across suspend and resume cycles, and propagates from parent to nested child workflows.

Điều kiện áp dụng

Requires Mastra workflows framework. stateSchema uses Zod for type definitions. Each step receives previous step’s output as inputData.


Nội dung gốc (Original)

Workflow state

Workflow state lets you share values across steps without passing them through every step’s inputSchema and outputSchema. This is useful for tracking progress, accumulating results, or sharing configuration across the entire workflow.

State vs step input/output

It’s important to understand the difference between state and step input/output:

  • Step input/output: Data flows sequentially between steps. Each step receives the previous step’s output as its inputData, and returns an output for the next step.
  • State: A shared store that all steps can read and update via state and setState. State persists across the entire workflow run, including suspend/resume cycles.
const step1 = createStep({
  id: 'step-1',
  inputSchema: z.object({ workflowInput: z.string() }),
  outputSchema: z.object({ step1Output: z.string() }),
  stateSchema: z.object({ sharedCounter: z.number() }),
  execute: async ({ inputData, state, setState }) => {
    // inputData comes from workflow input or previous step's output
    console.log(inputData.workflowInput)
 
    // state is the shared workflow state
    console.log(state.sharedCounter)
 
    // Update state for subsequent steps
    await setState({ sharedCounter: state.sharedCounter + 1 })
 
    // Return output that flows to next step's inputData
    return { step1Output: 'processed' }
  },
})

Defining state schemas

Define a stateSchema on both the workflow and individual steps. The workflow’s stateSchema is the master schema containing all possible state values, while each step declares only the subset it needs:

const step1 = createStep({
  stateSchema: z.object({
    processedItems: z.array(z.string()),
  }),
  execute: async ({ inputData, state, setState }) => {
    const { message } = inputData
    const { processedItems } = state
 
    await setState({
      processedItems: [...processedItems, 'item-1', 'item-2'],
    })
 
    return {
      formatted: message.toUpperCase(),
    }
  },
})
 
const step2 = createStep({
  stateSchema: z.object({
    metadata: z.object({
      processedBy: z.string(),
    }),
  }),
  execute: async ({ inputData, state }) => {
    const { formatted } = inputData
    const { metadata } = state
 
    return {
      emphasized: `${formatted}!! ${metadata.processedBy}`,
    }
  },
})
 
export const testWorkflow = createWorkflow({
  stateSchema: z.object({
    processedItems: z.array(z.string()),
    metadata: z.object({
      processedBy: z.string(),
    }),
  }),
})
  .then(step1)
  .then(step2)
  .commit()

Setting initial state

Pass initialState when starting a workflow run to set the starting values:

const run = await workflow.createRun()
 
const result = await run.start({
  inputData: { message: 'Hello' },
  initialState: {
    processedItems: [],
    metadata: { processedBy: 'system' },
  },
})

The initialState object should match the structure defined in the workflow’s stateSchema.

State persistence across suspend/resume

State automatically persists across suspend and resume cycles. When a workflow suspends and later resumes, all state updates made before the suspension are preserved:

const step1 = createStep({
  id: 'step-1',
  inputSchema: z.object({}),
  outputSchema: z.object({}),
  stateSchema: z.object({ count: z.number(), items: z.array(z.string()) }),
  resumeSchema: z.object({ proceed: z.boolean() }),
  execute: async ({ state, setState, suspend, resumeData }) => {
    if (!resumeData) {
      // First run: update state and suspend
      await setState({ count: state.count + 1, items: [...state.items, 'item-1'] })
      await suspend({})
      return {}
    }
    // After resume: state changes are preserved (count: 1, items: ["item-1"])
    return {}
  },
})

State in nested workflows

When using nested workflows, state propagates from parent to child. Changes made by the parent workflow before calling a nested workflow are visible to steps inside the nested workflow:

const nestedStep = createStep({
  id: 'nested-step',
  inputSchema: z.object({}),
  outputSchema: z.object({ result: z.string() }),
  stateSchema: z.object({ sharedValue: z.string() }),
  execute: async ({ state }) => {
    // Receives state modified by parent workflow
    return { result: `Received: ${state.sharedValue}` }
  },
})
 
const nestedWorkflow = createWorkflow({
  id: 'nested-workflow',
  inputSchema: z.object({}),
  outputSchema: z.object({ result: z.string() }),
  stateSchema: z.object({ sharedValue: z.string() }),
})
  .then(nestedStep)
  .commit()
 
const parentStep = createStep({
  id: 'parent-step',
  inputSchema: z.object({}),
  outputSchema: z.object({}),
  stateSchema: z.object({ sharedValue: z.string() }),
  execute: async ({ state, setState }) => {
    // Modify state before nested workflow runs
    await setState({ sharedValue: 'modified-by-parent' })
    return {}
  },
})
 
const parentWorkflow = createWorkflow({
  id: 'parent-workflow',
  inputSchema: z.object({}),
  outputSchema: z.object({ result: z.string() }),
  stateSchema: z.object({ sharedValue: z.string() }),
})
  .then(parentStep)
  .then(nestedWorkflow)
  .commit()

Liên kết

Xem thêm: