Start & End Nodes
Start and End nodes define the entry and terminal points of a workflow.
Start Node
Every workflow must have exactly one start node.
Definition
dart
builder.start('begin');
// With custom name
builder.start('begin', name: 'Start Order Processing');Behavior
When a workflow starts:
- Engine creates a new
WorkflowInstance - Creates a token at the start node
- Start executor finds the outgoing edge
- Returns
ContinueResultto move to the next node
Executor
dart
class StartNodeExecutor extends NodeExecutor {
@override
Future<NodeResult> execute(WorkflowContext context) async {
final outgoingEdge = context.outgoingEdges.first;
return ContinueResult.single(outgoingEdge.targetNodeId);
}
}End Node
Workflows can have multiple end nodes for different outcomes.
Definition
dart
// Basic end node
builder.end('completed');
// Named end nodes for different outcomes
builder.end('approved', name: 'Request Approved');
builder.end('rejected', name: 'Request Rejected');
builder.end('cancelled', name: 'Request Cancelled');Behavior
When a token reaches an end node:
- End executor returns
CompleteWorkflowResult - Token is deactivated
- If all tokens are inactive, workflow status becomes
completed
Executor
dart
class EndNodeExecutor extends NodeExecutor {
@override
Future<NodeResult> execute(WorkflowContext context) async {
return CompleteWorkflowResult(
output: context.currentNode.config['output'] ?? {},
);
}
}Multiple End Nodes Pattern
Use multiple end nodes to represent different workflow outcomes:
dart
final workflow = WorkflowBuilder(...)
.start('begin')
.task('validate', ...)
.oneOf('checkValid', [
Branch.whenFn((o) => o['isValid'] == true, then: 'process'),
Branch.otherwise(then: 'invalid'),
])
.task('process', ...)
.end('success', name: 'Successfully Processed')
.end('invalid', name: 'Validation Failed')
.end('error', name: 'Processing Error')
.connect('begin', 'validate')
.connect('validate', 'checkValid')
.connect('process', 'success')
.build();Flow Diagram
Best Practices
1. Name end nodes descriptively
dart
// GOOD - Clear outcome names
builder.end('approved', name: 'Request Approved');
builder.end('rejected', name: 'Request Rejected');
// AVOID - Generic names
builder.end('end1');
builder.end('end2');2. Use a limited number of end nodes
A workflow should have 2-4 end nodes representing distinct outcomes:
- Success path
- Failure/error path
- Cancelled/abandoned path
- Optional: timeout path
3. Ensure all paths lead to end nodes
Every possible execution path should terminate at an end node. Use the default branch in gateways to catch unexpected cases.
Next Steps
- Task Nodes - Automated work
- User Tasks - Human tasks
- Gateways - Routing decisions