Skip to content

Automations

Make CompozyOS run an agent, a Loop, or a task on its own — on a schedule, when something happens, or when another app calls a link.

For people running agent work7 pages in this section

An automation is work that starts without you. You decide when it starts and what it does, and CompozyOS runs it, records every run, and shows you whether the last one worked.

Every automation reads as one sentence with up to three parts:

  • Starts — on a schedule, when something happens inside CompozyOS, or when another app calls a link.
  • Only if — optional conditions for event and link automations ("only if the stop reason is error").
  • Does — ask an agent, start a Loop, or create a task.

For example: "Every weekday at 09:00 UTC, ask summarizer." or "When a session stops in checkout-api with an error, start the Loop software-delivery."

Start with a tutorial

Each tutorial ends with a working automation and a way to check that it ran.

How an automation starts

In the Web UIWhat starts itCanonical name (CLI, API, tools, config)
On a scheduleA time: a repeating calendar time, a fixed interval, or one momentjob — compozy automation jobs, [[automation.jobs]]
When something happensAn event inside CompozyOS: a session starts or stops, a hook finishes, an extension sends an eventtrigger — compozy automation triggers, [[automation.triggers]]
When another app calls a linkA signed HTTP request from CI, a deploy tool, or any other apptrigger with event = "webhook"

The Web UI shows both kinds together in one Automations window. The CLI, the HTTP and UDS API, the native tools, and config.toml keep the two canonical nouns, job and trigger, because they have different fields: only jobs have a schedule and Run now, and only triggers have an event and conditions. The start you choose decides which one CompozyOS creates, and it can't change after creating.

What an automation does depends on how it starts:

DoesOn a scheduleWhen something happensWhen another app calls a link
Ask an agentYesYesYes
Start a LoopYesYes, if the Loop allows that startYes, if the Loop allows that start
Create a taskYesNoNo

Where to find them

  • Dock → Automations opens the listing at /automations. The All · Scheduled · On events views split it by how each automation starts; link automations count as events.
  • Command palette (⌘K): "Open Automations", "New scheduled automation", and "New automation on an event". Typing a name finds automations of both kinds.
  • Loop page → Automate ▾ creates an automation that starts that Loop, on a schedule or when something happens.
  • Settings → Automation holds the time zone for schedules, how many scheduled automations can run at once, and the default run limit.

Each row in the listing shows the sentence, the next run (schedules) or when it last ran (events), the last run's result, and an On/Off switch. A failed last run reads "Last run failed 7h ago" on the row, so you see it without opening anything.

Check whether an automation worked

Every job and trigger carries its most recent run as last_run. It is the same run that the detail page lists first, and it is absent when the automation has never run.

compozy automation jobs --workspace checkout-api -o json | jq '.jobs[] | {name, enabled, next_run, last_run}'
{
  "name": "nightly-delivery",
  "enabled": true,
  "next_run": "2026-10-08T02:00:00Z",
  "last_run": {
    "id": "run_nightly_delivery_042",
    "status": "failed",
    "started_at": "2026-10-07T02:00:01Z",
    "ended_at": "2026-10-07T02:00:01Z"
  }
}
last_run fieldMeaning
idRun id; the same run as the first item of …/{id}/runs?limit=1
statusscheduled, running, delegated, completed, failed, or canceled
started_atWhen the run started, if it did
ended_atWhen it ended; absent while it is still running
skip_reasonself_overlap or misfire_grace_exceeded, only when the fire was skipped (the run is stored as canceled)

The human tables of compozy automation jobs and compozy automation triggers add a Last Run column: the status and how long ago it started ("failed 7h ago"), or — when it never ran. A skipped fire reads skipped (an overlap) or missed (CompozyOS was off at the start time), never canceled; skip_reason in the JSON carries the same distinction. -o toon adds last_run_status (the raw status) and last_run_started_at.

Both list commands also take --target agent|loop|task to filter by what the automation does, and the HTTP routes and compozy__automation_jobs_list / compozy__automation_triggers_list accept the same target filter. task matches jobs that create a task; on triggers it matches nothing.

