Appearance
Node reference overview
FlowRunner ships with twenty-one nodes. This page lists every one — its category, what it does, and the ports it exposes — so you can pick the right building block for a flow.
What a node is
A flow is a graph of nodes joined by connections. When a request hits your flow's URL, FlowRunner starts at the Start node and follows connections from one node's output port to the next node's input, running each node in turn until it reaches an End node.
Every node reads and writes a shared bag of references (refs). A node stores its output under a variable name — a namespace — and later nodes read values back with a dotted reference like start.email or response.body. The inputs that arrived with the request land under the Start node's namespace (start by default).
NOTE
Node behaviour on this reference is documented from the flow engine (packages/engine/src/engine.ts) for built-in and I/O nodes, and from the published manifest and handler for component nodes. Config field names below are the exact keys read at run time.
The twenty-one nodes
| Node | Category | Kind | Purpose | Output ports |
|---|---|---|---|---|
| Start | Trigger | Built-in | The entry point — declares the HTTP method and validates the request into start.* | one (next) |
| End | Terminal | Built-in | Shapes the HTTP response (statusCode, responseBody) and stops the flow | none |
| If | Control flow | Built-in | Branches on a condition or structured expression | true, false |
| Switch | Control flow | Built-in | Routes on a value, matching cases to named ports | your case ports, default |
| ForEach | Control flow | Built-in | Loops over an array, running a sub-branch per item | loop, next |
| Filter | Data | Built-in | Keeps only the array items matching a condition | next |
| Merge | Control flow | Built-in | Fans branches back into one variable (coalesce / combine) | next |
| Code | Logic | Built-in | Runs sandboxed JavaScript on the flow data | next, error |
| Set | Data | Built-in | Copies a ref or a literal into a new variable | next |
| Template | Data | Built-in | Renders a ${...} string into a variable | next |
| Parse | Data | Built-in | Parses a JSON or CSV string into structured data | next, error |
| Delay | Control flow | Built-in | Waits a bounded number of milliseconds, then continues | next |
| HTTP | I/O | Component | Calls an external API and stores { status, ok, body } | next, error |
| I/O | Component | Sends a transactional email via Resend | next, error | |
| MongoDB | I/O | Component | Reads or writes a MongoDB collection | next, error |
| SQL | I/O | Component | Reads or writes a Postgres database | next, error |
| Google Sheets | I/O | Component | Appends a row to or reads a range from a Google Sheet | next, error |
| Stripe | I/O | Component | Creates a Stripe Checkout session to take a payment | next, error |
| Slack | I/O | Component | Posts a message to a Slack channel via an incoming webhook | next, error |
| SMS | I/O | Component | Sends a text message via Twilio | next, error |
| AI | AI | Component | Sends a prompt to a Claude model and stores the reply | next, error |
Built-in nodes run entirely inside the engine — no network, no external service.
I/O nodes reach out to the world (an API, a database) and can fail for reasons outside your flow, which is why each carries an error port.
Component nodes are also I/O, but they are not part of the engine: they are installable components, published and signed separately and run in a sandbox that can only reach the hosts their manifest declares. Every workspace gets the first-party set installed automatically, so they work out of the box — and unlike a built-in, you can update, remove, or replace one without waiting for a FlowRunner release.
NOTE
If a component node is not installed in your workspace, it does nothing at run time — the node passes straight through on its default port. The editor marks uninstalled nodes in the Add panel; open Components in the project header to install one.
The error port is universal
Any non-terminal node that fails follows the same rule:
- If you have wired a connection from its
errorport, the failure is routed there — a try/catch branch you control — and the flow keeps running. - If nothing is wired to
error, the node falls through on its default port (next, orfalsefor If), and an unhandled failure surfaces as a top-level500response.
On any failure the engine also writes error.message and error.nodeId into refs, so an error-handling branch can read what went wrong.
Reading the values a node produces
Each node stores its result under a variable you name (resultVar, var, itemVar) with a sensible default. Downstream, reference a field with variable.field:
text
start.email # a request input
response.status # from an HTTP node with resultVar: response
result.value # a scalar wrapped by Set / Template / Mongo
error.message # set whenever a node fails