Workflows are started by trigger nodes or entry points. Each trigger type has its own endpoint or background process.
Trigger Nodes
Start nodes (no incoming edges) that initiate execution:
| Node Type | Description |
|---|---|
| Input (textInput) | HTTP entry point. Receives body, headers, query from requests. |
| Cron | Runs on a schedule (cron expression, e.g. 0 * * * * for hourly). |
| Telegram Trigger | Starts when Telegram sends a bot webhook update to the node-specific webhook URL. |
| Discord Trigger | Starts when Discord sends an Interactions API webhook to the node-specific endpoint. |
| IMAP Trigger | Polls an IMAP mailbox and starts once for each newly detected email. |
| Google Drive Trigger | Polls a Drive folder or file and starts once per created, updated, or deleted file. |
| Google Sheets Trigger | Polls a sheet tab and starts once per added, updated, or deleted row. |
| Heym Trigger | Starts when Heym publishes a platform event. Events in one dispatch window arrive together as an array. |
| WebSocket Trigger | Opens an outbound client connection to an external socket and starts on selected socket events. |
| File Upload Trigger | Mints a single-use upload URL and starts when a caller posts a large multipart file. |
| RabbitMQ (receive) | Starts when a message is consumed from a RabbitMQ queue. |
| Slack Trigger | Starts when Slack sends an event via the Events API webhook. |
Entry Points
| Trigger | Endpoint / Source | Auth |
|---|---|---|
| Webhook/API | POST /api/workflows/{id}/execute | anonymous / jwt / header_auth |
| MCP | POST /api/mcp/tools/call, /message, /sse | X-MCP-Key header or Authorization: Bearer (headers only) |
| Portal | POST /api/portal/{slug}/execute | Portal session token |
| Board | Board card move / follow-up run into a column with a workflow chain (trigger_source="board") | JWT (board owner) |
| Cron | Cron scheduler (runs every 60s, evaluates cron expressions) | N/A |
| IMAP | IMAP trigger manager (leader worker, per-node polling interval) | IMAP username/password |
| Google Drive / Sheets | Google trigger poller (leader worker, per-node polling interval) | Google OAuth2 credential |
| WebSocket | Outbound WebSocket trigger manager (leader worker, persistent client connections) | Optional per-node headers |
| File Upload | POST /api/file-intake/u/{token} after a slot is minted | Single-use capability token |
| RabbitMQ | RabbitMQ consumer (leader worker) | N/A |
| Slack | POST /api/slack/webhook/{node_id} | HMAC-SHA256 signing secret |
| Discord | POST /api/discord/webhook/{node_id} | Ed25519 application public key |
| Telegram | POST /api/telegram/webhook/{node_id} | Optional x-telegram-bot-api-secret-token |
| Editor | Same as Webhook, via workflowStore.executeWorkflow | JWT |
Webhook / API
- Endpoint:
POST /api/workflows/{workflow_id}/execute - Input: Request body is passed as
bodyto textInput nodes - Body mode: Workflows can use
definedfield-shaped examples orgenericraw JSON examples in the editor and cURL dialog - Auth: Configured per workflow (
auth_type,allow_anonymous)
See Webhooks for details on TTL, cache, rate limiting, and auth.
MCP
Workflows with mcp_enabled=true appear as tools to MCP clients. Tool name is derived from the workflow name. See MCP Tab.
Portal
Public chat UI at /chat/{slug}. See Portal for details.
Cron
The cron scheduler runs every 60 seconds, finds workflows with active cron nodes, evaluates cron expressions, and runs matching workflows. Input includes {"triggered_by": "cron"}.
IMAP
The IMAP trigger manager runs in the leader worker and checks active imapTrigger nodes on their configured pollIntervalMinutes. Each node stores an IMAP cursor (UIDVALIDITY + last seen UID). Input includes email, triggered_by: "imap", trigger_node_id, and triggered_at.
Google Drive and Google Sheets
The Google trigger poller runs in the leader worker and checks active googleDriveTrigger and googleSheetsTrigger nodes on their pollIntervalMinutes. Each node keeps a snapshot in the database: file metadata for Drive, keyed fingerprints of cells for Sheets (never cell values). Polls are claimed per node and each change is consumed with a compare-and-swap, so a change starts one run across every worker and instance. Input includes change, triggered_by ("google_drive" or "google_sheets"), trigger_node_id, and triggered_at.
Heym Platform Events
The Heym event dispatcher polls the heym_events log every 5 seconds and delivers matching events to active heymTrigger nodes. Delivery is claimed per (event, workflow, node) through a unique constraint, so an event fires exactly once per subscribing node across every worker, container, and machine. Every event claimed in one pass is delivered in a single run: input includes events (always an array, oldest first), count, triggered_by: "heym_event", trigger_node_id, and triggered_at. Only events published in the last 5 minutes are dispatched, which stops an outage from replaying a backlog; events are retained for 7 days.
WebSocket
The WebSocket trigger manager runs in the leader worker and keeps one outbound client connection per active WebSocket Trigger node. It can emit runs for onMessage, onConnected, and onClosed. Input includes eventName, url, triggered_by: "websocket", trigger_node_id, and one of message, connection, or close.
File Upload
The File Upload Trigger mints a TTL-bounded, single-use
upload slot when the workflow is invoked through the API, MCP, or canvas. Uploading multipart form
data to POST /api/file-intake/u/{token} consumes the slot, stores the file as a Drive file, and
starts the workflow synchronously. Input includes file, uploaded_at,
triggered_by: "file_upload", and upload metadata. Set Accept: text/event-stream
to receive heartbeats and the final result
without leaving a long-running request silent.
Telegram
Telegram sends bot webhook updates to POST /api/telegram/webhook/{node_id}. The payload is passed into the workflow as update, message, optional callback_query, sanitized headers, triggered_by, trigger_node_id, and triggered_at. If the selected credential has a secret token, Heym verifies x-telegram-bot-api-secret-token before execution.
Discord
Discord sends interaction webhooks to POST /api/discord/webhook/{node_id}. The payload is passed into the workflow as interaction, type, data, sanitized headers, triggered_by, trigger_node_id, and triggered_at. Heym verifies the request using Ed25519 and the selected discord_trigger credential's application public key before execution.
RabbitMQ
The RabbitMQ consumer starts when the leader worker initializes. Workflows with rabbitmq nodes where rabbitmqOperation === "receive" get a consumer. Input includes message_data (body, headers, routing_key, etc.) and triggered_by: "rabbitmq".
Concurrency Limit
A workflow with a concurrency limit queues production runs from every entry point above when its slots are full, first in, first out, across all instances. How a caller learns the result depends on the entry point:
| Entry point | While the run waits |
|---|---|
| Webhook / API | 202 Accepted with an execution_id and a status URL |
| SSE streaming, Quick Drawer, Portal chat | The stream stays open and sends queued events |
| Portal without streaming | The request waits for the result |
| MCP | A queued result to poll with heym_execution_status |
| Cron, IMAP, Google Drive / Sheets, WebSocket, RabbitMQ, Slack, Discord, Telegram, Heym events, error workflows, Dashboard run widgets | The trigger waits for the result, as long as a run on another instance would. The run executes either way and is written to history |
When the queue is full, the run does not start and history records it as queue_full. Editor test runs, sub-workflow calls (Execute node and agent workflow tools), Evals, chat build-mode test runs and review resumes are never queued. Board card runs, File Upload runs, runs started by the AI assistant's run-workflow tool, and alert notify workflows also start without waiting for a slot.
trigger_source
Execution history records trigger_source for every entry point:
| Value | When |
|---|---|
"API" | Webhook / API call with no explicit header (default) |
"Canvas" | Run from the workflow editor canvas |
"Quick Drawer" | Run from the editor quick-drawer panel, including file runs uploaded from its drop zone |
"cron" | Cron scheduler |
"imap" | IMAP trigger manager |
"google_drive" | Google Drive Trigger poller |
"google_sheets" | Google Sheets Trigger poller |
"websocket" | Outbound WebSocket trigger manager |
"file_upload" | File Upload Trigger upload endpoint (links minted over HTTP, MCP, or the canvas) |
"dashboard" | Dashboard widget runs, and uploads from a file drop widget |
"telegram" | Telegram bot webhook |
"Discord" | Discord interactions webhook |
"MCP" | MCP tool call |
"portal" | Portal execute |
"dashboard_chat" | AI assistant chat |
"AI Agents" | Sub-workflow invoked by an AI agent node |
"SUB_WORKFLOW" | Sub-workflow invoked by an Execute Workflow node |
| custom | Any value sent in X-Trigger-Source header or trigger_source query/body param |
| (not set) | RabbitMQ consumer |
Inputs by Trigger
- HTTP/Webhook:
body,headers,queryfrom the request - Cron:
{"triggered_by": "cron"} - Telegram:
update+message+ optionalcallback_query+ sanitizedheaders+triggered_by: "telegram"+trigger_node_id+triggered_at - Discord:
interaction+type+data+ sanitizedheaders+triggered_by: "Discord"+trigger_node_id+triggered_at - IMAP:
email+triggered_by: "imap"+trigger_node_id+triggered_at - Google Drive / Sheets:
change+triggered_by: "google_drive"or"google_sheets"+trigger_node_id+triggered_at - WebSocket:
eventName+url+triggered_by: "websocket"+message/connection/close - File Upload:
file+uploaded_at+triggered_by: "file_upload" - RabbitMQ:
message_data+triggered_by: "rabbitmq" - Slack:
event(full Slack event object) +headers(sanitized) +triggered_by: "Slack"+trigger_node_id - Portal:
body.inputs+ optionalconversation_history
Related
- Webhooks – Webhook TTL, cache, rate limit, auth
- Workflow Structure – Nodes and edges
- Node Types – Input, Cron, Telegram Trigger, IMAP Trigger, Google Drive Trigger, Google Sheets Trigger, Heym Trigger, WebSocket Trigger, File Upload Trigger, RabbitMQ
- Discord Trigger – Discord interactions webhook trigger
- Quick Start – Build a workflow with Input
- Portal – Portal trigger and chat UI
- Execution History – View past runs and trigger_source