Skip to content

Triggers & Scheduling

A trigger is what kicks a flow off without a human invoking it. A flow can have multiple triggers — fired by a cron at 09:00 and by a webhook on demand and by a file landing in an SFTP directory. The flow body does not change based on which trigger fired it; the difference shows up only in the source payload key, which any step can read.

TypeFires when…
CronA cron schedule is due.
WebhookAn HTTP request hits the flow’s webhook endpoint.
AWS SQSA message arrives on an SQS queue.
MailA matching message arrives in a watched mailbox (IMAP/POP3).
Filesystem watchA file appears/changes in a watched directory (local or SFTP).
Log monitorA configured log pattern matches.
Flow-to-flowAnother flow calls this one — see Composing Flows.

Each trigger is named, typed, and parameterised independently.

The simplest scheduling form is a top-level schedule: field with a standard 5-field cron expression:

name: daily-report
schedule: "0 9 * * *" # every day at 09:00
steps:
- $report:
invoke: http.get
with:
Url: "https://api.example.com/daily-report"
- return:
value: "${report.body}"
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
* * * * *

Special characters: * (any), , (list), - (range), / (step).

PatternExpression
Every 15 minutes*/15 * * * *
Daily at 9 AM0 9 * * *
Weekdays at 8 AM0 8 * * 1-5
Monday at 6 AM0 6 * * 1
First of month, midnight0 0 1 * *
Every 6 hours0 */6 * * *
  • Cron is evaluated in the system timezone.
  • Scheduled flows invoke with no parameters — only system params (invocation-id, flow-name) are present.
  • One schedule per flow — use a single cron expression. (For multiple firing patterns, use the richer triggers: block.)
  • The scheduler picks up changes automatically; remove the schedule: field to unschedule.

For non-cron triggers (and multiple triggers on one flow), use a triggers: block. Each entry is named and typed:

triggers:
nightly:
type: cron
schedule: "0 2 * * *"
on-upload:
type: filesystem
on: drop-zone # a connection alias
path: "/incoming/*.csv"
on-demand:
type: webhook

Any step can branch on which trigger fired by reading ${source}:

- if: "source.type == 'webhook'"
do:
- log: "Triggered on demand by ${source.caller}"

A scheduled flow that alerts on failure combines cron, retry, and messaging:

name: health-check
schedule: "0 * * * *"
steps:
- $check:
invoke: http.get
with: { Url: "https://api.example.com/health" }
retry: { maxAttempts: 3 }
- if: "check.body.status != 'healthy'"
do:
- $alert:
invoke: notify.send
with: { Message: "Health check failed: ${check.body.status}" }