Agent schedules
A schedule that belongs to an agent, not to a workflow: a cron entry in the agent's own profile that injects a message into it at a fixed time.
Not to be confused with Scheduling workflows, which is a different mechanism entirely β that one installs a launchd agent or crontab entry that runs mur run <name>. Both read cron in local time; everything else about them differs.
mur agent schedule list mur
mur agent schedule add mur "0 9 * * 1-5" "morning brief"
mur agent schedule next mur 3
mur agent schedule remove mur 0
Cron is the standard five fields β minute, hour, day-of-month, month, day-of-week β read in the machine's local time, not UTC.
An agent cannot create its own schedule
It can ask. The remind tool writes a proposal into the agent's home; nothing fires until a person grants it.
mur agent schedule proposals mur
mur agent schedule accept mur <id>
mur agent schedule decline mur <id>
A proposal shows the user's own words next to the cron, because a cron expression is not reviewable on its own β the question being asked is whether it matches what was said:
b10582d9b543 0 10 1 9 * β θ©²εζ©ι€δΊ π₯
asked for: δ»ε€©ζ©δΈει»ζιζεζ©ι€
fires once, on 2026-09-01 10:00:00 +08:00 β does not repeat
Accepting appends the entry to the agent's profile. Restart the agent for it to take effect β the runtime reads its schedule once, at startup.
Correcting a request supersedes it rather than stacking: superseding keys on what the user asked for, not on the cron, so an agent that guesses a date wrong and asks again leaves one proposal, not two.
One-off reminders
Cron has no year field. "Remind me tomorrow at 10:00" can only be written as 0 10 1 9 * β which means every September 1st, forever. A request for one morning would become a perpetual commitment.
Entries therefore carry a bound:
- cron: 0 10 1 9 *
message: θ©²εζ©ι€δΊ π₯
not_after: '2026-09-01T10:00:00+08:00'
The scheduler admits the firing the bound names and retires the entry before the next one. mur agent schedule list says so under the row, because a bare cron cannot:
IDX CRON MESSAGE SENDS_TO
0 0 10 1 9 * θ©²εζ©ι€δΊ π₯ (self)
β³ once, on 2026-09-01 10:00
Whether a request is one-off is decided from what the user said, never inferred from the expression: 0 9 15 3 * is both "remind me on March 15" and "every year on my birthday", and the cron cannot tell you which.
A bound that cannot be parsed is treated as no bound. The two ways to be wrong are not symmetric β a reminder that repeats is visible in schedule list and one remove away, while a reminder that silently never fires is not.
What a fired entry does, and does not, do
When an entry fires, the scheduler injects its message into the agent and the agent runs a turn. That much is reliable β it fires on the second, and a one-off retires itself immediately afterwards.
Nothing currently carries the result to you. The successful turn's output
is not pushed anywhere: notifications.on_task_complete exists in the profile
schema but is not yet wired to a sender, sends_to cross-agent dispatch is not
implemented, and the companion is off unless you turn it on. A schedule is
therefore a way to make an agent do something on a clock, and not yet a way
to be told something on a clock.
Plan accordingly: a schedule whose message asks the agent to act β write a file, open an item, run a check β leaves a result you can find afterwards. One that only says "tell me X" currently says it to nobody.
Idle triggers
A schedule fires at a time; an idle trigger fires after a stretch of quiet.
mur agent schedule idle-add mur --after-secs 3600 --message "anything stuck?"
mur agent schedule idle-list mur
mur agent schedule idle-remove mur 0
Commands
| Command | What it does |
|---|---|
schedule add <name> <cron> <message> | Append a cron entry to the agent's profile |
schedule list <name> | List entries, with the bound named where there is one |
schedule next <name> <n> | Next N fire times per entry |
schedule remove <name> <index> | Remove by 0-based index |
schedule proposals <name> | Schedules the agent asked for and has not been granted |
schedule accept <name> <id> | Grant one β it becomes a real entry |
schedule decline <name> <id> | Refuse one |
schedule idle-add / idle-list / idle-remove | Idle triggers |