Routines
Recurring work that gives an agent a fresh task on a cron schedule.
A routine is recurring work: a task template, the agent who does it and a cron schedule. Each time a routine is triggered, SAT creates a todo task from the template, assigns it to the agent and queues a routine run. NoteFlow's CEO Ada writes a weekly progress report every Monday at 09:00, and Margaret triages new bug reports every four hours.
The API does not evaluate schedules
The API stores cron but never runs anything on time. Something has to call the trigger endpoint: sat scheduler start (see Scheduler), Run now in the web app, sat routines trigger, or your own job. Without a scheduler, routines only run when a person triggers them.
How it works
When a routine is triggered:
- If the agent is
paused,pending_approvalorterminated, the trigger fails with400 INVALID_STATEand nothing is created. - A task is created with the routine's title and description, status
todo, prioritymedium, assigned to the routine's agent, in the routine's project (if any), with the triggering member as creator. It gets the next task key, for exampleNF-31. - A run with trigger
routineis queued, linked to the task and the routine. last_run_atis set to now.
Triggering does not check enabled. A disabled routine can still be run by hand; enabled only tells the scheduler to skip it.
The scheduler
sat scheduler start loads the company's routines and agents and fires their schedules:
- Routines: every enabled routine fires on its
cronand calls the trigger endpoint. Before firing it re-reads the routine and skips if it was disabled, or iflast_run_atis more recent than the smaller of 50 seconds and half the schedule's interval (another scheduler or a person just ran it). - Agent heartbeats: every agent with a
heartbeat_cronthat is notpaused,pending_approvalorterminatedis woken on that schedule with reasonheartbeat. This queues amanualrun without a task (see Runs). - It also expires runs whose runner stopped reporting, every
--expire-intervalseconds (default 60). - Cron expressions use the machine's time zone unless you pass
--timezone, for example--timezone Europe/Berlin. - It reloads definitions when a
routine.*oragent.*event arrives and every five minutes. Missed ticks while it is down are not run later.
Run one scheduler per company. Details are in Scheduler.
Cron syntax
The scheduler uses croner syntax:
| Fields | Format | Example |
|---|---|---|
| 5 | minute hour day-of-month month day-of-week | 0 9 * * 1 (Mondays 09:00) |
| 6 | second minute hour day-of-month month day-of-week | 30 0 9 * * 1 (Mondays 09:00:30) |
| 7 | second … day-of-week year | 0 0 9 1 1 * 2027 |
Nicknames such as @daily, @weekly and @monthly, names like MON and JAN, and L, W and # modifiers also work. Day-of-month and day-of-week combine with OR, as in standard cron.
The API stores any string of 1 to 100 characters without checking it. sat routines create and edit reject an invalid expression; the web form does not check it, and the scheduler skips an invalid one with a warning in its log.
Fields
RoutineOut:
Prop
Type
Use it
Open Routines. The table lists each routine's title and instructions, agent, schedule, last run and an Enabled switch.
- New routine asks for Title, Instructions, Agent and Schedule (cron), which defaults to
0 9 * * 1. The web form has no project field; use the CLI or API to set one. - Run now triggers the routine immediately and shows "Created NF-31" with an Open link to the new task.
- The Enabled switch turns the scheduler off or on for that routine.
Editing the title, agent or schedule of an existing routine, and deleting a routine, are not available in the web app yet; use the CLI or API.
Permissions
Any member can list, create, edit, trigger and delete routines. Non-members get 404 NOT_FOUND. Tasks created by a trigger are attributed to the member whose credentials made the call; for the scheduler, that is the person (or API key owner) running it.
Events
| Event | When |
|---|---|
routine.created | A routine was created. |
routine.updated | A routine was edited (only when something changed), or triggered (last_run_at changed). |
routine.deleted | A routine was deleted. |
task.created | A trigger created the routine's task. |
run.created | A trigger queued the routine run. |
The activity log records created, updated, deleted and triggered on the routine, plus queued on the run.
Limits and known gaps
- Schedules run only while a scheduler is running. There is no hosted scheduler.
- Missed ticks are not backfilled after the scheduler was down.
- Running more than one scheduler for a company is only guarded by the short duplicate window; two schedulers can still double-fire if their clocks or reloads drift.
- Each trigger creates a new task, even if the previous one is still open.
- The cron time zone belongs to the scheduler process, not to the routine or the company.
- The web app cannot edit (other than enable/disable) or delete routines, or set a routine's project.
- Deleting the routine's agent (terminating it) does not disable the routine; triggers then fail with
400 INVALID_STATE.
Related
Scheduler
Run sat scheduler to fire routines and heartbeats.
Runs
What a routine run is and how it executes.
Tasks
The tasks each trigger creates.
Create routine (API)
POST /api/companies/{company_id}/routines
Trigger routine (API)
POST /api/companies/{company_id}/routines/{routine_id}/trigger
Update routine (API)
PATCH /api/companies/{company_id}/routines/{routine_id}