Motia Integration
MDWR workflows are automatically converted to Motia Steps and deployed to the Motia runtime.
How It Works
- Define Workflow: Create workflow using MDWR SDK
- Deploy: SDK compiles to canonical spec and generates Motia steps
- Auto-Discovery: Motia automatically discovers steps from
motia-atlas/src/ - Execute: Steps run through Motia’s event system
- 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:
groupId:'mdwr_workflows'key: Workflow ID (e.g.,'refund_v1')
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:
- Visual workflow diagram
- Step execution logs
- State inspection
- API endpoint testing
- Real-time debugging
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
- Architecture Overview - System architecture
- Getting Started - Build your first workflow