Quick Start
Build and run a small workflow with the current CDX engine API.
What You Will Build
This example:
- Validates the workflow input.
- Waits for an external decision signal.
- Routes to approved or rejected work.
- Stores runtime state in
InMemoryStorage.
Complete Example
dart
import 'package:vyuh_workflow_engine/vyuh_workflow_engine.dart';
Future<void> main() async {
final context = RegistryTypeResolver(
descriptors: [DefaultWorkflowDescriptor()],
);
final storage = InMemoryStorage();
final engine = WorkflowEngine(
context: context,
storage: storage,
executionMode: ExecutionMode.production,
);
await engine.initialize();
final workflow = WorkflowBuilder(
'request-approval',
'Request Approval',
description: 'Validate a request and wait for an approval signal.',
)
.start('start')
.task('validate', execute: (ctx) async {
final requestId = ctx.getInitialRequired<String>('requestId');
return {
'requestId': requestId,
'validatedAt': DateTime.now().toUtc().toIso8601String(),
};
})
.signalWait(
'await-decision',
signal: 'approval_decision',
storeAs: 'decision',
)
.oneOf('route-decision', [
Branch.whenEquals('decision.status', 'approved', then: 'mark-approved'),
Branch.whenEquals('decision.status', 'rejected', then: 'mark-rejected'),
Branch.otherwise(then: 'mark-rejected'),
])
.task('mark-approved', execute: (ctx) async {
return {
'finalStatus': 'approved',
'approvedBy': ctx.getAny<String>('decision.userId'),
};
})
.end('approved')
.from('route-decision')
.to('mark-rejected')
.task('mark-rejected', execute: (ctx) async {
return {
'finalStatus': 'rejected',
'rejectedBy': ctx.getAny<String>('decision.userId'),
};
})
.end('rejected')
.build();
engine.registerWorkflow(workflow);
final instance = await engine.startWorkflow(
workflowCode: workflow.code,
input: {'requestId': 'REQ-001'},
userId: 'alice',
);
await engine.sendSignal(
workflowInstanceId: instance.id,
node: 'await-decision',
payload: {
'status': 'approved',
'userId': 'manager-1',
'comment': 'Looks good.',
},
);
final completed = await engine.getWorkflowInstance(instance.id);
print(completed?.status);
print(completed?.output);
await engine.dispose();
}Runtime Shape
Current API Points
| API | Current behavior |
|---|---|
RegistryTypeResolver | Resolves node configs, task executors, user task executors, and conditions from WorkflowDescriptors. |
InMemoryStorage() | Uses typed WorkflowDefinition, WorkflowInstance, UserTaskInstance, and WorkflowEvent repositories. It no longer takes a context. |
WorkflowEngine | Requires context, storage, and executionMode. Use ExecutionMode.production for real execution. |
WorkflowBuilder | Builds an executable Workflow with generated ID ${code}-v${version}. |
TaskExecutor | Returns TaskSuccess or TaskFailure; inline builder tasks can return plain maps and are wrapped for you. |
sendSignal | Matches waiting nodes by node ID, schema type, or signal name. Optional port chooses a user-task or multi-output route. |
Next Steps
- Packages for the current CDX package split.
- Loading and Registration for persisted workflow definitions and templates.
- Storage Adapters for Supabase and custom storage.