Edge kinds reference
Three edge kinds. Differ in semantics, not in field shape.
| Kind | condition required |
Used for |
|---|---|---|
sequential |
no | Unconditional next-step. Most edges. |
conditional |
yes | Branches from a logic_decision node, or any place a condition gates control. |
data |
no | Pure data dependency without control transfer. Rare. |
Shape#
Same for all three:
{
"id": "edge_<random>",
"type": "sequential", // or conditional, data
"source": { "node": "node_a", "port": "out" },
"target": { "node": "node_b", "port": "in" },
"condition": "confidence > 0.7" // required when type === "conditional"
}
source.port and target.port must refer to actually-existing port ids on the respective nodes — the analyze stage validates this and refuses dangling references.
sequential#
{ "type": "sequential",
"source": { "node": "node_classify", "port": "out" },
"target": { "node": "node_respond", "port": "in" } }
Plain control-flow edge. The target runs after the source completes.
conditional#
{ "type": "conditional",
"condition": "confidence > 0.7",
"source": { "node": "node_decision", "port": "out" },
"target": { "node": "node_respond_directly", "port": "in" } }
The target runs only if condition evaluates truthy in the source's emitted scope.
For a Decision node with three branches, you'd have three conditional edges all leaving the same out port, each with its own condition:
[
{ "type": "conditional", "condition": "intent == 'refund'", "source": {...}, "target": {...} },
{ "type": "conditional", "condition": "intent == 'complaint'", "source": {...}, "target": {...} },
{ "type": "conditional", "condition": "true", "source": {...}, "target": {...} } // fallthrough
]
The fallthrough edge could also be sequential — they're semantically equivalent when the prior conditionals have been evaluated. Decision-style conventions vary.
data#
{ "type": "data",
"source": { "node": "node_produce_value", "port": "out_aux" },
"target": { "node": "node_consume_value", "port": "in_aux" } }
Documents that the target needs a value from the source, but doesn't transfer control. Useful when the target is on a different control branch but still references a value the source bound.
Currently advisory — the compiler emits them on the IR but ScaiCore's runtime doesn't enforce data-only edges differently from sequential. Reserved for richer dependency-tracking in future.
Editing edges#
In the canvas:
- Click an edge to select it. The property panel shows the edge's type, condition (when conditional), source, and target.
- Decision branches: click the Decision node first — the property panel's Branches section lists every outgoing edge inline with editable conditions. Easier than clicking each edge separately.
In code:
PUT /v1/flows/{id}with the updatededgesarray.- Or programmatic via
flowStore.updateEdge(edge_id, { condition: ... })from the canvas.