# Notifications and alerts

> Field-level reference for the Integration record, its per-type delivery configuration, and the event-type taxonomy that routes surface, drift, and usage alerts to integrations.

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 →](/products/affinidi-trust-fabric/agent-stream/reference/surfaces/cost-and-usage-limits.md).

## 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. |
| email | 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](/products/affinidi-trust-fabric/agent-stream/reference/observability/telemetry-and-exports.md#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 →](/products/affinidi-trust-fabric/agent-stream/reference/surfaces/surface-reference.md)): 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.detected to exactly those ids when set. Absent or empty, it falls back to the surface’s own drift.detected 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 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 →](/products/affinidi-trust-fabric/agent-stream/reference/observability/llm-drift.md)). | 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 →](/products/affinidi-trust-fabric/agent-stream/reference/surfaces/cost-and-usage-limits.md)). | 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 →](/products/affinidi-trust-fabric/agent-stream/reference/governance/governance-records.md)). | 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](/products/affinidi-trust-fabric/agent-stream/reference/surfaces/cost-and-usage-limits.md#usage-alerts); this page covers only how a tripped alert reaches an integration, via the routing described above.

## Related

- [Cost and usage limits](/products/affinidi-trust-fabric/agent-stream/reference/surfaces/cost-and-usage-limits.md): Usage alert fields, alert-type thresholds, and the legacy monthly-budget block.

- [Alert on budget breaches and cost spikes](/products/affinidi-trust-fabric/agent-stream/how-to-guides/cost-and-usage/alert-on-budget-breaches-and-cost-spikes.md): Create an integration and attach a usage alert so a breach or spike actually reaches someone.

- [Governance records](/products/affinidi-trust-fabric/agent-stream/reference/governance/governance-records.md): The governance.record export event and its integration sinks.

- [LLM drift](/products/affinidi-trust-fabric/agent-stream/reference/observability/llm-drift.md): The drift.detected alert, its cadence, and the Drift Harness’s integration override.

- [Telemetry and exports](/products/affinidi-trust-fabric/agent-stream/reference/observability/telemetry-and-exports.md): The Langfuse and webhook integration types also used for tracing exports, not just alerts.
