Skip to content

Ports and links

Understanding ports is understanding when a box runs. This page is the model’s reference.

Every box has them, without their appearing in its configuration:

PortDirectionFlowRole
inInputSignalTrigger. Several incoming links accepted
errorOutputValue + signalFailure route
doneOutputSignalEmitted once the box and its whole downstream subgraph have completed

Three boxes have no error port: Output, Now and Retry (the last of which is itself an error boundary). Two have no done: Output and Throw.

FlowMental symbolBehaviour
ValueA piece of dataCarries a value; also serves as a trigger
SignalA tickCarries nothing, only triggers
BothCarries a value and triggers

The one forbidden combination: a pure-signal output into a pure-value input. There would be nothing to put in the value.

any · json · number · string · boolean · duration · response · status · list · object.

Typing serves mainly for visual comfort, with one strict exception: a list input (the list port of the Add to a list and Remove from a list actions) refuses a source that is not list-compatible. json and list are compatible with each other; a plain object is not.

  • An input port accepts only one link. That is what keeps the graph readable: one value, one origin.
  • Except in, which accepts as many links as you like.
  • An output can feed as many inputs as you like.

Three rules, in order:

  1. Roots start. Any box with no incoming link is primed when the scenario is launched. There is no “start” box.
  2. Only wired inputs are awaited. A box runs when each of its input ports that is actually connected has received a value. An unwired port is never awaited. Values are remembered: an input keeps the last value it received.
  3. The in port acts as a barrier. Fed by several links, it waits for all of them to have arrived, then triggers once. That is the model’s “wait for these three branches to finish”.

The “Play on each event received” option (in the box’s context menu) turns every wired input into a non-blocking “or” gate: the box re-triggers on every value received, on any port.

Two uses: handling a stream message by message, and unblocking a completion cycle (a graph that loops back on itself).

This is the most useful distinction in practice:

  • a value output emits as soon as the box has produced its result;
  • done additionally waits for everything that consumes that result to have finished.

To sequence — “do all this, then clean up” — wire from done. To pass data, wire from the value output.

They are not a separate mechanism: they are output ports carrying a role, which drives their colour.

BoxOutputs
Ifthen / else
While, Do…Whilethen (the body)
Assertthen (success) / else (failure)
Retryattempt / exhausted
Schema validatevalid / invalid / errors
Switchone port per case, plus default
Socket.IO connectone port per declared event, plus others

A link can carry a selector: a path applied to the value in transit.

data.items[0].id
body['user-id']
headers["content-type"]
status

The a.b, a[0], a['key'] and a["key"] forms are accepted. A segment holding JSON is parsed on the fly; a path that matches nothing yields undefined.

Restorm sometimes infers a selector on its own at wiring time, when the source has a static preview that reduces to a single primitive value. You can always replace it or empty it.