defineAlert.
Define an alert
alerts/error-spike.ts
schedule takes a 5-field cron expression or an @every interval (@every 5m, @every 1h30m), evaluated in UTC. An alert evaluates at most once a minute — every tick scans your spans, so sub-minute intervals are rejected. In the CDK enabled defaults to true, so a deployed alert is armed; set it to false to deploy one without arming it. folder files the alert under an "alert"-kind folder.
Scope: what it watches
The scope’skind names the data source. Each source pairs with its own metric menu, so a metric can never be asked of a source that can’t compute it.
Spans scope
kind: "spans" watches span telemetry directly. Use any subset of these filters; omitted fields don’t narrow. They mirror the Spans view.
parentAgent and agent are different filters. parentAgent matches spans
of runs an agent started — the agent-trigger case. agent matches an agent
node running inside the watched spans.SQL scope
kind: "orchestrationSql" runs read-only SQL over your orchestration data — the spans, runs, batches, and records tables, automatically scoped to your workspace. The query computes the value itself, so the threshold carries only the comparison:
NULL, or a non-number produces an error event rather than a value — so an empty aggregate can’t quietly read as 0 and breach an lte threshold.
Threshold: when it breaches
operator is gte (breach at or above value) or lte (breach at or below). For a spans scope, metric says what is measured — it is required, since it decides what the value means. A metric that supports aggregations requires one too:
Actions: what fires on breach
Each action becomes its own run, exactly like a play’shealthAlertActions. An action is a connector action, an agent, or a tool, and its config is the input it runs with:
config is typed already — every agent takes the same { prompt, output? }, so a misspelled key is an editor error in the literal above with nothing to import.
A connector action or a tool has an input of its own, and a bare object literal leaves it unchecked. Wrap it in alertConnectorAction / alertToolAction to have TypeScript check config against the real thing:
{{ … }} template string — so a numeric input can be bound to {{event.value}}. Where the two differ is the source of the schema: a connector action’s comes from cargo-ai cdk types, so an integration you haven’t synced keeps the loose object, while a tool’s comes from its own defineWorkflow input and needs no sync — but a toolRef(uuid) names a tool you didn’t author here, so that one stays loose. Both are helpers rather than the type of actions because TypeScript can’t infer a per-element type through an array literal, the same reason agentConnectorTrigger is one.
config is interpolated against the firing under two roots — alert is what you configured, event is what this firing measured — so an action can say what happened:
The evaluation window
An alert does not re-scan a fixed lookback on every tick. Each evaluation covers the time since the previous one, so windows are contiguous and never overlap and every span is judged exactly once:- Window start — where the last evaluation ended. The very first evaluation starts from the moment the alert was last saved.
- Window end — slightly behind now, by an allowance for span indexing lag. Spans that land late are picked up by the next tick instead of being missed.
@every 5m means each evaluation judges roughly the last five minutes.
Actions fire at most once per window. Before firing, an alert atomically
claims its window; if a retry or an overlapping tick already claimed it,
nothing is recorded and nothing fires. Actions spawn runs that spend credits
and can take real action, so a duplicate is worse than a rare miss — and a
sustained breach is detected again on the next tick anyway.
From the CLI
create also takes --actions (a JSON array), --description and --folder.
On update, passing none to --description or --folder clears the field,
while omitting the flag leaves it untouched.
Unlike
defineAlert, an alert created through the API or the CLI starts
disabled — arm it with alert update --uuid <uuid> --enabled true once
its scope and threshold look right.preview computes the value
now and reports whether it would breach, without firing anything:
--window-minutes (default 60) is the lookback for spans scopes; a SQL scope
windows itself, so the flag doesn’t affect it.
Using the UI
See Using the UI to build an alert visually, with a live preview of the spans it matches, and Events for reading an alert’s history. An alert built in the UI can be brought back into code:cargo-ai cdk pull writes it as a defineAlert under alerts/, with its scope, threshold and actions referencing the other resources it was pulled alongside.
