Workflow Nodes
Overview
A workflow is a chain of nodes (steps). This page covers every node in the builder’s Add a step palette: what it does, what you set in the inspector, and what it passes on.
| Group | Nodes |
|---|---|
| Triggers | Manual Trigger, Webhook, Schedule |
| AI | Agent, LLM Model |
| Actions | Tool, Connector, HTTP Request, Sub-workflow |
| Logic | IF, Switch, Merge, Loop |
| Data | Set Fields, Split Out, Aggregate, Filter |
| Code | Code, Sandbox |
| Output | Result |
| Agent parts | Memory, Knowledge, Guardrails, Output Format |
How data moves between nodes
Each node gets a list of items from the node before it, and passes a list of items on. An item is one JSON object.
- Most nodes run once per item. If a step gets 5 items, a Tool node calls the tool 5 times.
- Split Out turns one item into many. Aggregate turns many items into one.
- In any field that accepts expressions,
{{$json.field}}reads from the current item and{{$node["Step Name"].json.field}}reads from an earlier step. See Referencing earlier data.
Triggers
A trigger is the first node and decides how the workflow starts. A workflow has exactly one. Once you’ve added one, the palette greys out the others.
Manual Trigger
Starts the workflow when you click Run.
| Setting | What it does |
|---|---|
| Input | JSON handed to the next step when you click Run. Use it to seed test data. |
Webhook
Starts the workflow when an external system sends an HTTP POST.
| Setting | What it does |
|---|---|
| Webhook URL | Generated when you save. POST any JSON body here to run the workflow. Copy it, or copy the ready-made curl command. |
| Sample input | Used when you click Run in the builder. A real POST body replaces it. |
Schedule
Starts the workflow on a timer.
| Setting | What it does |
|---|---|
| Schedule type | Every N minutes, Daily at time, or Weekly. |
| Interval | For Every N minutes. The minimum is 1. |
| Day of week | For Weekly. |
| Run at | For Daily and Weekly, as HH:MM in UTC. |
| Input | JSON handed to the next step on each run. |
For more detail, see Triggers.
AI
Agent
Runs an AI agent that can reason and call tools. An Agent node works one of two ways:
- A saved agent: click Agent and pick one of your Rival Agents.
- A custom agent built here: leave the picker empty (or click Build a custom agent instead), then fill in:
- Agent Name
- Instructions: who the agent is and what it must do. This is its system prompt.
Both kinds have:
| Setting | What it does |
|---|---|
| Prompt | The message sent to the agent for each item. Supports {{$json.field}}. |
| Publish artifact to a share link | Turns a file or page the agent creates into a link a later step can email or post. Choose who can open it: My organization (signed-in members) or Public (anyone with the link). Only works with a saved agent. |
Ports. An Agent node has ports along its bottom edge. Drag from a port to attach other nodes that configure the agent:
| Port | Attach | Custom agent | Saved agent |
|---|---|---|---|
| model | An LLM Model node, to choose the model | Yes | Yes, for this step only |
| tools | Tool, Connector, HTTP Request, Code, Sandbox, or Sub-workflow nodes the agent may call | Yes | Yes, added to its own tools |
| memory | A Memory node | Yes | Yes |
| knowledge | Knowledge nodes | Yes | Yes |
| guardrails | A Guardrails node | Yes | No |
| output | An Output Format node | Yes | No |
| sub-agents | Other Agent nodes it can hand work to | Yes | No |
A saved agent keeps its own guardrails, output format, and sub-agents, so you edit those on the agent itself. On a custom agent, the Made of list in the inspector shows everything attached. With no model attached, the agent uses the platform default model.
Using a node as a tool. When you attach a node to the tools port, its inspector adds:
- Tool name: what the agent calls it. Defaults to the node name.
- What this tool does: the agent picks tools based on this text alone. Required for every node except Tool, which already describes itself.
- Arguments the model supplies: a JSON Schema. Fields you leave blank on the node are the ones the agent fills in.
Output: {{$json.text}}, the agent’s answer. With an Output Format attached, the fields of the JSON answer sit at the top level instead (for example {{$json.category}}).
LLM Model
Makes one call to a language model: summarize, classify, extract, or rewrite. There are no tools or memory, so it’s faster and cheaper than an Agent.
| Setting | What it does |
|---|---|
| Model | Pick a model, or Platform default. Models under Rival run on Rival’s key. Models under Bring your own key need your own API key. |
| Use my own API key | Run on your provider account. Set an optional Endpoint and an API key. Some providers, such as Claude and OpenAI, always need one. |
| System prompt | Optional instructions, for example “You are a strict JSON extractor.” |
| Prompt | The request. Supports {{$json.field}}. |
Under Advanced:
- Temperature, Max tokens, Top P, Top K
- Frequency penalty and Presence penalty
- Seed, Timeout (s) (up to 300), and Max retries (up to 5)
- Response format: Text, JSON object, or JSON schema (then enter the schema)
- Stop sequences, one per line
- Reasoning effort: Low, Medium, or High. Models that don’t support it ignore it.
- Safety settings: Gemini models only
Output: {{$json.text}}, plus model, finish_reason, and usage.
As an agent’s model. When you attach an LLM Model node to an Agent’s model port, the prompt fields disappear. The agent writes the prompts, and this node only supplies the model, the key, and the sampling settings.
Actions
Tool
Runs a tool from the Marketplace or your organization.
| Setting | What it does |
|---|---|
| Tool | Pick the tool. |
| Secrets | If the tool needs external keys, choose which of your organization’s secrets supplies each one. |
| Operation | For tools with more than one operation, pick one. Its input fields appear below. |
| Input fields | Type a value, or use {{$json.field}} to pull data from an earlier step. Advanced lets you edit the raw JSON input. |
The node runs the tool once per incoming item. If the tool reports a failure in its response, the step fails.
Output: the tool’s response.
Connector
Runs an operation on a third-party account, such as Gmail, Slack, or Google Sheets.
| Setting | What it does |
|---|---|
| Provider | Pick the service. |
| Connect | Sign in to the service. You need to save the workflow first. Each workflow has its own connection. |
| Operation | Appears once the connector is connected. For example: send an email, or append a row. |
| Input fields | The operation’s parameters. Supports {{$json.field}}. |
Output: the service’s response. See Connectors for how connections work.
HTTP Request
Calls any REST API.
| Setting | What it does |
|---|---|
| Method | GET, POST, PUT, PATCH, or DELETE. |
| URL | The endpoint. Supports {{$json.field}}. |
| Headers | A JSON object. Values support {{$json.x}}. |
| Query params | A JSON object. |
| Body type | For POST, PUT, PATCH, and DELETE: JSON, Raw text, or None. |
| Body | The request body. |
Runs once per incoming item. Requests to private or internal addresses are blocked.
Output: { statusCode, headers, body }.
Sub-workflow
Runs another of your workflows as one step.
| Setting | What it does |
|---|---|
| Workflow to run | Pick the workflow. |
Output: the output of the other workflow’s last step.
Logic
IF
Splits the flow in two. Connections leaving an IF node have the Branch true or false.
Build the condition in plain terms:
- If this field…: a field from the previous step, such as
result.body.status. - …is / compares: is, is not, is greater than, is less than, is empty, or is not empty.
- …this value: what to compare against.
For anything more complex, click Advanced and write the expression yourself, for example $json.total > 500.
Output: the incoming items, unchanged, sent down the matching branch.
Switch
Splits the flow several ways based on one value.
| Setting | What it does |
|---|---|
| Value expression | What to check, for example $json.status. |
| Cases | A comma-separated list, for example open, pending, closed. |
Give each outgoing connection a Branch that matches a case. If no case matches, the items go to the default branch.
Output: the incoming items, unchanged, sent down the matching branch.
Merge
Joins two or more branches back into one flow. Connect every branch into this node.
| Setting | What it does |
|---|---|
| Mode | Append combines all incoming items into one list. By key merges items that share a field value into one item. |
| Key field | For By key: the field to match on, for example id. |
Loop
Repeats a group of steps once per item.
A Loop node has two outputs:
- loop: connect the steps to repeat. They run once for each item.
- done: runs once after the last pass. It gets the results of every pass.
| Setting | What it does |
|---|---|
| List to repeat over | An expression for the list, for example {{$json.articles}}. Leave it blank to repeat once per incoming item. |
| Field name for plain values | If the list holds strings or numbers, each one goes under this field name. Objects pass through as they are. |
| Items per pass | How many items each pass handles. Defaults to 1. |
| Maximum passes | A safety limit: the run fails instead of looping forever. Defaults to 100, and can’t go above 1000. |
| Collect from | The step inside the loop whose output is collected. Leave it blank to use the last step. |
| Keep going when one pass fails | Continue with the next pass instead of stopping the run. |
Inside the loop you can use {{$loop.index}}, {{$loop.total}}, {{$loop.first}}, and {{$loop.last}}. Loops can be nested up to 3 deep.
Data
Set Fields
Adds, renames, or reshapes fields on each item.
| Setting | What it does |
|---|---|
| Assignments | A JSON list of { "name": ..., "value": ... }. Values support {{$json.field}}. |
| Output only these fields | Off: add these fields to the incoming data. On: pass on only these fields and drop everything else. |
[ { "name": "email", "value": "{{$json.contact.email}}" }, { "name": "source", "value": "webhook" }]Split Out
Turns one item that holds a list into one item per list entry, so the next step runs once per entry.
| Setting | What it does |
|---|---|
| Field to split | The list field, for example items or $json.data.rows. |
| Destination field | For lists of strings or numbers, the field name each value goes under. Defaults to the list’s field name. |
| Carry the parent’s other fields onto each item | Copy the item’s other fields onto every new item. |
If an item doesn’t have the field, or the field isn’t a list, the item passes through unchanged.
Aggregate
Collapses all incoming items into a single item. It’s the opposite of Split Out.
| Setting | What it does |
|---|---|
| Field to collect | Collect only this field from each item. Leave it blank to collect each whole item. |
| Output field | The field that holds the collected list. Defaults to data. |
Output: one item, for example { "data": [ ... ] }, even when no items arrived.
Filter
Keeps only the items that match a condition and drops the rest.
| Setting | What it does |
|---|---|
| Keep items where… | A condition, built the same way as the IF node. Blank keeps everything. |
If nothing matches, the next step receives no items.
Code
Code
Runs a short JavaScript snippet over the items, directly inside the workflow.
| Setting | What it does |
|---|---|
| Run | Once for all items: items is the full list. Once per item: $json is the current item. |
| JavaScript | Must return the output. Return a list to produce one item per entry, or an object to produce one item. |
// Once for all itemsreturn items.map(x => ({ ...x, seen: true }));
// Once per itemreturn { greeting: "hi " + $json.name };Code runs sandboxed, with no network, no file access, and no packages, and has a 5-second time limit. For anything heavier, use Sandbox.
Sandbox
Runs a script on a temporary machine with a real file system, packages, and network. The machine is destroyed when the step ends.
| Setting | What it does |
|---|---|
| Language | Python, Node, or Bash. The script is saved as main.py, main.js, or main.sh. |
| Run | Once for all items or Once per item. |
| Script | Your code. Print the result. |
Before your script runs, these happen in order:
- Files are written: a JSON map of path to contents, such as a
requirements.txtor an input CSV. Contents support{{$json.x}}. - Packages are installed with pip, npm, or apt. Version pins are fine.
- Setup commands run, such as
apt-get install -y ffmpeg. If one fails, your script doesn’t run.
Other settings:
| Setting | What it does |
|---|---|
| Environment variables | Available to setup and your script. Values support {{$json.x}}. |
| Files to read back | Files your script writes, returned as {{$json.artifacts}}. |
Under Machine & overrides:
- Machine: Small (0.5 CPU / 512MB), Medium (1 CPU / 1GB), or Large (2 CPU / 4GB).
- Compute: CPU or GPU.
- Timeout and Setup timeout, in seconds.
- Command: replaces the default run command, for example
python3 main.py. - Keep going when the script exits non-zero
Output: stdout, stderr, exit_code, duration_ms, and timed_out. If your script prints a JSON object, it’s also available as {{$json.stdout_json}}.
Output
Result
Prints a value to the run log. Use it to see what a step produced, or to show a final message.
| Setting | What it does |
|---|---|
| Message to print | Supports {{$json.field}}, for example Status is {{$json.result.statusCode}}. Leave it blank to print the incoming data. |
Output: { "result": "<the message>" }.
Agent parts
Agent parts appear under Agent parts in the palette. They configure an Agent node and don’t run as steps. Add one, then connect it to the matching port on an Agent. A workflow won’t save with an agent part that isn’t connected.
Memory
Lets the agent remember earlier exchanges.
| Setting | What it does |
|---|---|
| Where to keep it | This run only: kept in memory, and lost when the run ends. Stored: saved, so it lasts between runs. |
| Turns to remember | How many earlier exchanges to keep. Defaults to 10, up to 100. |
| Session key | Optional. Set it to something from the item, like {{$json.customer_id}}, and the agent continues the same conversation the next time that key appears. Leave it blank and memory only lasts one run. |
Knowledge
Gives the agent reference material.
| Setting | What it does |
|---|---|
| Title | A label, for example “House style”. |
| Knowledge base | Attach files: PDF, Word, Excel, PowerPoint, text, Markdown, CSV, JSON, RTF, or images. Each file is read and indexed once. When the workflow runs, the agent gets the parts relevant to each item. Save the workflow first so files can be indexed. |
| Notes | Short facts, rules, or examples included in full on every turn. Put anything long in a file instead. |
Guardrails
Controls which actions the agent may take on its own. Set each category to Allow, Ask first, or Block:
- Sending externally: email, Slack, CRM writes, anything that leaves the organization
- Deleting or overwriting: removing records or replacing files
- Spending money: payments, refunds, purchases
- Writing data: creating or updating records
Nobody is watching a running workflow to approve an action, so Ask first and Block both stop it. Reading data is never restricted.
Output Format
Makes the agent answer as JSON, so later steps can use individual fields instead of parsing text.
| Setting | What it does |
|---|---|
| JSON schema | The shape of the answer. |
| Schema name | Some providers require a name. Blank is fine. |
{ "type": "object", "properties": { "category": { "type": "string", "enum": ["billing", "bug", "other"] }, "summary": { "type": "string" } }, "required": ["category", "summary"]}With this attached, a later step can use {{$json.category}} directly, for example as a Switch value.
Choosing the right node
Pick the simplest node that does the job:
- A Connector or Tool before an Agent, when one already does the work.
- An LLM Model before an Agent, when the step needs no tools or memory.
- Set Fields before Code, and Code before Sandbox.