Workflow building blocks
Build workflow diagrams from operations, human tasks and control-flow blocks.
Loading interactive example…Open in new tab ↗
Choose a block from the palette, edit its label and inputs, then connect its ports. The example builds workflow drafts; it does not execute them.
Available blocks
| Block | Use it for |
|---|---|
| Start / End | Mark the entry and exit of a workflow. |
| Operation | A registered automated task. |
| Human work | A task with named responses, such as approve or revise. |
| Wait for event | Wait for an external event. |
| Sleep / timer | Continue after a delay. |
| Decision / switch | Choose a path based on a value. |
| Parallel / Race / Quorum | Run branches until all, the first, or a required number finish. |
| Branch end | Finish one branch. |
| Call / Spawn / Join workflow | Run a child workflow and optionally wait for it. |
| Saga | Pair steps with compensating actions. |
| For each | Repeat a branch for each item. |
| Continue as new | Start another run with new input. |
| Query | Read a registered query. |
Set it up
Register the standard blocks and attach the session to a Flutter canvas:
dart
import 'package:vyuh_diagram_kit/vyuh_diagram_kit.dart';
import 'package:vyuh_diagram_workflow/vyuh_diagram_workflow.dart';
final registry = WorkflowAuthoringRegistry([
WorkflowStart(),
...defaultWorkflowPrimitives(),
]);
final documentSession = registry.createSession(
textLayout: FlutterDiagramTextLayoutEngine(),
);
final canvasSession = DrawingSession.fromSession(documentSession);
final canvas = DrawingCanvas(session: canvasSession);Use registry.entries for your palette. Create a node with its registered shape type:
dart
canvasSession.createShape(
type: registry.entries.first.shapeType,
worldCenter: const DiagramPoint(100, 100),
);Unmount the canvas, then dispose canvasSession followed by documentSession. For headless authoring, use registry.createSession() without the Flutter adapter.
Add your own tasks
Add WorkflowOperation and WorkflowWork entries to the registry using your workflow engine contracts. Use WorkflowResponse to name the outcomes of human work.
The example registers Send notification and Review proposal. Expand its source for a complete registration example.
Task registration source
dart
import 'package:json_schema_builder/json_schema_builder.dart' as json;
import 'package:vyuh_diagram_workflow/vyuh_diagram_workflow.dart';
import 'package:vyuh_workflow_engine/vyuh_workflow_runtime.dart' as runtime;
/// Example business contracts compose with the durable control primitives.
/// No handlers are installed and no execution service is created.
WorkflowAuthoringRegistry exampleWorkflowRegistry() {
final attachment = json.Schema.object(
properties: {'name': json.Schema.string(), 'url': json.Schema.string()},
required: ['name', 'url'],
);
final request = runtime.Schema.identity<Map<String, Object?>>(
name: 'notification-request',
jsonSchema: json.Schema.fromMap({
...json.Schema.object(
properties: {
'recipient': json.Schema.string(),
'message': json.Schema.string(),
'priority': json.Schema.string(enumValues: ['normal', 'urgent']),
'cc': json.Schema.list(items: json.Schema.string()),
'delivery': json.Schema.object(
properties: {'sender': json.Schema.string()},
),
'attachments': json.Schema.list(
items: json.Schema.fromMap({r'$ref': r'#/$defs/attachment'}),
),
},
required: ['recipient', 'message'],
).value,
r'$defs': {'attachment': attachment.value},
}),
);
final receipt = runtime.Schema.identity<Map<String, Object?>>(
name: 'notification-receipt',
jsonSchema: json.Schema.object(
properties: {'messageId': json.Schema.string()},
required: ['messageId'],
),
);
final review = runtime.Schema.identity<Map<String, Object?>>(
name: 'review-request',
jsonSchema: json.Schema.object(
properties: {
'title': json.Schema.string(),
'summary': json.Schema.string(),
},
required: ['title', 'summary'],
),
);
runtime.Schema<Map<String, Object?>> response(
String name,
List<String> decisions,
) => runtime.Schema.identity<Map<String, Object?>>(
name: name,
jsonSchema: json.Schema.object(
properties: {
'decision': json.Schema.string(enumValues: decisions),
'comment': json.Schema.string(),
},
required: ['decision', 'comment'],
),
);
return WorkflowAuthoringRegistry([
WorkflowOperation<Map<String, Object?>, Map<String, Object?>, Never>(
label: 'Send notification',
description: 'System work: send a message and return its receipt.',
operation: runtime.Operation(
name: 'send-notification',
input: request,
output: receipt,
),
),
WorkflowWork<Map<String, Object?>, Map<String, Object?>>(
label: 'Review proposal',
description: 'Human work: approve the proposal or request a revision.',
work: runtime.Work(
name: 'review-proposal',
input: review,
response: response('review-response', ['approve', 'revise']),
),
responses: [
WorkflowResponse(
id: 'approve',
label: 'Approve',
payload: response('approval', ['approve']),
),
WorkflowResponse(
id: 'revise',
label: 'Request revision',
payload: response('revision', ['revise']),
),
],
),
WorkflowStart(),
...defaultWorkflowPrimitives(),
]);
}