Skip to main content
Connectors are the dots on a node. Inputs on the left, outputs on the right, and the lines you draw between them are how data moves through a workflow. You declare them in interface.yaml, and canvas draws one dot per entry.
interface.yaml
That node has one input dot and two output dots.

Sending something to an output

Declaring an output only creates the dot. api/events.yaml is what puts a value on it. One row per output connector, in the same order interface.yaml declares them. Read that one file and you know everything the node ever emits.
api/events.yaml
emit names the connector. value shapes what lands on it, as an expression over the reply. An output with no row is a dot that never carries anything, and lint warns about it.

Emitting once, or many times

This is where the node’s kind shows up. A PromiseNode settles. One call, one reply, and each row fires once over that reply. The rows above are a settling node. A CallbackNode emits. The reply arrives as a stream of events, so a row says which event it fires on, and it fires every time that event arrives.
api/events.yaml

Where a row fires from

from says where a row fires. response is the default, which is why most rows do not write it. complete fires once at the end, over everything already emitted, and is how a streaming node also produces one settled value. from: tool exists because a tool’s result is never in the HTTP stream. The tool loop produced it. Two things are recorded without any row here, because they are execution facts rather than node outputs:
  • Every tool call becomes a bar on the execution timeline the moment it returns, with its arguments, its result, its duration, and whether it succeeded.
  • Token usage is read off the vendor’s reply and summed across the turns of a run, with nothing declared. The usage connector on a node that declares one is a different thing: the node choosing to hand the block downstream as data.
Both are fire and forget. Recording never slows a run and never fails one. A run from the Nodes screen has no execution to attach to, so it records nothing.

Reading what arrives

A downstream node reads an upstream output by name:
quote1 is the id canvas gives the node on the canvas, and quote is the output connector. So signal.quote1.quote is the quote text. Give outputs names worth reading. They become the reference someone types into a Handlebars string later, and a good name is the difference between signal.crm1.contact and signal.crm1.output.

Types

type also decides how a wired field is written. A string field takes a Handlebars string, an object or array field takes a return expression. Config schema covers both.

Required, and what waiting means

required: true means the node waits for that connector before it runs.
A node that never runs is usually a required connector with nothing wired to it. Nothing reports an error, because waiting is a legitimate state for a node to be in.

Looping over a list

A node does not loop itself. You loop in the workflow, with the Loop nodes, and your node runs once per item like any other step. That keeps a node simple: it takes what it is given, does one job, and emits. A service connector is a different thing entirely. It is a node calling another node on demand, rather than a value travelling along an edge, and it fires no outputs. See Service connectors.

When it goes wrong

Next steps

Node types

Settling once or emitting many times, and how the platform tells.

api/events.yaml

Every field an events row takes, generated from the schema.