"Set up a scheduled headless afk run that pushes a summary to Telegram. Use when the user wants to automate a recurring task via the afk daemon scheduler (cron) with push-notified results."
Install
npx skillscat add griffinwork40/agent-afk/automate Install via the SkillsCat registry.
Set up a recurring headless task using afk's native scheduler. Do NOT hand-roll launchd plists or shell scripts — afk has first-class scheduling: the create_schedule tool writes ~/.afk/config/schedules.json entries that afk daemon runs on cron.
Input routing
The argument is one of three forms:
- Task description / directory path — proceed directly to the Scout + Prompt designer wave below.
- Session ID — run the fit-assessment flow first (Waves 0–1 + authorization gate) to determine whether the session is automatable before building a schedule.
Session ID path: fit-assessment
Wave 0 — Signal extraction (orchestrator, synchronous)
Read the session facet with get_facet (pass fields: ["duration_minutes", "user_message_count"] so the goal and first prompt never enter the extraction) and the session's tool calls with read_witness (kinds: ["tool_call"]), then extract four flat signals:
duration— the facet'sduration_minutesuser_messages— the facet'suser_message_count. Do not count witness events for this: the trace records no user turns, and itsqueued_user_messageevents cover only messages typed mid-turn, so they undercount.llm_branch_steps— count of tool calls whose branch condition is model output rather than exit code (i.e., tool calls following a reasoning step that is not mechanically determined)command_sequence— ordered list of distinct bash/shell commands issued, with item count
Emit Artifact 1: duration=Xm, user_messages=N, llm_branch_steps=M, command_sequence=[cmd1, cmd2, …] (K distinct commands). This is the only input forwarded to Wave 1 — the session ID, original user message, and any rationale are withheld.
Wave 1 — Automation-fit probe (isolated sub-agent)
Receives Artifact 1 only. Denied: session ID, original user message, any framing about why the task was run manually. Denied write tools.
Applies the five-point rubric:
| Criterion | Points |
|---|---|
duration ≤ 10m |
+1 |
user_messages ≤ 2 |
+1 |
llm_branch_steps == 0 |
+1 |
| Command sequence is idempotent with no destructive commands lacking a guard | +1 |
| No step requires live user judgment | +1 |
Emits one of:
FIT [score=N](≥ 4) — proceed to gatePARTIAL [score=N, guard=<exact modification required>](2–3) — surface the guard to the user before the gate; do not proceed until acknowledgedUNFIT [score=N](≤ 1) — halt with explanation; do not generate a schedule
Authorization gate
For FIT or acknowledged-PARTIAL verdicts, the orchestrator presents the proposed schedule: name, cron expression, and command sequence preview. Waits for an explicit token:
APPROVE(or bare "yes") — proceed to Scout + schedule creationMODIFY <field> <value>— adjust one parameter and re-presentABORT— exit withAUTOMATED_NOTHING
Do not proceed to schedule creation until APPROVE is recorded.
Schedule creation (all paths)
Dispatch two sub-agents in parallel:
- Scout — call
list_schedulesand inspect~/.afk/config/schedules.jsonfor existing or overlapping jobs, runafk service statusto see whether the daemon is installed as a launchd service and running, confirm Telegram is configured (TELEGRAM_BOT_TOKEN+AFK_TELEGRAM_ALLOWED_CHAT_IDS), and scan the target project folder for conventions. Report conflicts, daemon/service state, and any missing prerequisite. - Prompt designer — draft the recurring task's
commandstring: a self-contained prompt (or/skill --flagsinvocation) sent verbatim into a freshly spawned session each run. The daemon session starts cold, so encode all input context explicitly, and require the run to END by calling thesend_telegramtool with a concise, push-ready summary.
When both return:
- If Telegram is unconfigured, stop and tell the user to run
/telegram-setupfirst —send_telegramfails closed withoutTELEGRAM_BOT_TOKENandAFK_TELEGRAM_ALLOWED_CHAT_IDS. - Create the job with the
create_scheduletool:name, the designedcommand, the requested 5-fieldcron,trigger: "cron", andnotifyOn: "failure"as a crash safety-net (the per-run summary comes from the agent's ownsend_telegramcall, not fromnotifyOn). - Schedules only fire while the daemon is running, so make it survive reboot/crash: if
afk service statusshows the daemon isn't installed, runafk service install daemon(launchdRunAtLoad+KeepAliveon macOS).
Dispatch a verification sub-agent to confirm the job registered (list_schedules), the daemon is running (afk service status), and — by running the task's command once as a one-shot (afk chat "<command>") — that the Telegram summary actually arrives. On failure, diagnose (Telegram config, daemon not running, cron syntax, prompt shape) and fix before exiting. Report the schedule id, cron, notifyOn, daemon/service status, and the next scheduled run.
Completeness contract (session ID path only)
Before claiming Done, confirm all five items are present in the terminal report:
- Wave 0 signal report — duration, user-message count, LLM-branch count, command sequence with item count stated
- Wave 1 fit verdict — score and tier (FIT / PARTIAL / UNFIT) stated
- Authorization token — APPROVE, MODIFY <field> <value>, or ABORT recorded
- Schedule artifact — schedule ID and cron expression stated
- PARTIAL guard — if applicable, exact guard surfaced to user before the gate