Connections vs expressions

Four ways to feed a value into a parameter: a wire, a typed expression, an attribute binding, or a multi-input pin that gathers its own wires.

The four mechanisms sit next to each other in the interface and look alike. They do different jobs.

Wire it: a connection

A connection is a wire dragged from one node's output to another node's input. The downstream node reads whatever the upstream node produces, and a change at the source arrives on the next cook.

Use a connection when the value comes from somewhere else in the graph: a number another node computed, a position from a curve, a colour from a palette node, the output of an MIDI Input or OSC Input device.

Most parameters carry a socket and take a wire. Structural ones do not: a parameter that reshapes the node, such as a mode selector or an input count, is edit-only and shows no socket at all, and a wire dropped on it is refused.

A wire does not beat a = expression. While a parameter holds an expression, an incoming wire stops driving the value and the expression drives instead. Clear the expression to let the wire through, and clearing means emptying the field: typing a number over a formula makes that number the formula and leaves the wire shut out.

Type it: a parameter expression

A parameter expression is a formula typed into the parameter field itself, prefixed with =. It computes a value on every frame from globals like $T (time) and $F (frame):

= sin($T * 2) * 10

Use an expression when the value is procedural, driven by time or maths rather than by another node. It is the quickest route to continuous motion without authoring a curve.

Expressions resolve to a single value. They see the time globals, the maths constants and other nodes' parameters by name, but not per-element attributes (@). For per-element logic, use an Expression node in the graph. Parameter expressions lists every global and function.

That gives a parameter four possible drivers, resolving in a fixed order: expression, connection, keyframes, typed value. Whichever is highest and present is the one you see. An expression therefore shadows a wire. A wire with no expression above it makes the keyframes and the typed value dormant until it is unplugged, and if its upstream has not cooked the input goes absent rather than falling back to the number underneath.

Bind it: from an attribute

Some numeric parameters read their value from an attribute on the node's input, so the parameter varies per element instead of holding one number for the whole node. Type @ followed by an attribute name straight into the parameter field, for example @width, and the parameter follows that attribute element by element.

Use this when the input already carries the number: a per-point width, a per-row inset, a value an Expression node computed onto every element upstream.

Alt-click the value to open its editor, which lists the attributes carried by the node's connected inputs as clickable chips. A bound parameter reads as @width in place of its slider. Attribute, expression and typed number are mutually exclusive, so typing a plain number or a = expression back into the field releases the binding. An element that lacks the named attribute falls back to the value you last typed, with no error.

Seven parameters offer it so far: the four crop insets on Mask, angle and factor on Deform, and progress on Follow Path. Parameters that do not offer it show no @ binding. More will opt in over time.

Let it gather: a connection expression

Some inputs accept many wires at once, such as the inputs pin on Merge. Those pins carry a text field on their own row in the node body: click it, type a connection expression, and the wires are made for you.

Two things can be typed there. A list names nodes directly:

A query names a rule instead, and the wires follow the rule as the graph changes:

Reorder the layers and the query re-runs, with no re-dragging. A list does not: it is made into wires once, and a node created later that matches the name is not picked up. Use a query when which inputs you need is a rule, and plain wires when it is a fixed, deliberate handful.

The layer queries read from the owner's own place in the stack, and a node that has not been promoted into the stack counts as sitting on top of it. So layers.below() on a plain Merge pulls in every promoted layer, and layers.above() matches nothing.

A query owns the wires it makes. They cannot be deleted by hand, and a wire you drew yourself is never removed by editing the text, so a name deleted from the list reappears. Edit the query, not the wires.

Quick guide

See also