agentsclimarketplace

Schedule recurring agent

Skill ulpi-io/autonomous-engineering/schedule-recurring-agent

Stand up a recurring scheduled agent for standing work (triage, monitoring, audits, digests): a self-contained IDEMPOTENT brief (each run wakes memory-less and must dedup prior work), a cadence matched to how often work actually arrives, a per-run BOUND, escalation rules, and a teardown condition. For durable unattended work that runs while you're offline, use claude.ai Routines (the /schedule skill / RemoteTrigger); an in-session CronCreate is the lighter, session-scoped alternative. Use for scheduled repeat work — not one-off waits (watch-and-act).From its SKILL.md

Install
npx -y skills add ulpi-io/autonomous-engineering --skill schedule-recurring-agent

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

13.8 KB, ~3.1k tokens by cl100k_base, as published. Nobody here has run it

<EXTREMELY-IMPORTANT> A recurring agent acts unattended, repeatedly, forever — the failure modes compound. Non-negotiable: 1. THE BRIEF IS SELF-CONTAINED AND IDEMPOTENT. Each run wakes with NO memory of prior runs. The task brief must carry all its own context (what to do, where, how to report) and be SAFE TO RUN REPEATEDLY — deduplicate against prior work (don't re-file the same issue, re-ping the same PR, re-send the same digest). A non-idempotent routine spams. 2. EVERY RUN IS BOUNDED. Declare a per-run budget/cap (`budget-guard`) so one invocation can't grind for hours or fan out unboundedly. The schedule bounds frequency; the brief bounds each run. 3. CADENCE MATCHES THE WORK. Pick the cron interval from how often the work actually arrives — not "as often as possible". Over-frequent routines burn tokens and create noise; too-rare ones miss the window. 4. IRREVERSIBLE ACTIONS STILL ESCALATE. A routine may triage, monitor, and PREPARE, but it does not deploy, delete, merge, or send externally-visible messages on its own unless the user explicitly authorized that specific action. When in doubt, it produces a draft/report and asks. 5. HAS AN OFF-SWITCH. Define when the routine should stop or tear itself down (job done, N empty runs, user cancels). A routine with no teardown condition runs forever for no reason. List/inspect/delete it via the cron tools. 6. HONEST, LOW-NOISE REPORTING. Each run reports what it actually did (including "nothing to do") through the agreed channel — never fabricates activity, never floods. </EXTREMELY-IMPORTANT>

Schedule Recurring Agent

Inputs

  • $job: the recurring job description, optionally followed by a schedule ("weekday 9am", "hourly") that seeds the cadence choice in Phase 2.

Overview

Stand up an agent that does a recurring job on a schedule, correctly: a self-contained idempotent brief, a cadence matched to the work, a per-run bound, clear reporting, an escalation rule for anything irreversible, and a teardown condition. Getting the brief and the bounds right is what separates a useful routine from one that spams, grinds, or acts beyond its mandate.

Phase 0: Confirm it should be a recurring routine

  • Is this genuinely RECURRING standing work (arrives repeatedly on its own timeline), or a one-off? A one-off wait on a signal is watch-and-act; work to do once is just done now.
  • Does it act autonomously in a way the user must authorize? Confirm scope (especially any action beyond read/report) with AskUserQuestion before creating it.

Success criteria: confirmed recurring + the autonomy scope the user authorized.

Phase 1: Write the self-contained, idempotent brief

The brief is what the routine wakes into with zero memory — make it complete and repeat-safe:

  • What to do, precisely, and where (repo/paths/queries) — no reliance on session context.
  • Idempotency rule — how it recognizes and skips work already done (a marker label, a state file, a "since last run" query, a dedup key). This is the load-bearing part: without it, the routine repeats itself every run.
  • Per-run bound (budget-guard) — max items handled, token/time cap, so a busy day can't turn one run into a grind.
  • Report + escalate — the channel it reports through, and the triggers that make it stop-and-ask a human instead of acting (irreversible/ambiguous/high-volume).
  • Teardown condition — when it should stop (job complete, N consecutive empty runs, a date, user cancel).

Success criteria: a brief a fresh, memory-less agent can execute correctly and repeatedly without duplicating work or exceeding its mandate.

Phase 2: Pick the cadence and the mechanism, then create the routine

  • Choose the cron cadence from the work's real arrival rate: issue triage → weekday mornings; CVE watch → weekly; PR babysitting → a few times a day; nightly audit → once daily. Prefer the LEAST frequent cadence that still catches the work in time.
  • Pick the mechanism honestly — this is the load-bearing choice:
    • Durable / unattended (the usual case) — work that must run on its own timeline even while you are offline (nightly audits, CVE watch, weekday triage): stand it up as a claude.ai Routine via the /schedule skill (backed by the RemoteTrigger API). Routines run on Anthropic's infrastructure on a cron schedule, persist across sessions, and their runs count against your plan's usage/rate limits. This is the ONLY mechanism that actually delivers "runs when no one's kicking it off."
    • In-session only (the lighter alternative) — a recurrence you want ONLY while a session stays open: CronCreate. It is NOT a standing cloud agent — see the constraints below before choosing it.
  • Create it, then confirm it registered (/schedule list for a Routine; CronList for an in-session cron).

Constraints of each mechanism (state these to the user — they change what "recurring" means)

claude.ai Routine (/schedule · RemoteTrigger)In-session cron (CronCreate)
Runs while you're offlineYes — on Anthropic infraNo — only while this session's REPL is idle
Survives closing ClaudeYes — persistentNo — in-memory; gone when the session exits
Lifetimeuntil you disable/remove itauto-expires after 7 days (one final fire, then deleted)
Per-run token budgetno native cap — bound via brief + budget-guard; runs count against plan usagesame — no native cap

There is NO native per-run token budget on either — the per-run bound is enforced by the brief + budget-guard, not a platform parameter.

Success criteria: created on the mechanism that matches its durability need, on a justified cadence; registration confirmed; the mechanism's constraints stated to the user.

The validated job schema (the gate)

Both the brief (Phase 1) and the creation (Phase 2) are enforced deterministically by scripts/validate-job.mjs — the guardrails above are mechanically checkable, so they do NOT ship as prose only. A recurring job is a JSON object that MUST declare all nine fields; missing/empty any → the gate exits nonzero and names it:

FieldWhat it pinsShape
keya STABLE idempotency + registration key (dedup and the automation id are built from it)[A-Za-z0-9][A-Za-z0-9_-]*
repowhere it operates — no reliance on session contextstring
cadencea TIMEZONE-anchored recurrence (a cron with no tz drifts){ timezone, cron|expression }
promptthe self-contained brief a memory-less run executesstring (≥ 20 chars)
dedupthe idempotency rule — marker/state/since-query so repeats don't re-file/re-spamstring or object
perRunCapa POSITIVE per-run bound so one run can't grind or fan out{ maxItems|maxTokens|maxMinutes|maxActions } or a positive number
reportingthe channel each run reports through (incl. "nothing to do")string or object
escalationthe stop-and-ask rule for irreversible/ambiguous/high-volume workstring or object
teardownthe off-switch (job done, N empty runs, a date, user cancel)string or object
node schedule-recurring-agent/scripts/validate-job.mjs validate <job.json>

The capability ladder (honest creation — never a false registration)

Creation runs through the same gate in create mode, and the ORDER is load-bearing:

node schedule-recurring-agent/scripts/validate-job.mjs create <job.json> \
  [--capability RemoteTrigger|CronCreate] [--authorize] [--existing <registry.json>]
  1. Validate the schema. Invalid → created:false, exit 2, nothing registered.
  2. List + DEDUP FIRST. Before any capability check, the job's key is looked up in the registry. A match is a correct idempotent NO-OP (created:false, reason:duplicate, the existing id echoed, exit 0) — a re-run never stacks a second routine. This is why the key must be stable.
  3. Capability + authorization. A verifiable automation id (<capability>:<key>) is minted ONLY when a SUPPORTED capability AND explicit --authorize are both present:
    • RemoteTrigger — durable claude.ai Routine (the /schedule skill). Claude Code only.
    • CronCreate — in-session cron. Claude Code only.
    • anything else (Codex, plain CLIs) → NO capability. The gate returns created:false, registered:false, exit 3, and a ready brief for manual/other-platform registration. It NEVER claims a RemoteTrigger/CronCreate registration on a platform that has neither — it degrades and says so. Missing --authorize on a supported platform degrades the same way.
  4. On success the id is appended to the --existing registry, so a later list/create sees it — the id is VERIFIABLE, not invented.

Phase 3: Manage the lifecycle

  • List/inspect existing routines before creating a near-duplicate — extend one rather than stacking overlapping schedules (/schedule list for claude.ai Routines; CronList for in-session crons).
  • When the teardown condition is met (or the user asks), tear it down (disable/remove via /schedule for a Routine; CronDelete for an in-session cron). Don't leave dead routines running.

Success criteria: no duplicate/overlapping routines; completed/cancelled routines are torn down.

Common Rationalizations

RationalizationReality
"The routine will remember what it did last time."It won't — each run is memory-less. Put an idempotency rule in the brief or it re-does/re-spams every run.
"Run it every 15 minutes so nothing's missed."Over-frequent routines burn tokens and create noise. Match the cadence to how often the work actually arrives.
"Let it auto-merge / auto-deploy when it looks good."Irreversible actions need explicit per-action authorization. A routine prepares and reports; it doesn't pull irreversible triggers unbidden.
"No need for a per-run cap, it's a small job."Small-usually is not small-always. A busy day turns an unbounded run into a grind. Bound every run.
"I'll leave it running; it's harmless."A routine with no teardown runs forever, spending tokens for nothing. Give it an off-switch.
"Report only when there's something interesting."Silent runs hide failures. Report what it did, including 'nothing to do' — just don't flood.

Red Flags

  • A brief that assumes memory of prior runs (no idempotency/dedup rule).
  • A cadence far more frequent than the work arrives.
  • A routine authorized to take irreversible actions without explicit per-action sign-off.
  • No per-run bound (one run can grind or fan out unboundedly).
  • No teardown condition; overlapping duplicate routines accumulating.
  • A run that fabricates activity or floods the report channel.

Guardrails

  • Never write a brief that relies on prior-run memory; make it self-contained + idempotent.
  • Never over-schedule; match the cron cadence to the work's arrival rate.
  • Never let a routine take irreversible/external actions without explicit authorization.
  • Never create an unbounded per-run job; declare a per-run cap.
  • Never leave a completed/duplicate routine running; tear it down.

Native goal/loop routing

On Claude Code, a routine's BRIEF should itself be goal-shaped: state the per-run done-condition the way /goal would ("triage every issue opened since the last run; done when each has a label and a priority"), so each scheduled invocation runs as a bounded goal loop rather than an open-ended prompt. Routines are the scheduled form; /loop is the in-session form; this skill is about choosing and briefing the former correctly.

When To Load References

  • scripts/validate-job.mjs — the deterministic job-schema + honest-creation gate (run it in validate mode on the brief, in create mode to stand the routine up dedup-first with a verifiable id).
  • budget-guard (skill) — the per-run bound + escalation contract each invocation enforces.
  • watch-and-act (skill) — for a one-off in-session wait instead of a standing routine.
  • The phase/loop skills (auto-*, converge-loop, …) — the actual work a routine's brief invokes.

Output Contract

Report:

  1. the routine created — its job, cadence (with the rationale), the MECHANISM (claude.ai Routine vs in-session cron) and why, and the idempotency rule
  2. the per-run bound and the report/escalation channel
  3. the teardown condition + how to list/cancel it (via /schedule for a Routine, or the cron tools for an in-session cron)
  4. confirmation it registered (or the duplicate it extended instead)

What ships with it: 1 file

14.5 KB alongside SKILL.md, 1 of them executable

scripts/

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.