Skip to main content
Three things in AgentX notify, and it helps to know which one you are reaching for:
  • A scorer’s alert threshold fires per verdict - one trace the judge rated badly.
  • An automation rule routes per trace - one matching trace into review, a dataset, or a webhook.
  • An alert rule watches an aggregate over a sliding window - failure rate, p95 latency, spend, judge failures, traffic volume - and pages an on-call channel when it crosses a threshold. This is the page an ops team used to build by hand from raw webhook payloads.
Alert rules live under Manage → Rules, below the automation rules.

What you can alert on

A rate with nothing in its window is “no data”, never a breach: an empty deployment does not page you for a 0% failure rate, and “no traffic at all” is what a traceCount floor is for. Windows run from 1 minute to 7 days (the editor offers 5m, 15m, 1h, 6h, 24h); a rule can watch every agent in the project or one agent. Evaluation-run traffic is excluded from every metric, and on the ClickHouse tier the trace-derived metrics read spans from ClickHouse directly.

Lifecycle

Rules are evaluated once a minute by a background sweep (one evaluator per tick across replicas that share a database). The lifecycle is the one pagers expect:
  1. Triggered - the first evaluation that breaches sends one notification and sets the rule to firing.
  2. Repeat - while it keeps breaching, a reminder goes out every cooldownMinutes (default 60), never more often.
  3. Resolved - the first evaluation back inside the threshold sends a resolve notification (PagerDuty closes the incident it opened, with the same dedup key) and the rule returns to ok.
Every notification carries an incidentKey that is stable for one firing episode (the trigger, its repeats, and its resolve) and fresh for the next, so a new incident is never deduplicated into an old one. Editing a rule’s metric, operator, threshold, window, or agent resets it to ok, and so does pausing it (enabled: false) - a re-thresholded rule never sits “firing” on a value it would no longer breach, and a rule re-enabled mid-incident pages a fresh “triggered”. If the rule was firing at that moment, its channels get a final resolved notification first (PagerDuty closes the incident), and deleting a firing rule does the same before it goes. Each rule keeps its last 200 notifications as history, with every channel’s delivery result, so “did the page actually go out?” has an answer.

Channels

A rule pages up to 5 channels. Each channel is a { kind, target } pair: Channel targets are validated when the rule is saved: a URL must pass the engine’s egress guard (http(s) only, cloud metadata endpoints refused, private targets refused on multi-tenant deployments), an email must be an address, a PagerDuty key must look like one. A channel that could never deliver is refused with a 400 instead of failing silently on the first real incident. The threshold is checked against the metric the same way: a count (judgeFailures, traceCount) must be a whole number and a rate must be between 0 and 1. PagerDuty keys are stored once and shown masked on every read; saving the rule with the mask in place keeps the stored key. The generic webhook body:
kind is triggered, repeat, resolved, or test; status is FIRING, RESOLVED, or TEST. agentName is the scoped agent’s display name (null for an all-agents rule), and incidentKey is the firing episode’s identity described under Lifecycle. A delivery that a channel refuses is recorded as HTTP <status> in the rule’s history - never the receiver’s response body.

In the dashboard

The editor shows the metric’s current value for the draft’s window and agent as you build the rule - the same computation the sweep will run - so a threshold is set against real numbers. Each rule row shows its state (ok, firing, or paused), the live value, and honest activity (“never fired”, or the incident count and when it last fired). Send test delivers a test notification to every channel with the live value and reports each channel’s result, so a mistyped hook shows up now rather than during an incident; History opens the per-channel delivery log.

From the SDK

create and update refuse an unknown metric, operator, or channel kind locally, and a channel the engine cannot deliver to comes back as a 400 with the reason. Deleting a rule drops its history; if it was firing, its channels get a final resolved notification first, so the PagerDuty incident it opened is closed with it.

REST

All routes live under /api/v1/agent-monitoring/alert-rules and take the project API key: AGENTX_ALERT_SWEEP=false disables the background evaluator entirely; the manual route still works. Alert rules and their history ride along in backups as the alert-rules and alert-events entities, with hook URLs and PagerDuty keys redacted. The runnable walkthrough is sample-scripts/monitor_ops/08_alert_rules_and_streaming.py: it stands up a local Slack stand-in, drives a failure-rate rule through triggered → held → resolved with real traffic, and sends a test page.