Scheduling
A schedule runs an agent by itself, on the days and at the times you choose. Use it for jobs nobody should have to remember: a sales summary in Slack every weekday at 8:00, a stock check on the last day of the month, a health check every 15 minutes. It works for both kinds of agent: one that works on its own and one you drew step by step.
A schedule runs one task at a set time and posts the result. To keep an autonomous agent working in the background, waking on a timer and when something happens and picking up where it left off, use Always on instead. An agent can have both.

Set up a schedule
- Open the agent and stay on its Overview tab.
- On the Schedule card, click Set up a schedule (or Edit schedule).
- Under When it runs, pick how it repeats:
- At a time of day: every day, weekdays (Monday to Friday), or the days you pick, at a time.
- Once a month: a day from the 1st to the 28th, or the last day of the month, at a time.
- Every few minutes or hours: how often.
- Check the Time zone. It starts as the one on your profile (Settings → Your account). The agent runs at that time there in summer and in winter.
- Under Send the result to, choose where the result goes (see below).
- Say what the agent should do:
- For an agent that works on its own, write the Message it gets each time, the way you would ask it in a chat: “Summarise yesterday’s sales and point out anything unusual.”
- For an agent you drew step by step, fill in What the agent is given: the same starting information for every run, such as
{ "days": 1 }, or{}for nothing.
- Click Save schedule.
While you choose, the page says the schedule back in plain words, for example Every weekday at 8:00, Europe/Berlin, and lists the next few runs. After you save, the card shows the same sentence and when the next run is.
The agent has to be active. A schedule on an agent that is still a draft never runs, so saving one is refused until you activate it.
Send the result to
Every result is kept in the agent’s run history. You can also send it on:
- Only the run history: nothing else.
- The agent’s webhook: the address on the agent’s Webhook card. Add one there first. A scheduled result goes to the webhook only when you choose it here.
- One of the agent’s channels: a messaging app the agent already has on its Channels tab. Choose the channel, then where in it:
| Channel | Where the result goes |
|---|---|
| Slack | A channel the bot is in, picked by name (#sales). Under Other, you can enter a channel ID instead. |
| Microsoft Teams | A channel or chat where someone has talked to the bot. Teams only lets a bot write where it has been talked to, so mention it there once first. |
| One or more email addresses, up to 10, separated by commas. | |
| Telegram | A chat that has talked to the bot, or a channel where the bot is an admin. |
| Discord | A channel, by its ID. |
| Google Chat | The space the channel is connected to. |
| WhatsApp, SMS, iMessage, Signal | A phone number with its country code, such as +14155550100. |
| Matrix, IRC | A room or channel. |
The message goes out the way the channel’s replies do: from the same bot, and counted against the same spending limit. If the channel has reached its limit for the day or month, that run is skipped and you are told why. A long result is split into several messages where an app limits their length.
The AI disclosure line comes once per conversation, as it does for replies: on the first post to a Slack channel, chat or phone number, not on every result after it. Each email starts a conversation of its own, so every emailed result carries it.
WhatsApp only delivers a business message to someone who wrote to that number in the last 24 hours. Outside that window WhatsApp refuses the message, and you are told.
When a message does not arrive
If the app refuses a message (the bot was removed from the Slack channel, a number is wrong), the run still counts as done, and:
- Recent runs on the Overview tab says Posting failed, with the app’s own reason, and
- you get a notification in almyty (and by email, if you turned that on for failed runs).
Stop a schedule
Use the switch on the Schedule card. It keeps everything you set, so turning it back on runs it exactly as before. The runs it already made stay in the agent’s history.
Good to know
- Pausing the agent pauses its schedule; activating it again resumes it.
- A failed run does not stop the schedule; check Recent runs for errors.
- almyty pauses a schedule by itself when it cannot run properly: when the model it uses no longer exists at the vendor, when the member who owns the agent leaves the organization, or when that owner can no longer run it. The agent shows why, and turning the schedule back on starts it again.
- On the night the clocks go forward, a time that does not exist that night (such as 2:30) runs just after the change. On the night they go back, a time that happens twice runs once.
What it costs
Each scheduled run costs what a normal run of the agent costs. Look at Avg cost per run on the agent’s Overview tab and multiply it by the number of runs: about 22 a month for every weekday, 30 for every day, 720 for every hour and 2,880 for every 15 minutes. Run limits and cost governance can cap what an agent spends.
For developers
| Method | Path | What it does |
|---|---|---|
GET | /agents/:id/schedule | The schedule, its plain-words summary and its nextRunAt |
POST | /agents/:id/schedule | Turn it on, or change it |
PATCH | /agents/:id/schedule | The same, with enabled; enabled: false turns it off |
DELETE | /agents/:id/schedule | Turn it off (the settings are kept) |
POST | /agents/:id/schedule/preview | summary and the next three runs, without saving |
GET | /agents/:id/schedule/destinations | The agent’s webhook URL and the channels a result can go to, with the places each can reach |
| Field | Type | Used with | Description |
|---|---|---|---|
kind | interval, days or monthly | all | Defaults to interval |
intervalMinutes | number | interval | 1 to 525,600 (one year) |
time | "HH:MM" | days, monthly | 24-hour, in timezone |
days | number[] | days | 0 = Sunday to 6 = Saturday |
dayOfMonth | number or "last" | monthly | 1 to 28, or the last day of the month |
timezone | string | days, monthly | IANA name such as Europe/Berlin; defaults to the caller’s profile time zone, then UTC |
input | object | all | Passed to every run. An autonomous agent is sent input.message |
deliverTo | object or null | all | { "kind": "webhook" } or { "kind": "channel", "channelId": "...", "to": "..." } |
curl -X POST https://api.almyty.com/agents/$AGENT_ID/schedule \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"kind": "days", "time": "08:00", "days": [1,2,3,4,5], "timezone": "Europe/Berlin",
"input": { "message": "Summarise yesterday'\''s sales." },
"deliverTo": { "kind": "channel", "channelId": "<agent channel id>", "to": "C0123ABCDEF" }
}'to is what the channel reaches: a Slack channel ID, a Teams conversation ID from the destinations list, comma-separated email addresses, a phone number with its country code, a Telegram chat ID, a Discord channel ID, a Matrix room ID or an IRC channel. The server checks it against the channel and answers 400 with a sentence when it does not fit.
Schedules are Bull repeatable jobs: every for an interval, cron plus tz for a time of day (0 8 * * 1,2,3,4,5 in Europe/Berlin; L for the last day of the month). The next-run times the API returns come from the same expression. A tick runs as the agent’s owner, on the engine that owns the agent: an autonomous agent on the autonomous runtime, a workflow on the workflow engine. Both record triggerType: "scheduled". What became of posting the result is on the run as metadata.channelDelivery (status delivered, failed or skipped, the channel, the destination and the app’s error); a webhook delivery is metadata.webhookDelivery.
Review scheduled runs from the terminal:
$ npx @almyty/agents runs daily-reporter --json \
| jq '[.[] | select(.metadata.channelDelivery.status == "failed")]'