Make a routine
Member·6 minutes to read
The routine health line (a routine that hasn't fired, or was paused while you were away) is verified against
docs/superpowers/specs/2026-09-15-p4-e-routine-heartbeat.md§1.1–§1.2; the spend cap againstdocs/superpowers/specs/2026-09-15-p5-g-billing-meter-budgets.md§1.2; and the delete restore againstdocs/superpowers/specs/2026-09-14-p2-f-web-quality.md§1.2. None of the three has shipped yet — re-verified against the code at close-out.
What this does for you
A routine runs an instruction on a schedule, or when something happens, so a bot does a job without you starting it by hand.
Before you start
- The bot or group this routine belongs to, open in its details pane.
- An instruction ready to give — the same words you'd use if you asked the bot directly.
- Fewer than 50 existing routines on that bot or group; a bot or a group may have at most 50 (
packages/db/src/repos/routines.ts). - A minute to read the checklist below. A routine runs unattended, so the six habits that make one worth trusting are worth having before you build it, not after it has already run a few times:
- Draft it first. Give the routine a narrow instruction, run it once with Test run, and read what it did before you let the schedule take over.
- Decide what it does with no data. If the thing it looks for (an unread email, an open ticket) isn't there, say so in the instruction — otherwise the bot improvises.
- Decide what it does with stale data. A routine that reads the same feed every hour needs to know whether to re-report something it already reported.
- Ask for idempotent retries. A routine that failed partway and fires again on schedule should not resend what it already sent.
- Say where partial completion is reported. If the instruction has several parts, say what the bot should tell you when only some of them finished.
- Re-test after anything the routine depends on changes — a renamed sheet, a moved folder, a plugin re-authenticated.
Steps
-
Open the bot's or group's details pane, go to Routines, and choose + Create Routine.
<!-- shot: create-a-routine-01-phone.png | Creating a routine from a bot's Routines section, on a phone --> <!-- shot: create-a-routine-01-desktop.png | Creating a routine from a bot's Routines section, on a desktop --> -
Name the routine and write its instruction. Both save as you leave the field — there is no separate Save button.
<!-- shot: create-a-routine-02-phone.png | The routine editor's name and instruction fields, on a phone --> <!-- shot: create-a-routine-02-desktop.png | The routine editor's name and instruction fields, on a desktop --> -
Choose + Add trigger, then On a schedule, and pick a preset — Every hour, Every day, Weekdays, Every week, Every month or Interval. Each preset opens a short time picker and closes into a plain-English summary line, such as "Every day at 8:00 AM".
<!-- shot: create-a-routine-03-phone.png | The trigger menu's schedule submenu, on a phone --> <!-- shot: create-a-routine-03-desktop.png | The trigger menu's schedule submenu, on a desktop --> -
To edit a trigger later, open its summary row: the edit menu offers the same presets plus Custom, which swaps the pills for a raw five-field cron expression (minute, hour, day of month, month, weekday — no seconds, no
@daily-style macros). The summary above it regenerates from whichever value you leave it on. -
If the job should also start from an event rather than a clock, choose one of the other rows in + Add trigger — Slack message, Git event, Teams message, Linear issue, Sentry alert, PagerDuty incident or Webhook — instead of, or alongside, a schedule. Prefer the narrowest trigger that does the job. A trigger that fires on every message in a busy channel, rather than one scoped to a keyword or a specific event, costs you noise, usage and the occasional wrong-context run — narrow it at the source, not by asking the bot to ignore most of what it sees.
-
Once the routine has a name, an instruction and a trigger, Test run turns on. A test run does the real work — it sends, spends and changes whatever the instruction says, and it costs the same as a run the trigger starts on its own — so read the instruction back before you press it.
-
Turn Active on when you're ready to let the trigger fire it on its own; turn it off at any time to pause the routine without deleting it. Delete removes the routine immediately, with no confirmation step.
A worked example
A daily inbox sweep, written the way the fields above take it:
Name: Inbox sweep
Instruction: Read unread email from the last 24 hours. Reply to anything that only needs an
acknowledgement. Leave everything else unread for a person to handle, and say at the end how
many you replied to versus left.
Trigger: On a schedule → Every day → 8:00 AM
Stored as: 0 8 * * *
The stored value is what the schedule actually runs on; the preset is only how you set it. Picking Custom later and typing 0 8 * * * by hand would produce the identical trigger.
What can go wrong
| What you see | Why | What to do |
|---|---|---|
That schedule is not valid. | The cron expression didn't parse — it needs exactly five space-separated fields, and neither seconds nor a macro like @daily are understood. | Fix the expression, or switch the trigger back to a preset from its edit menu. |
A bot may have at most 50 routines. | Every bot, and every group, is capped at 50 routines. | Delete or combine an existing routine before adding another. |
That routine could not be found. | The routine was deleted, or it belongs to someone else. | Reopen the Routines list and pick it again. |
That change could not be saved. Try again. | A rename, an instruction edit, the Active switch or a delete didn't reach the server. | Try the change again; if it keeps failing, check your connection. |
Name, instruction and a trigger first. | Test run stays off until the routine has all three. | Fill in whichever one is still missing. |
See also
Last verified against build c0f77aa.