Scheduling
Automate recurring and one-time tasks with schedules, the heartbeat, and webhooks - each on its own model if you like
Foxl can run tasks on schedules - automating work 24/7 without you having to prompt it each time.
Three Trigger Types
Cron (Time-Based)
Time-based schedules. Tell the agent in natural language and it creates the schedule automatically, or set one yourself in the schedule editor without writing cron: Repeats offers Every day, Weekdays (Mon-Fri), Weekly on chosen days or Once, each with a time (and, for Once, a date), and shows the cron it saves. Custom (cron expression) is the last option, and a schedule whose cron the picker cannot show opens in it unchanged.
A Once schedule runs a single time at the date and time you pick. The list marks it One-time, and then Done - or Missed, if the computer was asleep or Foxl was closed at that moment and Run if missed was off. When you ask the agent for a one-time reminder, it turns Run if missed on, so a late reminder still arrives. A date that does not exist, such as February 30, is refused instead of being quietly set for a day in March.
| What you say | Cron expression | When it runs |
|---|---|---|
| "Every morning at 7am" | 0 7 * * * | Daily at 7:00 AM |
| "Every Monday at 9am" | 0 9 * * 1 | Mondays at 9:00 AM |
| "Every hour" | 0 * * * * | Top of every hour |
| "First of every month" | 0 0 1 * * | 1st of month, midnight |
Heartbeat (Periodic)
Runs at a fixed interval. Foxl ships one heartbeat, the Feed Generator,
switched off: once you turn it on it wakes hourly between 07:00 and 23:00 and
surfaces items into your Notifications feed rather than replying in a chat.
Everything about it lives under Settings > Heartbeat - the switch, Run
now, the check frequency (every 15 minutes up to once a day, or a custom
interval from 1 minute to 7 days), active hours or Always on, and the
instructions, which are HEARTBEAT.md in your workspace. Run now runs it at any
hour; the active hours apply only to its timed runs. On the Schedules page it
is a locked row: change its cadence, but it cannot be deleted. Heartbeat schedules
of your own cannot be added, from the Schedules page or by the agent; a repeating
task is a cron schedule.
Settings > Heartbeat also has the Morning briefing and Check-ins switches, off until you turn them on. They are not heartbeats: each is a cron schedule on this page (the pre-made Morning Briefing row, and a Check-ins row made when you turn that switch on). See Morning Briefing and Check-ins.
Waiting for something to happen
HEARTBEAT.md takes an optional watch block with a shell command. Foxl runs
that cheap command on the interval and wakes the agent only when its output or
exit code changed - then hands the agent that output, so the run starts already
knowing what it is reacting to.
The block takes command, an optional timeout in seconds (default 20), and
mode: changed (the default - wake when exit code or output differ from last
time) or mode: nonempty (wake whenever the command prints anything, the right
shape for a command that lists work).
A 24/7 agent then stops paying for a model turn every interval just to discover that nothing happened, which means the interval can get shorter rather than longer.
Off unless you configure it. Because HEARTBEAT.md is a file the agent can write, the
command is armed only when you set it: send it with the Feed Generator settings
(PATCH /api/heartbeat/config with { "watch": { "command": "...", "mode": "changed" } };
"watch": null removes it). That writes the block into the file and records the command
outside the workspace. A watch that appears in the file any other way is refused and
logged, and the command goes through your tool approval rules like any shell command - a
run nobody approves is skipped, not executed. With auto-approve off, the question appears
as a card at the top right of the desktop app on whatever screen is open (there is no chat
behind a heartbeat tick), and it waits for your answer (a minute at most with Settings >
Safety > Time out unanswered requests on).
Webhook (External Trigger)
A webhook schedule runs when something sends a POST to its Trigger URL, which the schedule's editor shows once you save it:
POST http://127.0.0.1:13847/api/webhook/<secret>- The long random part is the secret, and it is the only credential: the call needs no sign-in and no connection token, so anyone who has the URL can run the schedule. Regenerate it if it leaks.
- It works from this computer only - curl, a git hook, a local cron job or another app on this machine. Foxl does not accept connections from other machines, so GitHub, Zapier or another computer cannot call it directly. To reach it from outside, run a tunnel or reverse proxy on this computer that forwards to the URL; the editor's note under the URL says which host settings that forwarder needs.
- It answers as soon as the run is queued and says nothing about the run itself; the result arrives like any other scheduled run's.
- The URL is shown in Foxl on the computer that runs the schedule. On the phone or app.foxl.ai, open the schedule on that computer to copy it.
What ships with the page
Schedules arrives with five pre-made jobs, all switched off:
| Pre-made schedule | When |
|---|---|
| Morning Briefing | Weekdays at 08:30 |
| Evening Wrap-Up | Weekdays at 18:00 |
| Weekly Review | Fridays at 17:00 |
| Memory Tidy - a pass over what Foxl remembers about you | Sundays at 22:00 |
| Points Check - points and credits on your sites that expire within 30 days | Saturdays at 10:00 |
The page lists the heartbeat beside them, so a new install reads 0 of 6 enabled:

