---
title: Edge kinds reference
path: reference/edge-kinds
status: published
---

# 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:

```jsonc
{
  "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`

```jsonc
{ "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`

```jsonc
{ "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:

```jsonc
[
  { "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`

```jsonc
{ "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 updated `edges` array.
- Or programmatic via `flowStore.updateEdge(edge_id, { condition: ... })` from the canvas.
