Documentation v1.0.9

Scheduler

This page covers automated scheduling and how to recover a scheduler skill after a bad edit.

Scheduler skills (isolated namespace)

Scheduler-triggered skills live in a separate tree, not scanned by agents.Scanner():

~/.config/agenvoy/skills/scheduler/<short>-<hash8>/SKILL.md
Aspect Regular skill Scheduler skill
Path ~/.config/agenvoy/skills/<name>/SKILL.md ~/.config/agenvoy/skills/scheduler/<short>-<hash8>/SKILL.md
Frontmatter name <name> <short>-<hash8> (no scheduler- prefix)
/<name> autocompletion yes no — surfaced as /sched-<name> (warn-purple) at the bottom of the picker
Trigger runtime.MatchSkill (in exec.Prepare) then a synthesized run_skill (a) cron / one-shot fire from daemon runtime.SetRunner, (b) manual /sched-<name> or /schedule from TUI

Creation flow

The scheduler-skill-creator skill is the canonical entry for new schedules. It:

  1. Pre-flight gate (Step 0): if the user message lacks a time token (+5m / HH:MM / etc.) or task token, it must call ask_user first — no defaulting to +10m, no inferring "probably 9am". When both are missing they go out as two questions in one ask_user call rather than one round each.
  2. Runs python3 ~/.config/agenvoy/skills/.system/scheduler-skill-creator/scripts/init_scheduler_skill.py <short> to create the skill dir with hash suffix. The path is absolute on purpose: run_command runs in the user's work directory, not the skill directory, so a relative scripts/... never resolves.
  3. Delegates the body to /skill-creator (its "edit an existing skill" path) instead of patching the SKILL.md inline. The directory and name are already fixed by step 2, so this step only fills in content.
  4. Calls schedules(mode=write) to bind the schedule.

Direct schedules(mode=patch) calls are allowed only for rebinding existing schedules (changing the time of an already-created scheduler skill). mode=write is internal to the creator flow — its skill_name carries a generated hash suffix, so a hand-made one always fails.

Manual execution (/sched-<name>)

The TUI command picker lists each directory under scheduler/ whose cron or one-shot entry is bound to the current session as /sched-<name>. Selecting one reads the body and dispatches it to the current agent with a preamble that blocks weaker models from misreading the SKILL.md-shaped body as a schedule-creation request and re-running the creator. /schedule lists every cron and one-shot entry in one popup: enter fires the selected one through this same path, d deletes it; adding or editing a schedule is done by asking the agent (the former /cron and /task commands were removed).

The preamble enforces:

Daemon fire

The daemon calls runtime.SetRunner(app.RunSkill), where app.RunSkill(ctx, sessionID, skillName) is the runner. When the scheduler fires (cron tick or one-shot deadline), the runner:

  1. Reads body via skill.GetSchedule(skillName).
  2. Ensures the session directory and its SQLite row exist.
  3. Runs the body through exec.ExecWithSubagent — an in-process subagent in schedule context.

One-shot tasks are removed and the skill dir is trashed after a successful fire.

Recovering from a bad edit

Automatic post-run skill rewriting was removed — a failed run no longer edits the skill behind your back. Recovery runs on the file-level snapshot layer: every change the tools make to a file is recorded, so recovery is explicit:

Step Tool
Inspect the recorded versions of a skill or tool file file_history(mode=list)
Diff the newest recorded version against what is on disk file_history(mode=read)
Put one version back edit_file(mode=restore, version=...)
Undo everything one task changed edit_file(mode=restore, task_id=...)

A removed skill lands in .Trash/ and stays recoverable from there.

中文