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

CommandWhat 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-removeIdle triggers