The first time you open Schedules, they are named in the app's language, and so are their cards under Start from a pre-made schedule; schedules you already have keep their names.
They are there so the page shows what an agent can do on a schedule instead of an empty list. Nothing runs until you turn one on - Foxl does not start doing work on your machine because you installed it.
Otherwise they are completely ordinary schedules: edit the prompt, change the time, Run now, delete. Deleting one is permanent and it does not come back on the next launch. When you want it back, "Start from a pre-made schedule" appears under the list showing exactly the ones you do not currently have.
Creating Schedules
Just tell the agent what you want automated:
"Summarize my email every morning at 8am"
The agent will:
- Create a cron schedule (
0 8 * * *) - Set the task prompt ("Check Gmail and summarize unread emails")
- Start executing on schedule

With auto-approve turned off in Settings > Safety, the agent asks before it creates or changes a schedule, because a schedule's instructions later run with nobody watching. Listing and reading schedules do not ask.
Even with auto-approve on, a scheduled run that would send a card number or an ID number, or send money, move it between accounts or trade in the browser, waits for your answer, and so does a purchase, a subscription, a plan change, a refund or a cancellation when you turned on its switch under Settings > Safety > Purchases. When nobody can be asked then, the send waits in the run for your OK for 12 hours: your phone gets a notification while remote access is connected, the next check-in names it in the From Foxl chat, and Approve sends it once, after the run. A browser step that asks before it pays, books or moves money waits for your answer in the run: the run pauses there and goes on once you answer it in Foxl, on this computer or your phone. A scheduled run has nobody watching it, so every money step in it (a purchase, a booking, a subscription, a refund or a cancellation) shows its card first even with those switches off (the default), and so does a step on a page Foxl could not read. Every other step a scheduled run asks about (with auto-approve off, or with schedules on Ask first) waits the same way. See Steps that always ask and Approvals.
You can also be more specific:
"Every weekday at 6pm, check my GitHub notifications and send me a summary on Slack"
Or set one up by hand: Create Schedule on the Schedules page opens the editor, with a name, the type (Cron or Webhook), Repeats and a time for a cron, the prompt the agent runs, the Model and Run if missed.
A schedule can also run as one of your roles, with that role's instructions and only its tools: ask for it in a chat ("have my analyst brief me every Monday"). See A schedule that runs as a role.
Managing Schedules
Open the Schedules page in the sidebar to see:
- All active schedules with their trigger type and timing, as a List or on a Calendar, and every run under Runs
- Human-readable descriptions (e.g., "Daily at 7:00 AM"; a cron the page cannot put into words reads "Custom schedule", with the expression under it)
- Run history with success/failure status and duration
- Enable/disable toggles for each schedule, and Run now
Each schedule can run on its own model. Model in the editor is Same as Foxl Agent by default; pick another model for that schedule only. If the model you picked is no longer available on this computer, the run uses Foxl Agent's model and its result says so. When the model you pick offers Ultrafast (GPT-6 Astra through your own Amazon Bedrock connection), the editor also shows an Ultrafast switch for that schedule, which runs it faster at a multiple of the Standard rate (the switch says how many times); off uses Standard. It does not appear while the schedule uses Same as Foxl Agent. A schedule already saved with Same as Foxl Agent and Ultrafast on keeps it, and its editor shows the switch so you can turn it off or pick the model.
A schedule that keeps failing is paused, not switched off. After 3 failures in a row the page shows it as paused with the last error and a Resume button, a notification says so, and it keeps retrying - no sooner than an hour, then six hours, then a day after the last failure - until one run succeeds.
Watches and triggers are listed there too: see Watches and Triggers below.
Unattended runs are where a rate limit or an outage hurts most. Settings > Model & provider > Automatic fallback lets you list models to try, in order, when the one you picked is unavailable; it only engages after Foxl's own retries are exhausted, and it is off until you turn it on.
On OpenRouter, the Only free models switch in the same pane applies to scheduled runs too, so a key with no credit can still run a schedule.
Watches
Ask Foxl to keep an eye on a page until something happens ("tell me if a seat opens up on the 18:00 KTX") and it sets up a Watch on the Schedules page. A watch checks one page on an interval, looks for what it was told to wait for (When "..." appears, When "..." is gone, or a number above or below a value), and uses no model for a check. The row says how often it checks and until when, and how many of its checks are used, and Check now checks at once.
-
Its limits. A watch checks at most every 5 minutes, ends by a date at most 30 days ahead or after its number of checks, and stops at the first find. Foxl runs one watch per site and at most 10 at once. A site Foxl has learned should be checked less often is checked at that pace. A page that answers "too many requests" or a server error makes the watch check less often; that, or no answer, counts as a failure, and three failures in a row pause it. Any other error page (a 404, for example) ends the watch and says so. A CAPTCHA or an "are you human" page stops the watch and says so; Foxl never solves one. A site on the Web Access blocked list cannot be watched.
-
In Foxl's browser. A watch can also wait for something on a page that builds its content with JavaScript, or on a page behind a site's sign-in, using the sign-in Foxl saved for that site. Foxl checks those in its browser on its own, with no window: each check opens the browser for a few seconds and closes it, still at most every 5 minutes and without the model. The row says In Foxl's browser. A site that turns away automated browsers still stops the watch and says why.
-
When the site signs you out. The watch signs in again with the sign-in you saved for the site, by itself, and keeps watching. The chat where you asked for the watch gets one line, Signed in to (site) again and kept watching, with Don't use it again (see Signing in with a saved sign-in). It is one line per watch: each later sign-in updates it with how many times and when the last one was. A code from a 2FA setup key you saved for the site is typed in too. The watch pauses and asks only when it needs you, and once you answer it goes on by itself:
- the site does not take the saved sign-in: Sign in to (site) again asks for it;
- the site sends you a code by text or email: the code card asks for it;
- the site signs you in on another site: Foxl asks Use your (name) sign-in on (site)?;
- the site asks for a check that you are human (a CAPTCHA, for example): Foxl never solves one, so you get a notification and the Foxl's browser card in the From Foxl chat. Open browser shows that page on your computer or your phone; finish the check, tap I'm done, and the watch reads the page again and goes on. Until you do, the watch stays paused and the card stays;
- nothing is saved for the site, or Settings > Safety > Ask before Foxl uses a saved sign-in is on: the sign-in card asks.
When Foxl cannot sign in by itself (a form it cannot fill), the row says Paused: Foxl could not sign in to (site) with your saved sign-in. Sign in to it in a chat, then switch this watch on.
-
When it finds it. The find is posted in the From Foxl chat with one notification, and the chat where you asked for the watch gets one card, Found: (name), with what the page showed, when it was checked and a link to the page. Book it sends your go-ahead in that chat, so the booking is an ordinary chat turn and the step that pays runs like any other purchase, on its approval card when Settings > Safety > Purchases > Ask before purchases is on. A watch never books or buys by itself. Ask for a watch that also prepares the booking, and at the find Foxl reads what it can (your notes and past chats) to say what booking it would take, without booking anything.
Triggers
A trigger runs when something new arrives instead of at a time. Ask for one in a chat, in Foxl on your computer as on your phone or app.foxl.ai: it starts watching right away, with Pause and Delete on its card in the chat. When that chat had already read text someone else wrote, such as a web page, an email or a command's output, the trigger is saved without starting, and its card says Not watching yet with Start; only you start it, on the card or under Schedules. To confirm each trigger before it starts, and again before one is switched back on, turn on Settings > Safety > Ask before Foxl starts watching for events. Three kinds:
- New mail in Outlook ("when an email from my landlord arrives, summarize it"), with Microsoft 365 connected.
- New messages in a Slack channel ("when a new bug report lands in #support, draft a fix plan for me to review"), through your Slack connection under Settings > Tools > Integrations (not the Slack bot under Settings > Connect > Messages). New messages in that channel start it, from anyone but you and from apps too; replies in threads do not, and editing a message does not start it again. It tells you in Foxl, and anything it would post in Slack waits for your OK first.
- New mail in a mailbox Foxl reads with an app password ("when mail from my landlord arrives in Naver Mail, summarize it"): Naver Mail, Daum, Kakao, iCloud, Gmail by app password and the other services Foxl reads mail from, once you have given Foxl the mailbox's app password in a chat. Foxl keeps one connection open between checks where the mail service allows it, signing in again only when the service has closed it, and nothing in the mailbox is marked read or moved. Mail that was already there when you set it up does not start it. If the mailbox refuses the saved app password, the trigger pauses rather than keep trying it, and the card for a new app password appears in the chat where you made the trigger; save it there and the trigger starts watching again. If the mailbox will not open your account, the trigger stays on, tries once every 6 hours and starts watching the moment the mailbox opens.
A trigger's run follows Settings > Safety > By where a run comes from > Runs started by incoming mail or messages, which shows Same as Schedules until you choose otherwise. Since someone else writes the mail or message that starts it, it still asks before it sends anything, before any payment, and, unless you choose Full access on that row, before a step that could carry what it read off your computer; see Security. With nobody at Foxl, such a step waits in the trigger's run for your OK.
Each trigger is listed under Triggers in the List view, with what it watches for (for a Slack one, the channel, whose messages and which words count), what it does, when it last checked and how many times it has run, and its limits (at most so many emails or messages an hour, and runs a day). When it cannot read its source it says Can't read Outlook, Can't read Slack or Can't read Naver Mail and why, for example Slack is not connected on this computer., and a mail trigger its mailbox paused or holds says why and what starts it again; one waiting for you to start it says so. Switch one off to pause it; switching it back on starts it at once and says what it watches, with Pause. Delete, here or on its card in the chat, removes it with Undo for 8 seconds, and it stops watching at once (to be asked first, turn on Settings > Safety > Confirm before deleting).
Use Cases
Morning Briefing
Schedule a daily briefing that checks your email, calendar, and news:
"Every morning at 7am, read my Gmail, check my Google Calendar for today, and give me a briefing"
Or turn on the built-in Morning briefing in Settings > Heartbeat; see Morning Briefing and Check-ins.
Competitive Monitoring
Track competitor activity on a daily basis:
"Every day at noon, check globex.example.com for any new blog posts or product updates"
Git Status Reports
Get daily summaries of repository activity:
"Every weekday at 5pm, show me a summary of today's git commits across all my repos"
Health Checks
Monitor your services with regular pings:
"Every 5 minutes, check if api.example.com is responding and alert me if it's down"
Schedules run on your computer, so it has to be awake and Foxl's local server has to be up. With Settings > General > Keep running when closed on (see Background service) the scheduler lives in the background service, so quitting the app window does not pause it. If the machine sleeps, schedules pause either way. Settings > General > Keep this computer awake (off by default) keeps the screen on and stops the computer from going to sleep on its own while Foxl is running, so a long run is not cut off halfway and the next scheduled run finds the computer awake. With Keep running when closed on, it keeps working after you quit the app. Closing the lid or choosing Sleep still sleeps the computer, and it does not wake a computer that is already asleep.
A missed run is skipped unless you ask otherwise. If a cron job was due at 7am while your laptop was asleep it does not fire retroactively when you wake it - only the next scheduled time does. Each schedule has a Run if missed switch in its editor: turn it on and Foxl runs it once on the next startup instead. Plan accordingly for critical automations - keep the service running or use an always-on machine.
Execution History
Every schedule run is logged with:
- Timestamp
- Duration
- Success or failure status
- Output summary
View the full history on the Schedules page, where each run opens on its transcript, or ask the agent: "Show me the last 5 runs of my morning briefing schedule." In Runs, a check-in or a morning brief that had nothing to tell you reads Nothing new since the last check-in (or Nothing new to brief you on).
Results in From Foxl
A chat called From Foxl holds the messages Foxl writes to you on its own. When a schedule finishes or fails, its result is posted there, so you can reply to it in the same place; the whole run is still on the Schedules page. It is listed by date with your other chats and moves up when a result is posted. On a phone a label over each posted result shows how that schedule stands when you open it (running, failed, paused after repeated failures, or fine); tap the label to open Schedules. Delete From Foxl to start it clean: the next result posted begins a new, empty one. To stop results being posted there, switch off From Foxl in Settings > Heartbeat (or archive the chat); each result then stays with its run, with its notification. Heartbeat runs are not posted, and runs from before this version stay where they were.
Notifications
A run that fails sends a notification on this computer, and so does one that pauses its schedule after repeated failures. A run that finishes sends one only while Task Completed is on under Settings > Notifications > Schedules, which is off on a new install (a computer that already used Foxl keeps it as it was). The notification opens the result in the From Foxl chat when it was posted there, and the run otherwise. A run also reaches your phone as a push under Scheduled tasks when the phone app is set up for notifications.