This document describes the architecture of subflows (loop and parallel blocks) in the Sim workflow system. Subflows are container nodes that can contain child blocks and execute them iteratively or in parallel. This covers the storage model, computed structure generation, editor integration, and execution orchestration.
For information about workflow execution, see Workflow Execution Engine. For details on loop and parallel execution semantics, see Loop & Parallel Execution.
Subflows are special container blocks that enable advanced control flow patterns. There are two main types:
| Subflow Type | Subtypes | Purpose |
|---|---|---|
| Loop | for, forEach, while, doWhile | Execute child blocks iteratively |
| Parallel | count, collection | Execute child blocks in parallel |
Key Architecture Principles:
data.parentIdloops and parallels records are regenerated from blocks on every state changeblock.data fieldsSources: apps/sim/stores/workflows/workflow/types.ts5-143
Configuration Fields (apps/sim/stores/workflows/workflow/types.ts16-23):
| Field | Type | Used By | Description |
|---|---|---|---|
loopType | 'for' | 'forEach' | 'while' | 'doWhile' | All | Loop execution mode |
iterations | number | for | Number of iterations (stored in data.count) |
forEachItems | array | object | string | forEach | Collection to iterate over (stored in data.collection) |
whileCondition | string | while | JS expression evaluated before each iteration |
doWhileCondition | string | doWhile | JS expression evaluated after each iteration |
Sources: apps/sim/stores/workflows/workflow/types.ts16-23 apps/sim/stores/workflows/workflow/utils.ts61-83
Configuration Fields (apps/sim/stores/workflows/workflow/types.ts25-29):
| Field | Type | Used By | Description |
|---|---|---|---|
parallelType | 'count' | 'collection' | All | Parallel execution mode |
count | number | count | Number of parallel executions (stored in data.count) |
distribution | array | object | string | collection | Collection to distribute across parallel executions (stored in data.collection) |
Sources: apps/sim/stores/workflows/workflow/types.ts25-29 apps/sim/stores/workflows/workflow/utils.ts92-119
Subflows are stored as BlockState objects with type='loop' or type='parallel'. Configuration is stored in the data field:
Sources: apps/sim/stores/workflows/workflow/types.ts45-69
Child blocks reference their container using data.parentId and data.extent='parent':
Finding Child Nodes (apps/sim/stores/workflows/workflow/utils.ts128-132):
Sources: apps/sim/stores/workflows/workflow/utils.ts128-132 apps/sim/stores/workflows/workflow/types.ts45-69
The workflow store maintains separate loops and parallels records that are computed from blocks. These computed structures are used by the execution engine.
Sources: apps/sim/stores/workflows/workflow/types.ts125-134
Sources: apps/sim/stores/workflows/workflow/types.ts136-143
The computed structures are generated by utility functions that convert UI blocks to execution structures:
generateLoopBlocks Implementation (apps/sim/stores/workflows/workflow/utils.ts167-180):
convertLoopBlockToLoop Implementation (apps/sim/stores/workflows/workflow/utils.ts61-83):
The parallel generation follows the same pattern via generateParallelBlocks() and convertParallelBlockToParallel().
Regeneration Triggers:
The computed structures are regenerated whenever blocks are modified:
| Operation | Regeneration |
|---|---|
addBlock | ✅ Regenerates loops and parallels |
batchAddBlocks | ✅ Regenerates loops and parallels |
batchRemoveBlocks | ✅ Regenerates loops and parallels |
batchUpdateBlocksWithParent | ✅ Regenerates loops and parallels |
updateLoopType | ✅ Updates loops record directly |
updateParallelType | ✅ Updates parallels record directly |
Sources: apps/sim/stores/workflows/workflow/utils.ts61-203 apps/sim/stores/workflows/workflow/store.ts161-163 apps/sim/stores/workflows/workflow/store.ts238-239
Subflow nodes are rendered using the SubflowNodeComponent which displays the container with its configuration:
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:177-182
The useSubflowEditor hook provides editor state and logic for configuring subflows:
Configuration (apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-subflow-editor.ts:21-48):
Key Functions:
handleSubflowTypeChange() - Updates loop/parallel type via collaborative actionshandleIterationCountChange() - Updates iteration count (for/count types)handleCollectionChange() - Updates collection/distribution (forEach/collection types)highlightWithReferences() - Syntax highlights references and env vars in expressionsMoving Blocks Into Containers:
When blocks are dragged into a subflow, their parent relationship is updated:
Implementation (apps/sim/stores/workflows/workflow/store.ts277-315):
Sources: apps/sim/stores/workflows/workflow/store.ts277-315 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:589-676
The workflow store provides actions for modifying subflow configuration:
Loop Type Update (apps/sim/stores/workflows/workflow/store.ts752-773):
Sources: apps/sim/stores/workflows/workflow/store.ts752-851
Parallel Type Update (apps/sim/stores/workflows/workflow/store.ts853-874):
Sources: apps/sim/stores/workflows/workflow/store.ts853-918
Subflow operations are synchronized across clients using socket-based collaborative editing:
Socket Operations (apps/sim/hooks/use-collaborative-workflow.ts238-278):
Collaborative Actions:
| Action | Socket Operation | Payload |
|---|---|---|
| Update loop type | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'loop', config: { loopType } } |
| Update loop count | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'loop', config: { iterations } } |
| Update forEach items | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'loop', config: { forEachItems } } |
| Update while condition | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'loop', config: { whileCondition } } |
| Update parallel type | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'parallel', config: { parallelType } } |
| Update parallel count | SUBFLOW_OPERATIONS.UPDATE | { id, type: 'parallel', config: { count } } |
Sources: apps/sim/hooks/use-collaborative-workflow.ts238-278 apps/sim/socket/constants.ts
When pasting or duplicating blocks that contain subflows, special handling is required:
Triggers Cannot Be in Subflows (apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:927-936):
Subflows Cannot Be Nested (apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:938-947):
When pasting into a subflow, positions are adjusted from absolute to relative coordinates:
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:883-1040
At execution time, the computed Loop and Parallel structures are used by the execution engine:
The serializer converts the workflow state including the computed loop/parallel structures into a SerializedWorkflow that the executor uses. The execution engine orchestrates iteration state, variable scoping, and parallel execution based on the subflow configuration.
For details on how loops and parallels are executed, see Loop & Parallel Execution.
Sources: apps/sim/serializer/ apps/sim/executor/
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.