Skip to main content

Automations

Automations run an instruction on a schedule and deliver the result as a normal chat session. A daily news digest, a weekly review, a monthly report: each run executes headlessly on the server, lands in your chat list, and can be opened and continued like any other conversation.

Anatomy

An automation has a name, free-text instructions, one or more triggers, an optional model (empty means Auto: your default chat model at run time), a run target, and a notification preference (in-app or off). The target decides what a run produces: Chat session (the default) queues the instructions as a conversation, while Work task launches an isolated Work sandbox with the instructions as its opening message, optionally under a named Work policy chosen in the form. With notifications on, a failed run also lands in the notification inbox, so failures reach you even when the Automations page is closed. Names and instructions are encrypted at rest. Every automation belongs to the user who created it.

Triggers reuse the calendar's shared model — once, hourly, daily, weekly, monthly, yearly — and an automation may hold up to five. The next run is always the earliest upcoming occurrence across its triggers, computed in the server's local timezone.

Execution

A scheduler tick runs every minute behind a coordination lease, so exactly one replica advances schedules. When an automation is due, the tick records a run, enqueues a durable automation.run.v1 job, and advances next_run_at with a compare-and-set so each occurrence fires at most once. The job creates a chat session titled after the automation, then queues the instruction through the same durable chat-generation pipeline every conversation uses — provider routing, persona defaults, and persistence included.

If the server was down when an occurrence passed, the next tick fires that occurrence once and skips any older missed slots. Pausing an automation clears its schedule; resuming or editing recomputes it from now. Deleting an automation removes its run history through a foreign-key cascade.

Runs settle from the durable job ledger: succeeded when the chat generation finished, failed when either job dead-lettered, and failed as stalled when a queued run never started within 30 minutes.

Work-target runs behave the same way with the Work lifecycle in place of the chat job: the run records the task it created (the Runs tab links straight to it), succeeds when the agent completes — or stops to ask for input — and fails when the task fails or is cancelled. Work access is enforced when the schedule fires, so revoking a user's Work access also silences their Work-target automations; the run then fails as work-access-denied rather than silently skipping. A selected policy is validated when the automation is saved, and its network default and resource limits apply to every task the automation launches. Only direct model providers run in Work, and the model must support tools — the same rules as the Work composer.

Agent routines

A Work-target automation can instead bind to an existing Work task via workTaskId — the shape behind the Routines section on an agent's detail panel. A bound routine does not create a new task per fire: each occurrence starts a run inside that task's own workspace and conversation, using the task's model, provider, and runtime policy, so the automation-level model and policy fields do not apply and any supplied policy is dropped at save time. The binding is validated when the automation is saved (the task must exist and belong to the caller). At fire time, a deleted task fails the run as work-task-missing, and a task that is already running — or holding a live preview — fails the occurrence honestly as work-task-busy instead of queueing behind it.

Webhook triggers

Beyond the schedule, an automation can be fired by an external system — a CI pipeline, a cron service, home automation. In the automation's edit dialog, Webhook trigger → Enable generates a per-automation secret; only its SHA-256 is stored, so the plaintext is shown exactly once. Rotating the secret invalidates the previous one immediately, and disabling the webhook closes the endpoint again.

The external system fires the automation with:

curl -X POST https://your-host/api/automations/<automationId>/webhook \
-H "Authorization: Bearer lwh_..."

(X-Libre-Webhook-Secret: lwh_... works as an alternative header.) The response is 202 with the queued run id — the same manual-run path as Run now, so runs settle, notify, and appear in history identically. The secret comparison is constant-time, a missing automation and a wrong secret answer identically (no automation-id oracle), and a paused automation answers 409: unlike the owner's Run now, an external caller cannot fire through a pause.

API

All endpoints except the webhook fire require authentication and operate only on the caller's own automations; the webhook fire authenticates with the per-automation secret instead.

MethodPathPurpose
GET/api/automationsList automations
POST/api/automationsCreate an automation
GET/api/automations/occurrences?from=&to=Upcoming computed occurrences
GET/api/automations/runsRun history (filterable)
GET/api/automations/runs/summaryUnseen count + 30-day buckets
POST/api/automations/runs/seenMark finished runs as seen
GET/api/automations/:automationIdRead one automation
PUT/api/automations/:automationIdUpdate an automation
DELETE/api/automations/:automationIdDelete an automation
POST/api/automations/:automationId/pausePause the schedule
POST/api/automations/:automationId/resumeResume the schedule
POST/api/automations/:automationId/runRun now (202 with a run id)
POST/api/automations/:automationId/webhookFire via secret (202)
POST/api/automations/:automationId/webhook-secretGenerate/rotate the secret
DELETE/api/automations/:automationId/webhook-secretDisable the webhook

A user may keep up to 50 automations; names are limited to 200 characters and instructions to 20,000.