GenerateSaaS

Scheduled agents

Prompts that run automatically on a cadence on the user's device - built-in ones you ship, plus ones the end-user creates - and, when the app is connected, their account's schedules beside them.

A schedule runs a prompt on a cadence, with no user present. A local schedule is entirely on-device: it is stored on the device, fired by the local companion daemon, and executed through the user's own connected CLI - its creation, runs, and results never touch a backend.

When the app is connected to your backend, the Schedules tab also shows the account's backend-origin schedules beside the local ones, origin-tagged (On this device / From <product>). Those are a live projection, read fresh over the app's own session and never stored on the device - disconnect and they vanish from the tab with nothing to clean up. An edit writes through to each schedule's origin (a local edit stays on the device, a backend edit goes to your backend); moving a schedule between the two is not a v1 action.

Schedules appear on the Schedules page, in two sections:

SectionAuthored by
Built-inYou - schedules the app ships. The user enables the ones they want; the prompt and cadence are fixed, and they can never be deleted.
Your schedulesThe end-user, when config.desktop.agents.userSchedules is true (the default). They create, enable, run now, edit, and delete their own.

Set config.desktop.agents.userSchedules to false to ship only your built-in schedules.

When schedules fire

  • While the app is open, by default. The daemon runs with the app, so schedules fire only while the app is running - and the tab says so. A schedule that comes due while the app is closed fires once at the next launch, never once per missed interval.
  • Or in the background. The companion can instead run as a background OS service, so schedules keep firing while the app is closed. That service runs from a stable copy staged outside the app bundle, so an app update or move never strands it - and because it runs detached, config and schedule changes reach it the next time the app opens, not live. The Schedules tab states which mode is active.
  • On an interval - the presets (hourly, daily, weekly) and every-N-minutes are all intervals, with a 5-minute floor. Cron expressions are not supported for on-device schedules.
  • Unattended, confined like chat. A scheduled run goes through the same audited executor as chat: same folder confinement, same local audit log, same policy checks.

Each schedule shows its last run and last result on the tab, and any schedule can be run once on demand. A schedule the user creates starts disabled, so nothing runs until they turn it on.

Run outcomes

OutcomeMeaning
CompletedThe run finished; its output is recorded on-device and readable from the tab.
FailedThe CLI run errored; the schedule waits for its next interval.
BlockedThe device's local policy refuses scheduled work (policy set --local --schedule deny). The refusal is audited like any other run.

Built-in schedules

Built-ins are declared in packages/config/src/ai/schedules.ts and staged into the app at launch. An entry appears on the tab when its surfaces includes "desktop" or is omitted (omitted means every surface); the user controls nothing but the enable switch. Editing a built-in's config requires an app restart to reach the daemon - the staged copy refreshes when the app launches.

On this page