Skip to Content
Agent computeScheduled tasks
Raw

Scheduled tasks

What a scheduled task is on Aetherfy

A scheduled task on Aetherfy is an agent that Aetherfy starts for you at fixed times. It is not a separate resource: there is nothing to create, register, or attach. One field in aetherfy.yamlschedule: — turns an agent into a scheduled task, and removing that field turns it back.

Each time a schedule fires, Aetherfy starts a run. The run reuses the agent’s existing image, so there is no build step and no deploy latency at fire time. Runs started this way are recorded with trigger_source=cron, which is how you tell them apart from runs you started by hand. See /agents/runs-and-logs.

Declaring a scheduled task in Aetherfy configuration

Add schedule: to the agent’s aetherfy.yaml and deploy. A complete configuration for a task that runs daily at 03:00 UTC:

name: nightly-report runtime: python3.12 type: job entrypoint: main.py memory_mb: 512 schedule: "0 3 * * *"

Quote the expression. Unquoted, a YAML parser can read some expressions as something other than a string, and Aetherfy needs the literal text.

Deploy it exactly like any other Aetherfy agent:

afy deploy

type: job is a literal configuration value and is required here. Aetherfy only schedules agents of that type, because a long-lived service agent is already running and so has nothing to start on a cadence.

The Aetherfy schedule expression format

An Aetherfy schedule expression is exactly 5 whitespace-separated fields, always interpreted in UTC.

┌───────────── minute │ ┌─────────── hour │ │ ┌───────── day of month │ │ │ ┌─────── month │ │ │ │ ┌───── day of week │ │ │ │ │ * * * * *
PositionFieldRange
1minute0–59
2hour0–23
3day of month1–31
4month1–12
5day of week0–6 (0 = Sunday)

One honest caveat about how Aetherfy validates this. Only the minute field has a hand-written grammar in Aetherfy. Fields 2–5 are handed to the underlying parser, which accepts a broader dialect than the table above — including 7 for Sunday and name forms for the day of week. The table is the supported core, not the outer limit of what will parse. Write expressions that fit the table and your schedule will behave as documented.

Schedule expressions Aetherfy rejects

Aetherfy validates the expression at deploy time, so an invalid schedule fails the deploy rather than silently never firing. Each rejection has its own message.

Rejected inputExampleWhy
Any @-alias@hourlyAliases are not supported — write the 5 fields
6-field syntax with seconds0 0 3 * * *Exactly 5 fields are required
An expression that can never fire0 0 30 2 *”schedule never fires (impossible date combination)” — February has no 30th
A stepped wrapping minute range50-10/15”unsupported minute-field syntax”
Anything firing more often than every 300 seconds*/2 * * * *Below the Aetherfy minimum interval — see below

The minimum interval on Aetherfy

The minimum interval between fires on Aetherfy is 5 minutes (300 seconds). An expression that would fire more often is rejected with:

schedule: fires more often than every 300 seconds (minimum interval). For continuous or sub-interval work, use an always-on agent (keep_alive) instead of a schedule.

That message names the right alternative. If you need work done continuously or faster than every five minutes, a schedule is the wrong instrument — deploy a long-running agent with keep_alive: true and control the cadence inside your own program. Always-on agents require a plan that permits them; see /platform/limits.

Why Aetherfy schedules are UTC only

Every Aetherfy schedule expression is interpreted in UTC. There is no timezone field, and this is deliberate rather than an omission.

A local-time schedule is ambiguous twice a year at daylight-saving boundaries: in the spring the named local time does not exist, and in the autumn it happens twice. Rather than pick a silent policy for those two days, Aetherfy defines schedules in a timezone that has no such boundaries.

If you want a task to land at a fixed local time, convert that time to UTC yourself and accept that it will drift by an hour across a daylight-saving change, or schedule it at a UTC hour where the drift does not matter.

Examples of Aetherfy schedule expressions

ExpressionFires
0 * * * *Every hour, on the hour
*/15 * * * *Every 15 minutes
0 3 * * *Daily at 03:00 UTC
30 2 * * 1Mondays at 02:30 UTC
15 2 * * 1-5Weekdays at 02:15 UTC

Where Aetherfy allows a schedule

Three rules govern where a schedule is valid on Aetherfy.

RuleDetail
Only on type: job agentsA long-lived service agent is already running, so there is nothing to start on a cadence. Aetherfy rejects a schedule on a service agent.
One schedule per agentTo run the same code on two cadences, deploy it as two agents with different names.
Not on a spawned workerAn agent that is spawned as a worker by a parent agent cannot carry a schedule. Rejected with AGENT_SCHEDULE_NOT_ALLOWED_ON_WORKER.

The one-schedule-per-agent rule is worth planning around. Two agents pointing at the same repository directory, differing only in name and schedule:, is the supported way to run one program hourly and also nightly.

Changing or removing an Aetherfy schedule

Aetherfy applies aetherfy.yaml as a merge patch, which gives the schedule field four distinct behaviours depending on what you deploy.

What you deployWhat Aetherfy does
schedule omittedPreserves the existing schedule and does not move the next run
schedule with the same expressionLeaves the cursor alone — the next run does not shift
schedule with a new expressionRecomputes the next run from now
schedule: nullRemoves the schedule, removes its cursor, and clears any pause you had set

The last row matters if you are using pause as a temporary off switch. Deploying schedule: null does not preserve a paused state for later — it clears the pause along with the schedule, so re-adding an expression later starts a live schedule rather than a paused one.

To stop scheduled runs without editing configuration at all, pause instead:

afy agents schedule pause nightly-report afy agents schedule resume nightly-report

Pausing and resuming, overlap behaviour, and missed windows are covered on /agents/managing.

Building a schedule in the Aetherfy dashboard

You do not have to write the expression by hand. The Aetherfy configurator at https://app.aetherfy.com/dashboard/agents/configurator  builds a valid expression from presets and previews the upcoming runs in both UTC and your local time, which is the fastest way to confirm that a UTC expression lands where you expect it to locally.

PageWhat it covers
/agents/task-contractHow your code runs and exits, how it reads input, and the at-most-once guarantee
/agents/managingRunning on demand, pausing and resuming, overlaps, missed windows
/agents/runs-and-logsRun history, run states, and log retrieval
/agents/aetherfy-yamlEvery configuration field and the merge-patch rules
Last updated on