Motia Integration

MDWR workflows are automatically converted to Motia Steps and deployed to the Motia runtime.

How It Works

  1. Define Workflow: Create workflow using MDWR SDK
  2. Deploy: SDK compiles to canonical spec and generates Motia steps
  3. Auto-Discovery: Motia automatically discovers steps from motia-atlas/src/
  4. Execute: Steps run through Motia’s event system
  5. Debug: Use Motia Workbench to visualize and debug

Generated Step Structure

Entry Step (API)

Every workflow gets an entry API step:

import type { ApiRouteConfig, Handlers } from 'motia';

export const config: ApiRouteConfig = {
  name: 'RefundV1Entry',
  type: 'api',
  path: '/workflows/refund_v1/execute',
  method: 'POST',
  emits: ['refund_v1.started'],
  flows: ['refund_v1-flow']
};

export const handler: Handlers['RefundV1Entry'] = async (_, { emit, logger, state }) => {
  logger.info('Executing MDWR workflow: refund_v1');
  
  const workflowState = await state.get('mdwr_workflows', 'refund_v1') || {};
  const executionId = workflowState.executionId || Math.random().toString(36).substring(7);
  
  await state.set('mdwr_workflows', 'refund_v1', {
    ...workflowState,
    executionId,
    status: 'running'
  });
  
  await emit('refund_v1.started', { executionId });
  
  return {
    status: 200,
    body: { ok: true, executionId, workflowName: 'refund_v1' }
  };
};

Workflow Steps (Events)

Each workflow step becomes an event step:

import type { EventConfig, Handlers } from 'motia';

export const config: EventConfig = {
  name: 'RefundV1EvaluateRisk',
  type: 'event',
  subscribes: ['refund_v1.started'],
  emits: ['refund_v1.evaluate_risk.completed'],
  flows: ['refund_v1-flow']
};

export const handler: Handlers['RefundV1EvaluateRisk'] = async (input, { emit, logger, state }) => {
  logger.info('Executing MDWR step: evaluate_risk', { input });
  
  const workflowState = await state.get('mdwr_workflows', input?.workflowName || 'refund_v1') || {};
  const executionId = input?.executionId || workflowState.executionId;
  
  // Execute step logic
  const result = {
    decision: "approve",
    reason: "Standard approval",
    confidence: 0.8
  };
  
  workflowState['evaluate_risk'] = {
    executed: true,
    timestamp: new Date().toISOString(),
    result
  };
  
  await state.set('mdwr_workflows', input?.workflowName || 'refund_v1', workflowState);
  await emit('refund_v1.evaluate_risk.completed', { executionId, result });
};

State Management

MDWR uses Motia’s state management:

// Get workflow state
const workflowState = await state.get('mdwr_workflows', 'refund_v1');

// Set workflow state
await state.set('mdwr_workflows', 'refund_v1', {
  ...workflowState,
  stepName: stepResult
});

State is organized by:

Event Flow

Entry API → emit('workflow.started')

Step 1 → subscribe('workflow.started') → emit('workflow.step1.completed')

Step 2 → subscribe('workflow.step1.completed') → emit('workflow.step2.completed')

...

Deployment Path

Steps are deployed to:

motia-atlas/src/{workflowId}/
  ├── {workflowId}-entry.step.ts
  ├── {workflowId}-{step1}.step.ts
  ├── {workflowId}-{step2}.step.ts
  └── ...

Workbench Integration

Deployed workflows appear in Motia Workbench:

Access at: http://localhost:3000

Best Practices

1. Use Workflow-Specific Flows

Each workflow gets its own flow:

flows: [`${workflowId}-flow`]

2. Consistent State Keys

Use consistent state keys:

state.get('mdwr_workflows', workflowId)
state.set('mdwr_workflows', workflowId, state)

3. Event Naming

Follow naming convention:

emits: [`${workflowId}.${stepName}.completed`]
subscribes: [`${workflowId}.${previousStep}.completed`]

Next Steps