Events¶
Every meaningful change is recorded as an event with a name, a sequence number, an occurred time, a resource (run, task_run, flow, schedule, rule, or custom), related resources, and a JSON payload. Rules match on events, the Events page and GET /api/events list them, and new ones arrive on the SSE stream as event.created.
The names below are the whole catalogue. It is declared once, in crates/core/src/events.rs, and every site that records an event names it from there, so this page is generated rather than maintained. GET /api/vocabulary serves the same list to the UI, and cereyan.events exposes it to Python: events.run.failed is the string "run.failed".
Run events¶
Resource run; related flow and the run's tags. Offline the payload is state and message only.
| Event | Payload | When |
|---|---|---|
run.scheduled |
state, state_type, message, flow, project, parameters, created_by |
The run is created, or re-enters Scheduled for a crash rerun |
run.pending |
state, state_type, message, flow, project, parameters, created_by |
An engine accepted the run |
run.running |
state, state_type, message, flow, project, parameters, created_by |
User code started |
run.completed |
state, state_type, message, flow, project, parameters, created_by |
The run finished without error |
run.failed |
state, state_type, message, flow, project, parameters, created_by |
The run raised, timed out, or was set failed |
run.crashed |
state, state_type, message, flow, project, parameters, created_by |
The engine died while the run was executing |
run.cancelled |
state, state_type, message, flow, project, parameters, created_by |
The run was cancelled |
run.late |
state, state_type, message, flow, project, parameters, created_by, scheduled_time, name |
The scheduled time passed 15 seconds ago and the run has not started |
run.retrying |
state, state_type, message, flow, project, parameters, created_by |
A retry attempt started |
run.skipped |
state, state_type, message, flow, project, parameters, created_by, reason |
The run ended Skipped: on_overlap="skip", a backfill value already done, a catch-up drop, a fire a person skipped (reason user), or an upstream run skipped that way (reason upstream) |
run.paused |
state, state_type, message, flow, project, parameters, created_by |
The run is waiting on wait_for_input |
run.resumed |
state, state_type, message, flow, project, parameters, created_by |
The run was answered and its next attempt scheduled |
AwaitingRetry, AwaitingResource, and Cancelling record no event.
Task run events¶
Resource task_run (id is the task run's external id, name its dynamic key); related run and flow. Offline the payload is state and task_run.
| Event | Payload | When |
|---|---|---|
task_run.running |
task, dynamic_key, state, message, flow, project |
The task started |
task_run.completed |
task, dynamic_key, state, message, flow, project |
The task returned |
task_run.failed |
task, dynamic_key, state, message, flow, project |
The task raised or timed out (after its retries) |
task_run.cancelled |
task, dynamic_key, state, message, flow, project |
The task was cancelled with its run |
task_run.skipped |
task, dynamic_key, state, message, flow, project |
The task's output= target already existed |
task_run.cached |
task, dynamic_key, state, message, flow, project |
The task returned a persisted result |
Flow events¶
Resource flow.
| Event | Payload | When |
|---|---|---|
flow.registered |
flow, project, module |
The server registered the flow at start or on handoff |
flow.disabled |
failures, window_seconds, until |
disable_after tripped; the flow's schedules are paused until until |
flow.enabled |
empty | The disable window ended and the schedules resumed |
flow.fan_in |
key, value, upstream, run_id |
Every upstream completed a run for the key value and the downstream run was created |
Schedule events¶
Resource schedule, related flow.
| Event | Payload | When |
|---|---|---|
schedule.paused |
schedule_id, reason |
A schedule was paused from the UI, the API, an MCP tool, a rule, or a disable window |
schedule.resumed |
schedule_id |
A schedule was resumed |
schedule.catchup |
schedule_id, policy, missed, created, dropped |
The server started and applied the catch-up policy to fires missed while it was down |
schedule.skips_dropped |
schedule_id, dropped |
An edit, or a restart that restored a code declaration, left skipped fires the schedule no longer produces, and they were forgotten |
Resource events¶
| Event | Payload | When |
|---|---|---|
resource.exhausted |
resource |
A run waited for a resource that had no capacity; recorded once per wait |
Rule events¶
Resource rule, related the run and flow of the triggering event.
| Event | Payload | When |
|---|---|---|
rule.fired |
rule_id, rule, event, event_id |
A rule matched an event and its actions started |
rule.action.completed |
rule_id, action, index, detail |
One action finished |
rule.action.failed |
rule_id, action, index, error |
One action failed, including a template that did not render |
expectation.armed |
id, rule_id, key, run_id, deadline |
A proactive rule's when event armed an expectation |
expectation.met |
id, rule_id, key |
The expected event arrived before the deadline |
expectation.lapsed |
rule_id, rule, flow, project, run, run_name, expected, deadline, armed_at, expectation_id |
The deadline passed, or a clock-armed rule's tick found no matching event; the rule's actions run against this event |
Runs created by a rule record created_by = rule:<id>, and a rule never fires on events of runs it created unless allow_self is set.
Custom events¶
cereyan.emit_event(name, payload=None, resource=None) records any name of your own. Inside a run the resource defaults to that run and the task run is recorded; outside a run the event goes to the store, or to the server's POST /api/events when one holds the store.
Names with a dot-separated prefix, such as orders.table_empty, match rules with events: ["orders.*"].
The prefixes run., task_run., flow., schedule., resource., rule., expectation. are the engine's. A name under one of them that is not in the catalogue above is rejected by emit_event, by @app.rule, and by the rules API, because nothing would ever emit it — a rule matching one could only ever sit silent. Every other name is yours and is never checked.
Stream messages¶
The SSE stream at GET /api/stream carries live notifications for the UI. They are not stored events and rules cannot match them, even where a name is shared with one: run.updated is a stream message, so a rule naming it is rejected.
| Message | Data | Sent when |
|---|---|---|
hello |
latest, since |
The connection opens, before any backlog |
run.updated |
The run | A run was created or changed state |
task_run.updated |
The task run | A task run was created or changed state |
log.appended |
run_id, last_id, count |
New log lines arrived |
event.created |
The event | Any event was recorded |
flow.registered |
The flow | A flow was registered or re-registered |
rule.updated |
The rule, or id and deleted |
A rule was created, edited, fired, or deleted |
variable.updated |
The variable, or name and deleted |
A variable was set or removed |
artifact.updated |
The artifact | A run published or updated an artifact |
schedule.updated |
The schedule, or id and deleted |
A schedule was created, edited, paused, resumed, or deleted |
backfill.created |
backfill_id, flow_id, count |
A backfill created its runs |
backfill.updated |
backfill_id, cancelled |
A backfill was cancelled |
expectation.armed, expectation.met, expectation.lapsed |
id, rule_id, and the key or the event |
A proactive rule armed, disarmed, or lapsed an expectation |
resync |
latest |
The client asked for a sequence number older than the replay buffer; refetch everything |
Each message carries the sequence number as its SSE id. Reconnect with ?since=<seq> to replay what was missed, or receive resync when the buffer no longer reaches back that far.