Triggers
A trigger is the node that starts a run. Everything downstream is reaction; the trigger decides when there is something to react to — and, just as importantly, what the run’s initial payload is. Flowdrome ships fourteen:
| Trigger | Starts a run when… |
|---|---|
| HTTP Trigger | a request hits the workflow’s webhook path (method, path and content type are configurable) — or add a Routes table to serve a whole API from one trigger: each route (GET /users/{id}) becomes its own output port (auto-named, e.g. get_users_id) with pathParams extracted, anything unclaimed leaves on unmatched, and Publish OpenAPI spec serves a generated spec of the lot |
| Telegram Trigger | the bot receives an update — long-polling (no public URL needed) or webhook mode |
| Slack Trigger | a Slack event arrives (the Events API handshake is handled for you) |
| WhatsApp Trigger | a WhatsApp Business message arrives (webhook verify + normalized payload) |
| Discord Trigger | a Discord message arrives via the Gateway WebSocket |
| WebSocket Trigger | a message arrives on the workflow’s WebSocket endpoint |
| Web Chat | a visitor sends a message through the embeddable chat widget the workflow serves |
| Form | someone submits the HTML form the workflow serves (GET renders it, POST runs the flow) |
| Schedule | a 5-field cron expression or fixed interval fires (IANA timezone aware) |
| File Event | a watched path sees a file created/changed/deleted |
| Receive Message | a message lands on an internal queue (paired with Send Message) |
| Inject | you press the button — a test fixture with a configurable payload |
| Manual | the workflow is invoked as a run-once job |
| Error Trigger | another node in the run fails — it starts the recovery lane |
Each reference page above shows the trigger on the canvas, wired, with a real run’s payload — the fastest way to learn a trigger’s output shape is to look at one captured run and start copying field paths.
The production trigger model
The same workflow behaves differently in the editor and in a deployed app — deliberately. The motivating problem: you need sample data to build a flow, but the deployed artifact must not fire your test scaffolding. Flowdrome resolves this with three trigger roles:
- Inject is an inert test fixture. It exists to hand the graph a payload while you build — its properties hold the sample content (JSON, text, even binary with an encoding). In a deployed workflow it never fires — dead weight by design, so you can leave your test scaffolding in the document forever. No “remember to delete the test trigger” step, no prod incident from forgetting it.
- Manual is the run-once entry. A deployed workflow invoked in job mode executes once from the Manual trigger and reports its outcome — cron-from-the-outside, CI steps, batch jobs.
- Real triggers serve. Once deployed, the host’s serve layer takes over: it binds the workflow’s HTTP/WebSocket/form/chat endpoints, starts its schedules, polls Telegram, answers the Slack and WhatsApp webhooks, watches files — continuously, with run history on the host dashboard.
“Promote to production” is therefore not a rewrite: you test with an Inject sitting next to the real trigger, deploy, and the real trigger takes over while the Inject goes dormant.
What a trigger emits
A trigger’s output is a content wrapper describing what arrived — kind, content type, and the payload — which the engine unwraps at the next node boundary, so downstream nodes see the content (the webhook body, the Telegram update, the file event) without ceremony. Text arrives as text (no false “invalid JSON” complaints), JSON as parsed values, binary as first-class binary items. The metadata (headers, query, method for HTTP) rides the run’s envelope where expressions can still reach it.
Responding to HTTP early
By default an HTTP-triggered run answers the caller when the run finishes — fine for quick flows, wrong for slow ones. The HTTP Response node flips that: the first one executed answers the caller mid-flow (status, headers, body) and the run keeps going — acknowledge in milliseconds, keep working for minutes. An approval gate downstream can then hold the rest of the flow for a human without holding the caller’s connection. Two HTTP Response nodes on the two branches of a gate (202 approved / 403 rejected) is the canonical webhook-with-a-human pattern.
Webhook security
- The HTTP trigger validates method, path and content type at the door.
- For signed webhooks (payment providers, GitHub-style signatures), pair the trigger with the Crypto node: HMAC the raw body and compare with a timing-safe equality check — the shipped Signed Webhook demo is exactly this.
- Telegram webhook mode can verify Telegram’s secret-token header; polling mode avoids inbound exposure entirely.
- Outbound HTTP from the web-request nodes (HTTP Request, API, RSS Read) passes an SSRF
guard: private-range and loopback targets are refused unless the operator explicitly allows them
(
FLOWDROME_HTTP_ALLOW_PRIVATE=1) — so those nodes can’t be tricked into probing your internal network with a crafted URL. Code nodes (JavaScript / C# Script) make raw requests and are not behind this guard — authoring a code node means running trusted code (disable code nodes entirely withFLOWDROME_ALLOW_CODE_NODES=0in locked-down deployments).
Choosing a trigger
| You want… | Use |
|---|---|
| An API endpoint / webhook receiver | HTTP Trigger (+ HTTP Response for early ack) |
| “Every morning at 9” / “every 30 s” | Schedule (cron or interval) |
| A chat bot | Telegram / Slack / WhatsApp / Discord Trigger (or WebSocket for your own client — see the AI guide) |
| Chat on your own website | Web Chat — the workflow serves an embeddable widget |
| Collect structured input from people | Form — the workflow serves the HTML form itself |
| React to files landing in a directory | File Event |
| Decouple two flows with a queue | Send Message → Receive Message |
| A batch job your scheduler invokes | Manual (job mode) |
| A cleanup path when things fail | Error Trigger |