Node reference
Every node you can add to a workflow, grouped the way the builder palette groups them: Triggers, Integrations, AI, Flow, and Core (with its Tables section). Each entry gives the node's key, ports, main parameters, and the output fields you can reference.
How to read this reference
A node's key is a prefix plus its normalized name. The prefix depends on the node family: trigger:, mcp: (integration steps), agent: (AI nodes), core:, table:, interface:, and note:. The name is lowercased, accents are transliterated, every other character becomes _, and repeats and edges are trimmed. A node you name Fetch Orders is therefore core:fetch_orders, and you read its output with {{core:fetch_orders.output.<field>}}. See Expressions for the full syntax.
Ports exist only on branching nodes. When you wire an edge from a port, you address it as key:port, for example core:check:if or agent:route:category_0. Numbered ports start at 0.
Outputs listed here are the fields a node stores after it runs. Only these declared fields are kept, so they are the ones you can reference downstream. The inspector may show extra run details (such as the resolved parameters) that are not part of the output.
Triggers
A trigger starts a run. A workflow can have several triggers, and each one drives its own part of the graph. Configuration details for each trigger are on the Triggers page.
| Palette name | Starts a run when | Main outputs |
|---|---|---|
| Webhook | An HTTP request reaches the workflow URL. | One field per body key, plus _webhookMethod, _webhookTimestamp, triggered_at, triggered_by |
| Manual | Someone runs the workflow on demand. | triggered_at, triggered_by |
| Tables | A row changes in a built-in table. | row, previous_row, event_type, row_id, triggered_at |
| Workflows | Another workflow finishes a cycle with no failed step. | parentWorkflowId, parentRunId, parentStatus, result, parentStatistics |
| Error | A cycle of the workflow it watches has a failed step. | parentWorkflowId, parentRunId, status, errorMessage, failedSteps, completedSteps, totalSteps, skippedSteps |
| Chat | A chat message arrives (optionally matching a rule). | message, extracted_message, conversation_id, attachments, matched |
| Scheduler | Its cron schedule comes due (at most once a minute). | triggered_at, execution_count, next_execution |
| Form | A custom form is submitted. | submission_id, submitted_at, form_data |
A webhook's request body fields sit directly under output, so a body field is {{trigger:webhook.output.userId}}, with no payload key in between. Request headers are not passed to the workflow.
Workflows and Error triggers
Both react to another workflow, which you pick when you add them. The Workflows trigger fires when that workflow finishes a cycle without a failed step. The Error trigger fires when a cycle of that workflow has a failed step, and hands you the failure details (errorMessage, failedSteps, and the step counts). A failing error-handling workflow does not set off other error handlers.
Integrations
The Integrations tile opens the app picker (Gmail, Slack, Notion, and hundreds more). Choosing an operation adds an integration step, keyed mcp:<name>. It calls that one operation with the credential you connected. Its parameters and output fields are those of the chosen operation, shown in the inspector. See Integrations.
AI
AI nodes call a model and use the agent: prefix. See Agents for models, tools, and budgets.
| Palette name | What it does | Ports | Main outputs |
|---|---|---|---|
| Agents | Reasons over a prompt and can call tools to produce a result. | None | response, tokens_used, tool_calls, iterations_used, model, provider |
| Guardrail | Checks content for PII, toxicity, or keywords, then passes or fails it. | pass, fail | passed, violations, details, sanitized |
| Classify | Routes the input to exactly one category by meaning. | category_N | selected_category, selected_category_index, confidence, reasoning, probabilities |
| Browser Agent | Drives a browser: navigates, fills forms, extracts structured data. | None | final_result, extracted_data, stop_reason, final_url, pages_visited, screenshots |
| Generate | Produces an image, video, audio, voice, or music clip from a prompt. | None | file, model, kind, provider, billed_quantity, billed_unit, billed_credits |
Generate
Pick an asset type and a Model. The model decides the format produced, which parameters are accepted (prompt, duration, aspect ratio, resolution, voice, input images, and so on), and what each run costs; the price is shown before you run. The result is always a file: output.file is a file reference you can pass whole to a later file parameter, and kind says what was produced. The same models are available in Studio.
Flow
Flow nodes route, repeat, parallelize, and join. For how branches, merges, and parallel items behave at run time, see Workflows.
| Palette name | What it does | Ports | Main outputs |
|---|---|---|---|
| If / else | Takes the first branch whose condition is true (exactly one). | if, elseif_N, else | selected_branch, selected_branch_index, skipped_branches, evaluations |
| Switch | Takes the first case that matches a value, or the default. | case_N, default | selected_branches, selected_case_index, skipped_branches, evaluations |
| Split | Runs the steps after it once per list item, in parallel. | None | items, item_count, split_id, spawn_reason, terminated |
| Aggregate | Collects the per-item results of a Split back into lists. | None | aggregated_count |
| While | Repeats a group of steps while a condition is true. | body, exit | iteration, maxIterations, terminated, selected_path, reason |
| User Approval | Holds back the steps after it until a person approves, rejects, or the timeout passes. | approved, rejected, timeout | approval_context, selected_port, expires_at, required_approvals, delegated_channel |
| Transform | Computes new fields from expressions. | None | transformed, evaluations |
| Merge | Waits for every incoming branch, then continues once. | None | merged_branches, sources, merged_items, source_count, success_count |
| Fork | Runs every branch in parallel. | branch_N | branch_count, branches |
| Sub-Workflow | Triggers another workflow and waits for its result. | None | result, subWorkflowId, subRunId, success, failed_steps |
If / else and Switch
Both take exactly one path. If / else checks its conditions in order (if, then elseif_0, elseif_1, and so on) and falls back to else. Switch compares one value against its cases and falls back to default. Every path not taken is skipped. The evaluations output shows how each condition resolved, which is the fastest way to see why a branch was chosen.
The AI builder can also add an Option node (first true choice wins, ports choice_N). It is not in the palette, but it runs normally when a plan contains it.
Split
Give Split a list expression. Every step after it runs once per item, in parallel, and inside those steps {{core:<split>.output.current_item}} and current_index hold the item being processed. Those two fields exist only inside the split; they are not stored on the Split node itself.
- Max items defaults to 100. Items beyond the cap are dropped. It accepts an expression, which must resolve to a positive whole number or the node fails.
spawn_reasonisitems_spawned, orempty_listwhen there was nothing to process.terminatedis alwaystrue: Split finishes as soon as it has handed out the items.
Aggregate
Aggregate closes a Split: it waits for every item and returns one list per field you configure, plus aggregated_count.
While
While runs the steps on its body port, then evaluates its condition again. The last body step connects back to the node's iterate input. When the condition is false the loop leaves through exit. iteration starts at 0.
- Max iterations defaults to 10 and accepts 1 to 10,000 (or an expression that resolves to a positive whole number).
reasontells you how it ended:condition_false(normal),iterations_exhausted(no condition, so it ran the set number of times), ormax_iterations_reached.
User Approval
The nodes after it wait while the approver sees the request in the app; branches that do not depend on it keep running. The node continues on approved, rejected, or timeout. The timeout defaults to 24 hours. You can require several approvals and restrict who may decide by role.
- Approval context: text mixed with
{{...}}expressions, shown to the approver. The resolved text is also theapproval_contextoutput. - Continuation (only inside a Split, where each item gets its own request): After all items (the default) starts the next steps once every item has been decided. Per item (immediate) lets each decided item continue immediately; a Merge after it still waits for all items.
- Delegate via external channel: also sends the request to Telegram, Slack, Discord, WhatsApp, or Microsoft Teams with approve and reject buttons. Pick a Destination like a credential (the workspace default, a connected destination, or another chat by hand). You can set a message template, an image (for example an interface screenshot), custom button labels, and a list of allowed user IDs. The in-app decision keeps working in parallel. See Channels.
Merge and Fork
Fork starts every connected branch at once. Merge waits until every incoming branch has finished or been skipped, then continues once. Most nodes with several incoming edges wait the same way, and any node with several outgoing edges fans out the same way. Edges from triggers are the exception: a node fed by several triggers runs once on each trigger run, without waiting for the other triggers. If / else, Switch, Option, Classify, Guardrail, User Approval, Split, Fork, and While accept a single incoming edge, an edge from a trigger included (a loop edge back into them does not count), so put a Merge in front of them to join branches or several triggers. When the assistant builds through chat, every core: node except Merge must have exactly one incoming edge, or edges from triggers only.
Transform
Each field you define is an expression. The results are under transformed, so a field named total is {{core:<label>.output.transformed.total}}. An object built in a Transform reaches later steps as text; when a later parameter needs a real object or list, build it in a Code node.
Sub-Workflow
Sub-Workflow fires a trigger in another workflow (the child), passes it an input, and waits for that child run to finish. Parameters: Workflow ID, Input mapping (one expression that resolves to the object to pass; empty forwards this workflow's trigger data), Timeout (seconds), and Max depth.
- The child needs a live run. The node never creates one. Pin a version of the child (which creates its run); an unpinned child uses its most recently started active run, whatever its version.
- Outputs are keyed by the child step's bare name. A child Transform named Step Result is read as
{{core:call.output.result.step_result.output.transformed.field}}, without acore:prefix beforestep_result. With the prefix the expression resolves to nothing, silently. - A failed child step fails this node. Whenever a step of the child's cycle fails, also one that ran after an agent in the background, a wait or an approval, the node fails with
successset tofalse, andfailed_stepslists the child steps that failed. - Timeout defaults to 300 seconds and is capped at 1,500. It only limits how long this node waits; the child keeps running. Max depth defaults to 5 (at most 10), and a workflow cannot call itself in a cycle.
- When the timeout passes, the node fails and nothing after it runs. A child that pauses on a User Approval or on an interface waiting for the user to continue cannot finish on its own inside the call, so put those steps in the calling workflow.
Core
Core holds everything else. The tables below follow the palette, grouped by purpose. Detail entries for several of these nodes follow the tables.
Run control and replies
| Palette name | What it does | Main outputs |
|---|---|---|
| Exit | Ends the branch it sits on. Other branches keep running. | exited_at, reason, status |
| Stop on Error | Fails the whole run and cancels every branch. | error_message, error_code, stopped_at, status |
| Wait | Holds back the steps after it for a duration, then continues on its own (see note). | waited_ms, status, started_at, completed_at, duration_ms, expires_at |
| Respond to Chat | Sends one message (a template) back to the chat that started the run. | message, sent_at, message_id |
| Respond to Webhook | Answers the HTTP caller of a Webhook trigger: status, content type, headers, body. | responded, statusCode, contentType |
| Interface | Shows a web page built from workflow data; can hold back the steps after it until the user continues. | interface_id, screenshot, pdf, video |
| Note | An annotation on the canvas. It never runs. | None |
HTTP, files, and media
| Palette name | What it does | Main outputs |
|---|---|---|
| HTTP Request | Calls any URL (see note). | success, status, statusText, data, headers, error |
| Download File | Fetches a file from an http or https URL (up to 100 MB, received within 60 seconds) into storage. | file, source_url |
| Public Link | Turns a file into a public, time-limited signed URL (see note). | url, expires_at, ttl_minutes, file |
| Media | Processes audio and video files (see note). | file, duration_seconds, size_bytes, has_video, has_audio, video, audio |
| Data Input | Provides labeled text, file, and image inputs; each is output under its own label. | One field per input label |
| Convert to File | Writes items to a CSV, XLSX, JSON, or TXT file. | file, format, row_count, success |
| Extract From File | Reads a file into items or text (see note). | items, format, rowCount, columns, mode, total_chunks |
| Compression | Compresses or decompresses zip, gzip, or deflate data. | result, file, operation, format, success |
Data
| Palette name | What it does | Main outputs |
|---|---|---|
| Filter | Keeps the items that match conditions (equals, contains, greater than, is empty, and more). | items, rejected_items, count, rejected_count, original_count |
| Sort | Orders items by a field. | sorted_items, count |
| Limit | Keeps the first or last N items. | items, count, original_count |
| Remove Duplicates | Drops items that repeat on the chosen fields. | items, original_count, deduplicated_count, removed_count |
| Summarize | Count, sum, average, min, max, count distinct, or concatenate, optionally grouped by fields. | groups, total_groups, total_items, aggregation_count |
| Compare Datasets | Compares two lists on key fields. | matched, onlyInA, onlyInB, matchedCount, totalA, totalB |
| Set / Edit Fields | Assigns fields with a type (string, number, boolean, JSON). | fields, output, keep_only_set, count |
| HTML Extract | Pulls structured data out of HTML with CSS selectors. | items, count, matched_root, errors |
| XML | Converts XML to JSON or JSON to XML. | result, operation, success |
Code, messaging, and utilities
| Palette name | What it does | Main outputs |
|---|---|---|
| Code | Runs JavaScript, Python, TypeScript, or Bash in a sandbox (see note). | result, stdout, stderr, exitCode, success |
| Send Email | Sends an email with your SMTP credential. | sent, messageId, recipients, subject, success |
| Email Inbox | Reads a mailbox over IMAP, or marks read or unread, flags, moves, or deletes a message. | messages, count, folders, action, success |
| RSS | Fetches and parses an RSS or Atom feed. | items, channel, itemCount, feedFormat, success |
| Crypto / JWT | Hash, HMAC sign and verify, encrypt and decrypt, create, decode, and verify JWTs, Base64, UUIDs, and random secrets. | result, operation |
| Date & Time | Parse, format, convert time zones, add, subtract, compute differences, extract parts, or get the current time. | result, operation |
| Task | Creates, reads, updates, deletes, or lists agent tasks. | task, task_id, tasks, count, success |
| Page | Creates, appends to, replaces, reads, renames, or finds the pages of the workspace (see note). | page_id, title, url, markdown, text, pages, count, success |
Remote systems
| Palette name | What it does | Main outputs |
|---|---|---|
| SSH | Runs a command on a remote server. | success, exit_code, stdout, stderr, duration_ms |
| SFTP | Uploads, downloads (up to 100 MB), lists, deletes, renames files, or creates folders. | success, operation, remote_path, files, file, new_path |
| Database | Runs select, insert, update, delete, or raw SQL on PostgreSQL, MySQL, or MSSQL (up to 10,000 rows). | success, rows, columns, row_count, affected_rows |
Exit and Stop on Error
Exit ends only its own branch; the run can still succeed. Its reason defaults to “Branch exited” and status is exited. Stop on Error fails the whole run with your error message and code.
Wait
In the canvas you enter the duration in milliseconds, up to 10 minutes. A wait of 3,000 ms or less runs inline. A longer wait holds back the nodes after it and resumes them on a timer; the other branches of the run keep running.
HTTP Request
Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Authentication: none, basic, bearer, API key, or a custom header. An optional timeout is available.
The node reads at most 10 MB of a response. A larger successful answer fails the node, and the error says so (with its size when the server declared one). A larger error answer keeps its status, with an empty output.data. Ask the API for less with pagination or filters, or fetch a file with Download File, which stores it.
Download File, Public Link, and file references
Download File follows redirects (each hop is checked again) and returns file, a file reference with path, name, mimeType, and size. Pass the whole reference to a file parameter with {{core:<label>.output.file}}. See Files & storage.
Public Link signs a file from an earlier node into a public URL that anyone can open until it expires, for APIs that pull media from a URL (Instagram, TikTok) instead of accepting an upload. Link lifetime is 5 to 10,080 minutes (7 days), 240 by default. Disposition is inline (shown in the browser) or attachment (download prompt). A link cannot be revoked before it expires.
Media
Operations: Probe (read duration, streams, codecs), Mux audio (one audio track onto one video), Mix (up to 8 audio tracks, optionally onto a video), Extract audio, Concat (up to 8 videos back to back, with cut or crossfade), Frame (one still image, the middle by default), Overlay (burn an image onto a video), and Burn captions.
- Every file parameter must be one whole expression that resolves to a file reference, such as
{{core:download.output.file}}. - The Concat clip list is fixed in the node (one entry per clip); it cannot come from a single list expression.
- The node fails when the media renderer is not available on your installation.
Convert to File and Extract From File
Convert to File writes csv, xlsx, json, or txt. Extract From File parses csv, xlsx, and json into items, or extracts the text of a pdf, html, docx, txt, csv, or json file, optionally split into chunks (recursive or by separator, with a chunk size and overlap). For XML, use the XML node.
Code
Upstream results arrive in $input (JavaScript and TypeScript), _input (Python), or INPUT (Bash), keyed by each earlier node's normalized name: a file from Download Demo Video is $input.download_demo_video.file, not $input.file. Return data by assigning $output (or _output in Python). The timeout defaults to 10 seconds, up to 120.
What you return is stored under result, so downstream you read {{core:<label>.output.result.<field>}}. Values keep their types, which makes Code the right place to build objects, lists, or file references for later steps.
{{core:normalize.output.result.total}} the "total" field of the returned object
{{core:normalize.output.stdout}} anything the script printedPage
Operations: Create a page, Append to a page (adds markdown at the end), Replace a page's content (everything the page held is replaced), Read a page, Rename or change the icon, and Find pages. The content you write is markdown: headings, lists, checklists, tables, and links are kept.
- The node acts as the workflow's owner, in the workspace of the run. It sees and changes only the pages the owner can: a page the owner cannot see is reported as not found, and a page the owner can only read refuses every operation that writes.
- Page takes a page id, or the page of an earlier Page node:
{{core:<label>.output.page_id}}, or{{core:<label>.output.pages[0].page_id}}after a Find. It is required for every operation except Create and Find. - Create a page accepts a Title, the content, an Icon (an emoji), a Parent page (the new page becomes its sub-page and joins its project), a Project to file a top-level page in, and a Template page to start from a copy of that page (content, icon, sub-pages). When you give both a template and content, the content replaces the copied content. A project the owner cannot change fails the node, and no page is created.
- Rename or change the icon needs a title or an icon. An empty icon removes the page's icon.
- Find pages searches the words of Search in titles and text; left empty, it returns the most recently edited pages first. You can narrow it to the sub-pages of a Parent page or to the pages of a Project. Max results is 1 to 200, 20 by default. The matches come back as one list in
pages, with their number incount; the steps after the node run once, not once per page. - Someone who has the page open sees it reload with the new content after an append or a replace.
- An append or a replace fails when the page is in the trash or locked, or when it would make the page too large.
Every operation except Find returns the page: page_id, title, icon, url (a link to the page in the app), markdown and text (the whole page after the write, as markdown and as plain text), parent_id, project_id, created_at, and updated_at. Read a page also returns children, the sub-pages the owner can see. Each item of children and pages carries page_id, title, icon, url, excerpt, parent_id, project_id, has_children, and updated_at.
{{core:create_report.output.url}} a link to the page that was written
{{core:read_brief.output.markdown}} the page as markdown, for example in an agent prompt
{{core:find_log.output.pages[0].page_id}} the first page a Find returnedTables
The Tables section of Core reads and writes the built-in tables. These nodes use the table: prefix. See Tables & data for columns and query options.
| Palette name | What it does | Main outputs |
|---|---|---|
| Create Row | Inserts one or more rows. | row_id, created_at, inserted_count, inserted_values, warnings |
| Create Column | Adds columns to a table. | createdColumns |
| Get Row | Returns matching rows as one output. | rows, row_count, has_more, offset |
| Update Row | Updates the rows that match a condition. | updated_count, rows_affected, updated_at, warnings |
| Delete Row | Deletes the rows that match a condition (a condition is required). | deleted_count, rows_affected, deleted_at |
| Find Rows | Queries rows into a list. | items, item_count, total_before_limit, max_items, has_more, exit_reason |
Find Rows
Find Rows returns its matches as one list in items. It does not run the following steps once per row. To process each row, add a Split on {{table:<label>.output.items}}. It keeps 100 rows by default. You can set a higher limit, but one read returns at most 500 rows, so a limit above 500 behaves like 500. With the default limit, has_more tells you whether rows were left out; with a limit you set, compare item_count to that limit instead. exit_reason is items_found or empty_result.