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 export Agent Stream can raise 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 centralizing events through Kafka, Kinesis, Pulsar, or Redis? Stream puts alerts in that same pipeline as everything else.
- Langfuse covers tracing/observability export, not alerting, so pair it with one of the above if you also want alert delivery.
| Field | Description |
|---|---|
| Integration Name | Display name. Labeled “Integration Name” on the create/edit form; the integrations list table’s column header is the shorter “Name”. |
| Description | Free-text description. |
| Integration Type | Delivery type, picked from a dropdown: webhook, slack, email, stream, or langfuse. Labeled “Integration Type” on the create/edit form; the list table’s column header is “Type”. See above for which one to pick. |
| Category | Determines which runtime variables are available. The dashboard’s own category dropdown offers general, connection_point, user, gateway, x402, llm_governance, and llm_drift. |
| Connection settings | Connection/authentication configuration, a group of fields whose shape depends on the integration type (see the table below). Each type’s form presents these fields under its own heading rather than a single “Configuration” field; Langfuse is the exception, using a generic “Configuration (JSON)” textarea instead of a typed form. Stored as the record’s configuration field. |
| Message content | Message content template (subject, body, text, …) with ${VARIABLE} placeholders substituted from the event’s runtime variables at dispatch time. Its dashboard label varies by integration type rather than appearing under one shared field. Stored as the record’s content field. |
| Enabled | A toggle: active or otherwise, and a non-active integration is skipped at dispatch. The edit form labels it “Enabled”, not “Status”; the integrations list table’s column header is “Status”. |
| Created | Creation timestamp. Integrations list table column header. |
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. Configuration fields required per type:
| Type | Required fields |
|---|---|
| webhook | Destination URL, validated against SSRF before every dispatch. |
| slack | Webhook URL: the Slack incoming-webhook URL. |
| Host, Port, Username, Password, From Address, Recipient Email(s) (array); optional Use TLS, Use STARTTLS. | |
| stream | Platform (Kafka, Kinesis, Pulsar, or Redis), Topic. |
| langfuse | No dedicated form: host (default https://cloud.langfuse.com), public_key, and secret_key are entered as raw JSON keys in the generic “Configuration (JSON)” textarea (see Telemetry and exports → Langfuse). |
Sensitive fields inside configuration (SMTP passwords, stream credentials) are encrypted at rest alongside the rest of the integration record, the same as a surface’s integration mappings.
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. Two features can bypass the surface’s own mapping with an explicit override:
- LLM Drift: a Drift Harness’s alert integrations (a list of integration ids) fires
drift.detectedto exactly those ids when set. Absent or empty, it falls back to the surface’s owndrift.detectedmappings. - 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 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 executes successfully. | SURFACE_PROVIDER, SURFACE_MODEL, INPUT_TOKENS, OUTPUT_TOKENS, TOTAL_TOKENS, COST_USD, LATENCY_MS, TRACE_ID, and (when log_requests/log_responses are enabled) REQUEST_CONTENT/RESPONSE_CONTENT. |
pipe.error | A surface execution fails. | ERROR_MESSAGE |
drift.detected | A surface’s behaviour crosses into drift on any dimension (see LLM drift →). | DRIFT_DIMENSION, DRIFT_BASELINE, DRIFT_CURRENT, DRIFT_DELTA |
pipe.budget.threshold_reached | The legacy monthly-budget alert crosses alert_threshold_percent (see Cost and usage limits →). | Budget month, spend, limit, percentage |
pipe.budget.exceeded | The legacy monthly budget is exceeded. | Same as above |
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/label |
governance.record | A governance record is exported to an integration sink (see Governance records →). | RECORD_ID, CONTENT_HASH, PREV_RECORD_HASH |
Breach and usage-alert delivery
pipe.usage_alert and pipe.cost_spike are raised by an in-memory, per-surface rolling window (300-second window, capped at 200 samples) evaluated on the response path but dispatched off it. 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, alert-type thresholds, and the legacy monthly-budget block.
- 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.detectedalert, its cadence, and the Drift Harness’s integration override. - Telemetry and exports: The Langfuse and webhook integration types also used for tracing exports, not just alerts.
Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.