Overview
Overview
Automations
An automation is an app-owned project that fires on a trigger — a cron schedule, an inbound webhook, or a manual "Run now" — instead of waiting for a UI click. It lives on disk as a directory inside its owning app:
<appCodeDir>/automations/<id>/ automation.json # the manifest (this is the source of truth) handler.js # the generated handler the runtime executesThat directory is the automation. There is no separate registration step, no SQLite definition table; the manifest file on disk is the only thing the scheduler needs to register the trigger and the runtime needs to execute the handler.
Two structural shapes, one runtime
You'll encounter automations in two flavors. They run identically:
1. A UI app that also owns automations. A regular app — index.html, queries, actions, the lot — with an automations/<id>/ subdirectory carrying one or more automations that operate on the app's data. The Hydrate template's weekly-encouragement is this shape: a hydration tracker that also writes a Sunday-evening summary into its own table.
2. A headless automation app. An app whose folder exists only to hold automations — no index.html, no UI, empty actions[] and queries[] in app.json. The convention is to prefix the app id with auto. (e.g. auto.briefing, auto.email-triage). The desktop gallery uses the prefix as a hint to render the app in the Automations section instead of among UI apps.
There is no kind: "automation" flag in app.json and no headless: true field. The auto. prefix is a convention, not a runtime permission boundary. Whether an app has a UI is determined by whether index.html exists.
# Per-app automation (Hydrate)hydrate/ app.json index.html queries/get-today.js actions/set-cups.js automations/ weekly-encouragement/ automation.json handler.js # Headless automation app (Briefing)auto.briefing/ app.json # actions: [], queries: [] automations/ briefing/ automation.json handler.jsWhat a trigger does
When a trigger fires — the cron clock hits its expression, or an HTTP POST arrives at the webhook route — the runtime:
- Resolves the automation by its handle (
<appId>/<automationId>) and reads the manifest. - Spawns a worker thread, loads
handler.js, and invokes its default export with{ ctx, log, input }. - The handler runs JavaScript. It can call MCP tools via
ctx.tool, ask the model for a constrained turn viactx.agent({ prompt }), read/write its KV state viactx.state, look at prior runs viactx.runs, and chain to another automation viactx.invoke. See Handler runtime. - The handler returns
{ summary?, output? }. The summary shows in the run list; the output is persisted in the run ledger and validated againstoutputSchemaif declared. - Tool calls, model turns, sub-invocations, and the final result are written to per-app
runtime.sqliteas arunsrow plusrun_nodeschildren. See Run history.
The manifest's prompt is the human intent the builder agent originally translated into handler.js. At runtime it's documentation — what the handler is supposed to do. The handler itself is the executable, and you're free to edit it.
What an automation can not do
A few load-bearing constraints, called out so they don't surprise you:
- No direct database access. Automation handlers don't get the
dbproxy that queries and actions receive. If an automation needs to read or write the parent app's data, it does so by calling the parent app's tools throughctx.tool— going through the three-tool dispatcher the same way a UI iframe would. - No UI surface. Automations have no
index.html, no iframe, no postMessage channel. They communicate by writing data (via tools) and by emitting summaries into the run ledger. requires.modelcan't becentraid-mock/*. The mock provider is reserved for testing and would recurse into the runtime. The manifest validator rejects it.- Webhook triggers don't fire on the desktop. They're preserved in the manifest, but the desktop is a gateway client, not an HTTP host. Webhook fires happen only when the app is deployed to a remote gateway. See Webhooks.
What's in this section
Every field of automation.json, what's required, what defaults apply, what's rejected at validation time.
Cron, webhook, and pending-webhook triggers. Multi-trigger composition. Manual fire.
The ctx surface — tools, agent turns, KV state, prior runs, cross-automation invocation, onFailure.
/_centraid-hook/<slug>, the provisioning handshake, secret hashing, rate limits.
Per-app runtime.sqlite, the runs ledger, retention policies, audit nodes.
How the agent scaffolds handler.js from a prompt and hands pending webhooks back to the server.