POST /v1/responses on that instance’s own gateway, on a fresh session, and the request wakes the instance on its way in.
That last part is the reason to use this instead of the scheduler inside the agent. A crontab inside the container only runs while the container is running, so on an instance with auto-sleep it stops firing the moment the instance sleeps, and it keeps the instance awake for nothing when it doesn’t. A platform cron is outside the instance: it fires whether the instance is awake or asleep, and between firings the instance is free to sleep and cost you nothing but disk.
Crons belong to an instance. Deleting the instance deletes its crons. agent37-n8n takes none: it serves a web app rather than an agent, so there is nothing to send a message to.
Create a cron
prompt and schedule are required.
string
required
What to say to the agent. The same thing you would send as
input on POST /v1/responses, so it can be a whole standing instruction, not just a line. Up to 8,000 characters.string
required
A five-field cron expression: minute, hour, day of month, month, day of week.
0 9 * * 1-5 is 9am on weekdays; */15 * * * * is every fifteen minutes; * * * * * is every minute. Ranges, lists, steps, and three-letter day and month names all work. There is no seconds field: a six-field expression is rejected.string
Which harness runs the firing, for an image that ships more than one:
hermes, openclaw, claude-code, codex, opencode, grok or pi. Omit it and the firing goes to the template’s own agent, which is what a single-harness image wants. Naming a harness the image does not ship means the turn never starts: the run is recorded as skipped with wake_failed.string
Which profile the firing runs in, for an instance that hosts several distinct agents: the same
profile as on POST /v1/responses. Omit it, or send default, for the agent’s own setup. Supported on hermes today: a profile with any other harness is 400 invalid_request, and so is a name that is not lowercase letters, digits, - or _, or an instance whose image is older than profiles (update it first). Whether the instance has the profile is checked when the cron fires: one it does not have means the turn never starts, and the run is recorded as skipped with wake_failed.string
default:"UTC"
An IANA timezone name, for example
America/New_York. The schedule is read in this zone, so “9am” stays 9am across daylight saving.string
A label for your own UI. Up to 80 characters.
boolean
default:"true"
false creates it paused. A paused cron has next_run: null and never fires.The cron object
string
12-character hex id.
number | null
When it last fired on its schedule, epoch seconds.
null until it has. Running it now does not change it.number | null
When it fires next, epoch seconds.
null while enabled is false.number
Epoch seconds.
List, read, edit, delete
PATCH takes any of the create fields and changes only the keys you send: "agent": null hands the firing back to the template’s own agent, and "profile": null hands it back to the agent’s own setup. Changing schedule, timezone or enabled recomputes next_run from now, so a new schedule never replays a window that has already passed; editing only the prompt or the name leaves the next firing exactly where it was. Pausing is a PATCH:
404. An instance holds at most 50 crons.
Run one now
POST /v1/instances/{id}/crons/{cronId}/run fires the cron immediately, whether or not it is enabled, without touching its schedule. It answers 202 with the run record as soon as the run is recorded, before the turn is sent, so a run that reads triggered here can still end up skipped with wake_failed.
Run history
GET /v1/instances/{id}/crons/{cronId}/runs returns the latest 50 firings, newest first.
string
triggered (the turn was started) or skipped (nothing was sent).string | null
The session the firing ran on. Read what the agent actually did with
GET /v1/sessions/{session_id} on the instance URL, adding ?profile= when the cron names one. When the firing goes to hermes, openclaw or claude-code (the cron’s agent, or else the template’s own), it is set when the run is recorded, so the 202 from running it now already carries it. For codex, grok, opencode and pi, whose harnesses issue their own session ids, and on a workspace template when the cron sets no agent, it is null at first and filled in once the turn finishes. It stays null on a turn still running about 13 minutes after the firing (the turn itself carries on). On a skip it is null, except a wake_failed run that was already given an id: that session never started.string | null
Why it was skipped:
instance_stopped, past_due, free_hours_exhausted, or wake_failed.A cron is fire and forget.
triggered means the turn was started, not that it succeeded. The agent’s answer, its tool calls, and any error live in the session, which is where you read them.What fires, and what doesn’t
A sleeping instance is woken and the turn runs. An instance you stopped stays stopped: a schedule never undoes an explicit stop, and the firing is recorded asskipped with instance_stopped. The same goes for an instance suspended for non-payment (past_due).
Each firing opens its own session, so a cron never interleaves with your chat thread and 15 crons never turn into 15 conversations in the same transcript. If a firing is still running when the next one is due, the next one starts its own session as usual.
A window the platform misses (a schedule that came due while the instance was stopped, or a cron paused for a week and then re-enabled) is skipped, never backfilled.
Your agent can schedule itself
The agent running on the instance can create its own crons, with theagent37 cron CLI baked
into every Agent37 agent image:
agent37 cron list, agent37 cron update <id> [--pause|--resume], agent37 cron remove <id>
and agent37 cron runs <id>. The images tell the agent this exists, so “check my email every
weekday at 9” is usually enough; no key is involved, since the CLI uses the credential the
instance already holds.
Anything it creates is an ordinary cron: it appears in GET /v1/instances/{id}/crons, and you
can edit or delete it there like any other.