data.nodes, parsedData, trigger, and every edge source / target.
Canvas data (React Flow toObject())
Root nodes:
data.nodes, not nested. They carry parentId:
out edge from that parent. Execution continues from the sub-node connections.out.
Execution parsedData + trigger
transformReactFlowOutput builds this from the canvas:
- The trigger is removed from
parsedDataand stored asworkflow.trigger. triggerTypeistrigger.data.eventType.parsedDatais parent nodes only. Sub-nodes hang offparent.subNodes[].- Each node has
connections: { out: string[] }— target ids only. No handle ids. Branching is “which sub-node’sconnections.out”. - Runtime starts at
trigger.connections.out[0].
Parent
title is usually the NodeType string. Sub-node title is the canvas data.label. If/Else matches title.toLowerCase() === "true" / "false".Mapping checklist
How to wire a graph
Build the canvas first, then copy each edge into executionconnections.out. IDs must be identical in data.nodes, data.edges[].source / target, parsedData, trigger, and every connections.out entry.
1. Give every node a stable id
Use short unique strings (trig_1, wa_menu, ans_tours). Reuse the same string everywhere. Sub-nodes live in data.nodes as siblings with parentId set to the parent’s id.
2. Draw canvas edges (data.edges)
Every edge:
"out" edge from a parent that has sub-nodes. The engine ignores parent connections.out once subNodes exist and continues from the chosen child’s connections.out.
3. Copy each edge into execution
For every canvas edgesource → target, find that source in trigger, parsedData[], or parent.subNodes[] and append target to connections.out (array of target ids only — no handles).
Runtime starts at
trigger.connections.out[0]. If that array is missing, the run never starts.
4. Sanity check
- Every
source/target/connections.outid exists. - Trigger is not in
parsedData. - Sub-nodes are not extra
parsedDataitems; they hang offparent.subNodes[]. - Parent with answers / true-false / cases has no root
outedge.