ulpi-io/autonomous-engineering · Archived

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 s…

First seen Jul 6, 2026

Installation

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

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from ulpi-io/autonomous-engineering · top by installs.

npx skills add ulpi-io/autonomous-engineering

Browse all from ulpi-io/autonomous-engineering

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 2
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.2.0
Allowed toolsSkill, RemoteTrigger, Bash, Read, Write, CronCreate, CronList, CronDelete, AskUserQuestion
Declared agents claude-code codex

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 14,105 B
  • docs SUMMARY.md 590 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 3 installs

SKILL.md

<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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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 offline Yes — on Anthropic infra No — only while this session's REPL is idle
Survives closing Claude Yes — persistent No — in-memory; gone when the session exits
Lifetime until you disable/remove it auto-expires after 7 days (one final fire, then deleted)
Per-run token budget no native cap — bound via brief + budget-guard; runs count against plan usage same — 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:

Field What it pins Shape
key a STABLE idempotency + registration key (dedup and the automation id are built from it) [A-Za-z0-9][A-Za-z0-9_-]*
repo where it operates — no reliance on session context string
cadence a TIMEZONE-anchored recurrence (a cron with no tz drifts) `{ timezone, cron\ expression }`
prompt the self-contained brief a memory-less run executes string (≥ 20 chars)
dedup the idempotency rule — marker/state/since-query so repeats don't re-file/re-spam string or object
perRunCap a POSITIVE per-run bound so one run can't grind or fan out `{ maxItems\ maxTokens\ maxMinutes\ maxActions }` or a positive number
reporting the channel each run reports through (incl. "nothing to do") string or object
escalation the stop-and-ask rule for irreversible/ambiguous/high-volume work string or object
teardown the 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.

  1. 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.

  1. 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

Rationalization Reality
"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

  1. the per-run bound and the report/escalation channel
  2. the teardown condition + how to list/cancel it (via /schedule for a Routine, or the cron tools for

an in-session cron)

  1. confirmation it registered (or the duplicate it extended instead)