compozy automation jobs --workspace checkout-api --target loop -o json | jq -r '.jobs[].name'
nightly-delivery

Reference

Tool and CLI parity

Automation lifecycle is agent-manageable. The compozy__automation toolset and HTTP/UDS APIs expose the complete Agent-or-Loop request union. The compozy automation CLI reaches the same validators and writers for its supported flags. Create commands author Agent or Loop targets; update commands change common fields without replacing the target union. Read and lifecycle verbs operate on either kind:

SurfaceRead toolsMutation toolsCLI coverage
Suggestionscompozy__automation_suggestions_listcompozy__automation_suggestions_accept, compozy__automation_suggestions_dismissList, create the proposed Job, or dismiss
Jobscompozy__automation_jobs_list, compozy__automation_jobs_get, compozy__automation_jobs_historycompozy__automation_jobs_create, compozy__automation_jobs_update, compozy__automation_jobs_delete, compozy__automation_jobs_trigger, compozy__automation_jobs_enable, compozy__automation_jobs_disableAgent/Loop creation; common updates; all lifecycle
Triggerscompozy__automation_triggers_list, compozy__automation_triggers_get, compozy__automation_triggers_historycompozy__automation_triggers_create, compozy__automation_triggers_update, compozy__automation_triggers_delete, compozy__automation_triggers_enable, compozy__automation_triggers_disableAgent/Loop creation; common updates; all lifecycle
Runscompozy__automation_runs_list, compozy__automation_runs_get—compozy automation runs ...

List and get results carry last_run. The list tools use the Web UI nouns in their descriptions: compozy__automation_jobs_list lists "scheduled automations" and compozy__automation_triggers_list lists "automations on events", so an agent can connect what a person sees to the canonical tool.

Mutations require approval, run through the same domain validators as CLI/HTTP, and reject raw webhook secrets with deterministic codes including AUTOMATION_SCOPE_FORBIDDEN, AUTOMATION_SECRET_INPUT_FORBIDDEN, AUTOMATION_VALIDATION_FAILED, and AUTOMATION_APPROVAL_REQUIRED. Webhook secret material stays write-only on mutation surfaces and is referenced through webhook_secret_ref.

Upgrading from v0.3

v0.4.0 replaced the separate Jobs and Triggers windows with one Automations window. Your automations, their runs, and every config.toml key are unchanged. What moved:

  • Saved desktops reopen with an Automations window wherever a Jobs or Triggers window was, on the matching path and in the same place. Nothing you had open is closed, and the migration is permanent.
  • Command palette pins, recents, and usage for "Open Jobs" and "Open Triggers" merge into "Open Automations".
  • Old web links redirect to the new location until v0.5.0:
Old linkOpens
/jobs?enabled=true&q=nightly/automations?start=schedule&enabled=true&q=nightly
/jobs/<job-id>/automations/jobs/<job-id>
/triggers?event=session.stopped/automations?start=event&q=session.stopped
/triggers/<trigger-id>/automations/triggers/<trigger-id>
/jobs?create=loop&loop=<name>/automations?create=loop&start=schedule&loop=<name>
/triggers?create=loop&loop=<name>/automations?create=loop&start=event&loop=<name>

The app ids jobs and triggers became automations. During v0.4.0 the old ids still work and warn; v0.5.0 removes them, after which they fail like any unknown id:

Old inputReplacementWarning in v0.4.0
compozy window open --app jobs or --app triggers--app automationsstderr: app "jobs" is deprecated and will be removed in v0.5.0; use "automations"
app: "jobs" or "triggers" in window commands and window_layout resourcesapp: "automations"log windowmanager.app_id_deprecated
Palette ids app.open.jobs, app.open.triggersapp.open.automationslog cmdpalette.command_id_deprecated
Palette ids palette.view.jobs, palette.view.triggerspalette.view.automationslog cmdpalette.command_id_deprecated

Scripts that use compozy automation jobs|triggers, /api/automation/*, or the compozy__automation_* tools need no change: their only difference is the added last_run field and the optional target filter.

On this page