SCHEDULE_TRIGGER node at the start of the workflow and let Yukta keep time, or keep time outside Yukta and start the workflow each time over REST, the CLI or MCP.
How a scheduled workflow runs
A schedule lives inside one long-running execution. You start the workflow once. ItsSCHEDULE_TRIGGER node then emits a message on every tick, and the rest of the graph handles each message as it arrives. The execution stays open, and holds one execution slot, until you stop it, the trigger reaches its maxRuns, or the server stops. It is not a separate scheduler that creates a new execution per tick.
Every tick is a message with the payload {"tick": 1, "firedAt": "2026-10-15T09:00:00Z"}. tick counts from 1 and firedAt is the creation time in UTC.
Interval or cron
Set exactly one ofintervalMs and cron. Setting both, or neither, is rejected when the workflow is validated. See Triggers for the full option table.
A cron expression has six fields: second, minute, hour, day of month, month and day of week.
Invalid values are rejected when the workflow is validated: an invalid cron expression, an unknown time zone, a cron expression that has no future date, a non-positive
intervalMs and a maxRuns that is not a positive whole number.
Example
This session checks a URL every minute and sends a webhook message when the check fails. TheSCHEDULE_TRIGGER node allows 120 seconds of silence, twice the interval.
POST /api/sessions, then start the workflow once:
Stopping a schedule
An execution with a schedule runs until it is stopped. UsemaxRuns for a bounded schedule. To stop an open one, stop the workflow’s executions. The default DRAIN mode stops the trigger and lets in-flight work finish.
yukta workflow stop <session-id> <workflow-id>, and for one execution with yukta workflow executions stop <execution-id>. See Run controls.
Overlap
All ticks of a schedule belong to one execution, so schedules do not overlap as executions. Each tick is an independent message, and Yukta does not replay missed ticks. If the work a tick starts takes longer than the gap between ticks, new ticks arrive while earlier ones are still being handled. Keep the interval longer than the work, or putengine.edgeBuffer on the slow node so that it drops the oldest or newest waiting messages instead of slowing the trigger. See Delivery and backpressure.
Starting the workflow twice gives two executions and two independent schedules, subject to the admission limits. Start it once, and use an Idempotency-Key header on the start request so that a retried start does not create a second schedule.
What happens on a restart
The schedule is not stored. Its position lives in the running execution and is lost with the server process.- After a restart nothing starts the workflow again by itself, and ticks that were missed while the server was down are not replayed.
- Start the workflow again, for example from a script that runs when the server boots. A new execution begins with
tick1 and waits a full interval, or until the next cron time, before its first message. - If you resume an interrupted execution, or turn on automatic resume, the trigger likewise starts its schedule again from the beginning. See Checkpoints and resume.
Starting workflows from outside
When you need a schedule that survives restarts, or runs that are independent of each other, run the clock outside Yukta (cron, a CI scheduler, a cloud scheduler) and start the workflow for each run. Each start is a separate, short execution.
The workflow for this mode begins with
API_TRIGGER, which passes the payload of the start request into the graph, or with CONSTANT_SOURCE when it needs no input: