Notifications and alerts
Every alert Agent Stream raises (a budget breach, a drift detection, a signed governance record, a surface lifecycle event) is delivered the same way: as a named event dispatched to one or more configured integrations. This page documents that delivery mechanism. For the alert-trigger side (thresholds, conditions), see Cost and usage limits →.
Integration record
An integration is a stored, reusable delivery target: created once, then referenced from a surface’s own integration mappings, a Drift Harness’s alert integrations, or a usage alert’s notification channels. Every alert, and every governance-record export to an integration, goes through one of these, so you configure a destination once and point as many features at it as you need instead of re-entering delivery details each time.
- Slack suits team-visible alerts someone needs to notice quickly, in a channel they already watch.
- Choose Email when the recipient isn’t on your Slack/chat workspace, or you want a durable, searchable record of each alert.
- Webhook is the right choice for forwarding events into your own system (a ticketing tool, an internal alerting pipeline, a SIEM) rather than to a person.
- Already centralising events through Kafka, Kinesis, Pulsar, or Redis? Stream puts alerts in that same pipeline as everything else.
| Field | Description |
|---|---|
| Integration Name | Display name. Shown in the Name column of the integrations list. |
| Description | Free-text description. |
| Integration Type | Delivery type, picked from a dropdown: Email, Slack, Webhook, or Stream. Shown in the Type column of the integrations list. See above for which one to pick. |
| Category | Picked from a dropdown, and shown in the Category column of the integrations list. The category decides which features can pick the integration: a Drift Harness lists only LLM Drift integrations, and a surface’s Governance recording section lists only LLM Governance integrations. |
| Connection settings | Connection/authentication configuration, a group of fields whose shape depends on the integration type (see the table below). |
| Message content | Message content template (subject, body, text, …) with ${VARIABLE} placeholders substituted from the event’s runtime variables at dispatch time. Its label depends on the integration type. |
| Enabled | A toggle on the edit form. A disabled integration is skipped at dispatch. Shown in the Status column of the integrations list. |
| Created | Creation timestamp. Shown in the Created column of the integrations list. |
Every credential below comes from wherever that service issues its own credentials, not from Agent Stream: SMTP host/username/password come from your mail provider’s own account or admin settings; a Slack webhook URL comes from Slack’s own app/incoming-webhook settings for the target channel; stream platform credentials come from that platform’s own connection settings. Fields per type:
| Type | Fields |
|---|---|
| Webhook | Webhook URL, which must be a public address (private, link-local, and localhost addresses are rejected), and Payload Template. HTTP Method is POST by default, or PUT or PATCH. Optional: Signing Secret and Custom Headers. |
| Slack | Webhook URL: the Slack incoming-webhook URL, and Message Text. |
| SMTP Host, Port, Username, Password, From Address, Recipient Email(s), Subject, and Body. Optional: Use TLS and Use STARTTLS. | |
| Stream | Streaming Platform (Apache Kafka, AWS Kinesis, Apache Pulsar, or Redis Streams), Topic/Stream Name, and Event Payload Template, plus the platform’s connection fields: Broker URLs for Kafka and Pulsar, AWS Region for Kinesis, or Redis URL for Redis Streams. |
Sensitive connection settings (SMTP passwords, stream credentials) are encrypted at rest.
Per-surface and per-feature routing
A surface names which integrations fire for which events through its own integration mappings (documented in Core configuration →): which integration, which events it should fire on, and template variables. A mapping’s Trigger Events checklist offers the surface events (pipe.* and both drift events). A mapping with no event ticked receives every event the surface raises, including those not in the checklist. Two features can bypass the surface’s own mapping with an explicit override:
- LLM Drift: a Drift Harness’s Alert integrations send
drift.detectedanddrift.resolvedto exactly those integrations when any are chosen. With none chosen, both events go through the surface’s own mappings. - Usage alerts: each usage alert’s notification channels (integration ids) fires in addition to any surface mapping that already matches the alert’s event type, so a channel doesn’t have to also be listed in the surface’s own mapping to receive it.
Event-type taxonomy
Every event carries a stable EVENT_TYPE runtime variable plus event-specific variables (SURFACE_ID, SURFACE_NAME, and others named below), substitutable into an integration’s message content template.
| Event type | Fires when | Key variables |
|---|---|---|
pipe.created | A surface is created. | SURFACE_ID, SURFACE_NAME |
pipe.updated | A surface’s configuration is saved. | SURFACE_ID, SURFACE_NAME |
pipe.deleted | A surface is deleted. | SURFACE_ID, SURFACE_NAME |
pipe.executed | A surface execution finishes. For a streamed response it fires when the stream ends, with SUCCESS set to false if the stream stopped before completion. | SURFACE_PROVIDER, SURFACE_MODEL, INPUT_TOKENS, OUTPUT_TOKENS, TOTAL_TOKENS, COST_USD, CURRENCY, LATENCY_MS, TRACE_ID, STREAMING, SUCCESS, and RECORD_ID (the governance record, when one was written). |
pipe.error | A surface execution fails, or the team gate or a surface usage limit refuses the request. | ERROR_MESSAGE |
drift.detected | A surface enters drift, then again on its alert cadence while it stays there (see LLM drift →). | DRIFT_STATUS, DRIFT_DIMENSION, DRIFT_BASELINE, DRIFT_CURRENT, DRIFT_DELTA |
drift.resolved | A surface’s overall status leaves drift for any other status. | DRIFT_STATUS (the new overall status) |
pipe.usage_alert | A usage alert of type cost_threshold, token_threshold, or error_rate trips. | ALERT_TYPE, THRESHOLD, OBSERVED, MESSAGE |
pipe.cost_spike | A usage alert of type cost_spike trips. | ALERT_TYPE, THRESHOLD, OBSERVED, BASELINE, MESSAGE |
member.auto_provisioned | A caller is auto-provisioned as a new member. | MEMBER_ID, MEMBER_LABEL |
governance.record | A governance record is exported to an integration sink (see Governance records →). | RECORD_ID, CONTENT_HASH, PREV_RECORD_HASH |
Both drift events also carry the full evaluation in NEW_STATE: the surface, its overall status, the 1-hour window, and every dimension with its status, baseline, current value, and change. drift.detected adds the worst-drifting dimension.
Breach and usage-alert delivery
pipe.usage_alert and pipe.cost_spike are evaluated per surface over a rolling 5-minute window of recent requests, buffered and streamed, including requests that fail. A cost-spike alert needs at least 5 samples in its baseline and an error-rate alert needs at least 5 samples in its window before either can fire, so a single early request can’t trip either alert against an empty history. The evaluated alert types (cost_threshold, token_threshold, error_rate, cost_spike) and their threshold fields are documented in Cost and usage limits → Usage alerts; this page covers only how a tripped alert reaches an integration, via the routing described above.
Related
- Cost and usage limits: Usage alert fields and alert-type thresholds.
- Alert on budget breaches and cost spikes: Create an integration and attach a usage alert so a breach or spike actually reaches someone.
- Governance records: The
governance.recordexport event and its integration sinks. - LLM drift: The
drift.detectedanddrift.resolvedalerts, their cadence, and the Drift Harness’s integration override. - Telemetry and exports: The webhook integration type, also used for exports, not just alerts.
Glad to hear it. Thanks for letting us know.
Sorry to hear that. Thanks for letting us know.