Tutorials 4 min read

How to run a skill on a schedule in the cloud

A skill runs inside your agent — so a schedule needs somewhere to run without you. Deploy the skill as an app, then schedule the app: cron in your timezone, output emailed or webhooked, no server or CI runner to set up.

Some skills want to run on their own. A morning digest, a nightly check, a weekly report — work that should happen whether or not you’re at your terminal with an agent open. A skill can’t do that by itself: a skill is instructions for an agent, and if no agent runs it, nothing happens. So the question “how do I run my skill on a schedule” is really “where does it run when I’m not there?”

The answer is to give it a home that’s always on — deploy the skill as an app — and then put the app on a timer.

Deploy, then schedule

Deploying turns your skill’s prompt into an app at https://{slug}.skillsafe.ai that runs on our infrastructure. Once it exists, schedule it:

POST /v1/apps/{slug}/schedules
{
  "kind": "agent",
  "cron": "0 9 * * mon-fri",
  "timezone": "America/New_York",
  "input": { "region": "us-east" },
  "deliver_email": true
}

That runs the app’s prompt every weekday at 9am — and 9am means 9am where you are. The schedule is evaluated in your timezone, so it holds its slot across daylight-saving changes instead of drifting an hour twice a year. input is passed to the run exactly as if a user had submitted it, so a schedule is “run this app with these arguments, on this timer.”

Prefer a plain interval? Use "interval_minutes": 60 instead of a cron expression — anything from 15 minutes to 7 days.

Cron, but only as precise as it can honestly be

The cron parser supports the field forms you’d expect: ranges (9-17), steps (*/15), lists (0,30), and weekday names (mon-fri). It follows standard Vixie semantics, including the one people get wrong — when you restrict both day-of-month and day-of-week, they act as a union: 0 9 13 * FRI means “the 13th, and every Friday,” not “Friday the 13th.”

One honest limit: the platform wakes every 15 minutes, so nothing fires more precisely than that. A schedule asking for 03:07 runs at the first tick at or after 03:07. That’s fine for the things people actually schedule and we’d rather tell you than pretend to second-level precision we don’t have.

Getting the output

A scheduled run nobody sees is pointless, so delivery is built in. Set deliver_email: true and the run’s output is emailed to you. Set deliver_webhook_url to an https endpoint and each run POSTs {app, schedule_id, ran_at, output} — into Slack, a database, wherever. A broken sink never disables the schedule: the run already happened and was already billed, so a 500 from your webhook is logged, not fatal.

If a run fails for real — you’re out of credits, or a daily cap is hit — the schedule records why and keeps trying. Ten consecutive genuine failures auto-disable it so a broken app doesn’t burn credits forever; re-enabling resets the counter.

What this replaces

The usual way to run a skill on a timer is a cron job on a server you maintain, or a GitHub Actions workflow with the agent’s credentials in CI secrets and a runner to configure. Both work. Both are infrastructure you now own. Scheduling an app is neither: no server, no runner, no secrets in a YAML file — the app already exists, metered per run, and a schedule is a single API call against it. You bring the timer; we bring the “always on.”

Billed to you at cost — running your own app on a schedule carries no markup. Deploy the skill once, and it can work while you sleep.

More ways to run a skill: on any machine · shared with no install · in a browser