Workflow State trong Mastra.ai - Quản lý trạng thái chia sẻ giữa các bước

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

Published: 2026-05-09 · Source: crawler_authoritative

Tình huống

Nhà phát triển đang xây dựng workflow với Mastra.ai cần chia sẻ dữ liệu giữa các bước mà không cần truyền qua mọi step inputSchema và outputSchema. Workflow state cho phép theo dõi tiến trình, tích lũy kết quả và chia sẻ cấu hình xuyên suốt workflow.

Insight

Workflow State là một shared store cho phép tất cả steps đọc và cập nhật qua statesetState. Điểm khác biệt cốt lõi: Step input/output dữ liệu chảy tuần tự giữa các bước (mỗi step nhận output của step trước làm inputData), trong khi State tồn tại xuyên suốt workflow run bao gồm cả suspend/resume cycles. Workflow’s stateSchema là master schema chứa tất cả giá trị state có thể, mỗi step chỉ khai báo subset cần thiết. State tự động persist qua suspend/resume - khi workflow suspend rồi resume, tất cả state updates trước suspension được bảo toàn. Khi sử dụng nested workflows, state propagation từ parent xuống child - changes made by parent trước khi gọi nested workflow visible to steps bên trong nested workflow.

Hành động

  1. Khai báo stateSchema trên cả workflow và individual steps với Zod schemas. 2. Sử dụng initialState khi gọi run.start() để set giá trị khởi tạo matching với workflow’s stateSchema. 3. Trong execute function, access state qua state object và update qua await setState({ key: value }). 4. State changes persist tự động qua suspend/resume cycles - không cần xử lý thêm. 5. Với nested workflows, parent workflow set state trước khi gọi nested workflow để child steps có thể access state đã được modify.

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

Chỉ áp dụng cho workflow được xây dựng với Mastra.ai SDK. Yêu cầu sử dụng TypeScript với Zod cho schema validation. initialState object phải match structure của workflow’s stateSchema.


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: