> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Alerts

> Документация AgentEye Alerts.

Alerts оценивают правило по расписанию и уведомляют вас, когда что-либо пересекает пороговое значение. Они превращают AgentEye из пассивной панели мониторинга в систему оповещений для важных событий: всплески процента ошибок, регрессия задержки, падение оценок от оценивателя или любое пользовательское событие, которое можно выразить как запрос ClickHouse.

В этом руководстве рассмотрены: что такое alert, пять типов триггеров, четыре канала уведомлений, жизненный цикл инцидента и операционные параметры.

<img src="https://mintcdn.com/exosphere/RgxYS1UZshqb4m7m/agenteye/images/alerts.png?fit=max&auto=format&n=RgxYS1UZshqb4m7m&q=85&s=52dc18ed19b4e78604c20b5608994840" alt="Страница Alerts: сетка карточек alert-правил, каждая показывает тип триггера, окно оценки, каналы и значок серьезности (info/warning/critical)" width="2880" height="1800" data-path="agenteye/images/alerts.png" />

***

## Основные понятия

* **Alert** — правило. Оно указывает *что* проверять (триггер), *как часто* (интервал оценки), *когда считать неисправным* (составная логика), *насколько срочно* (серьезность) и *кого/куда уведомлять* (каналы).
* **Incident** — что происходит, когда alert срабатывает. Один alert имеет максимум один открытый инцидент одновременно. Повторные нарушения обновляют доказательства того же инцидента. Инциденты разрешаются оператором; автоматическое разрешение при прекращении действия правила планируется, но не включено в настоящее время.
* **Channel** — место отправки уведомления: email, Slack, generic webhook или внутри панели. Каждый alert может использовать любую комбинацию.

Alerts и инциденты принадлежат организации и совместно используются операторами этой организации (в развертывании с одним клиентом это просто встроенная организация `default`). Инциденты можно назначить отдельному оператору для сортировки.

***

## Типы триггеров

Пять видов, каждый с собственной JSON-спецификацией. Выберите тот, который соответствует тому, как вы хотите описать "неисправность". Форма **new alert** на панели мониторинга создает ту же спецификацию для вас, переключая редактор условий в соответствии с выбранным типом триггера:

<img src="https://mintcdn.com/exosphere/RgxYS1UZshqb4m7m/agenteye/images/alert-new.png?fit=max&auto=format&n=RgxYS1UZshqb4m7m&q=85&s=ee2fb0c2b98bbdc3602bb568751c5cc4" alt="Форма new-alert с основами (имя, описание, включено) и средство выбора триггера, показывающее metric threshold, custom SQL, evaluation score, eval failures и per-event опции" width="2880" height="1800" data-path="agenteye/images/alert-new.png" />

### 1. `metric_threshold`

Самый простой. Выберите метрику из закрытого списка, оператор, пороговое значение и временное окно.

| Метрика          | Что она считает                                                     |
| ---------------- | ------------------------------------------------------------------- |
| `event_count`    | Всего событий в окне                                                |
| `error_count`    | `event_type = 'error'` ИЛИ любое событие с `error_type IS NOT NULL` |
| `error_rate`     | `error_count / event_count` (0..1)                                  |
| `p95_latency_ms` | `quantile(0.95)(duration_ms)` для всех событий с `duration_ms`      |
| `p99_latency_ms` | `quantile(0.99)(duration_ms)`                                       |
| `token_sum`      | `SUM(input_tokens + output_tokens)`                                 |

Операторы: `>`, `>=`, `<`, `<=`, `==` (также принимаются как `gt`, `gte`, `lt`, `lte`, `eq`).

Необязательные фильтры: `environment`, `event_type`.

Пример спецификации:

```json theme={null}
{
  "metric": "p95_latency_ms",
  "filter": { "environment": "production" },
  "window_secs": 900,
  "op": ">",
  "value": 5000
}
```

### 2. `custom_sql`

Для всего, что не охватывают предустановленные метрики. SQL, предоставленный оператором, проходит через ту же защиту `/queries/run` (SELECT/WITH только, одно выражение, лимит 10 000 строк) перед запуском диспетчером. Два режима:

* **rows mode** (без `op`/`value`): alert срабатывает, как только запрос вернет как минимум одну строку.
* **value mode**: запрос должен давать одному столбцу псевдоним `metric_value`; диспетчер сравнивает `metric_value` первой строки с `value`, используя `op`.

```json theme={null}
{
  "sql": "SELECT count() AS metric_value FROM agenteye.events WHERE event_type = 'error' AND ts >= now() - INTERVAL 1 HOUR",
  "op": ">",
  "value": 100
}
```

### 3. `evaluation_score`

Читает `agenteye.evaluations` и сравнивает среднее значение именованной оценки в пределах окна.

```json theme={null}
{
  "score_key": "hallucination",
  "op": ">",
  "value": 0.6,
  "window_secs": 3600,
  "min_count": 5,
  "environment": "production"
}
```

`min_count` защищает от выбросов с одной выборкой; диспетчер не срабатывает, пока в окне не будет как минимум N оценок.

### 4. `eval_compound`

Перехватите регрессию качества, которая проявляется только во *многих* оценках оценивателя одновременно. Где `evaluation_score` отслеживает одну именованную оценку, `eval_compound` составляет несколько условий evaluation-score в один alert и объединяет их результаты с выбранной логикой; так что одно правило может выражать "срабатывай, если helpful падает **или** hallucination растет", "срабатывай только если helpful **и** tool-efficiency оба падают", или "срабатывай, если **как минимум 2 из** этих трех проверок нарушаются".

Каждое условие читает среднее значение одной именованной оценки из `agenteye.evaluations` в пределах общего окна и тестирует его с собственным оператором и пороговым значением. Логические результаты затем объединяются с помощью `combinator`:

| Combinator          | Логика | Срабатывает, когда                |
| ------------------- | ------ | --------------------------------- |
| `"any"`             | ИЛИ    | как минимум одно условие нарушено |
| `"all"`             | И      | все условия нарушены              |
| `{ "at_least": N }` | M из N | как минимум N условий нарушены    |

```json theme={null}
{
  "combinator": { "at_least": 2 },
  "conditions": [
    { "score_key": "hallucination", "op": ">", "value": 0.8 },
    { "score_key": "helpfulness",   "op": "<", "value": 0.6 },
    { "score_key": "tone",          "op": "<", "value": 0.5 }
  ],
  "window_secs": 3600,
  "min_count": 5,
  "environment": "production"
}
```

* `combinator`: `"any"`, `"all"`, или `{ "at_least": N }`.
* `conditions[]`: каждый `{ score_key, op, value }`, используя те же операторы, что и другие триггеры (`>`, `>=`, `<`, `<=`, `==`).
* `window_secs`: общий lookback, применяемый к каждому условию (по умолчанию `3600`).
* `min_count`: минимальное количество оценок на условие перед тем, как это условие может быть нарушено; условие с слишком малым количеством выборок в окне считается нарушенным (по умолчанию `1`).
* `environment`: необязательно; ограничивает каждое условие одной средой.

Доказательство уведомления записывает наблюдаемое среднее каждого условия, пороговое значение, для которого оно было протестировано, количество видимых оценок и был ли нарушен порог; так вы можете точно увидеть, какие проверки сработали.

### 5. `per_event`

Для alerts типа "любое событие, соответствующее X, попало". Без агрегации; диспетчер срабатывает, как только видит совпадение в окне lookback.

```json theme={null}
{
  "event_type": "error",
  "lookback_secs": 60,
  "environment": "production",
  "tool_name": "bash",
  "agent_id": "caa",
  "error_type": "TimeoutError",
  "message_contains": "vertex-ai timed out"
}
```

Все фильтры объединяются с И; любое поле, которое вы не указываете, не ограничено.

| Поле               | Назначение                                                                                                                                                                                                                                                                                 |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `agent_id`         | Ограничить ошибками от конкретного агента (тот, что показан на строке `/errors`).                                                                                                                                                                                                          |
| `error_type`       | Ограничить определенным классом ошибок (например, `TimeoutError`) вместо каждой ошибки.                                                                                                                                                                                                    |
| `message_contains` | Совпадение подстроки без учета регистра против `payload.message`. Полезно для перехвата одного конкретного режима отказа (например, `prompt is too long`) без оповещения об каждой ошибке от одного агента. Ограничено 200 символами; сопоставляется как буквальная строка, не как шаблон. |

Совет: установите `lookback_secs` примерно соответствующим `eval_interval_secs` alert, чтобы не получить двойное уведомление об одном и том же событии.

**Ярлык из `/errors`:** каждая строка представителя группы ошибок на представлении ошибок (и панель деталей события сеанса для события ошибки) имеет кнопку **+ alert**, которая открывает `/alerts/new` с предварительно заполненным триггером `per_event`, ключевым для `event_type` и среды этой строки, включая имя, полученное из `error_type` payload, когда присутствует. Вы все еще выбираете каналы и подтверждаете lookback, но средство сопоставления заполнено за вас. Операторы нуждаются в `alerts:write` для появления кнопки.

***

## Составная логика (M из N)

Каждый alert имеет два целочисленных параметра в дополнение к триггеру:

* `eval_window`: количество последних оценок, на которые смотреть (по умолчанию 1)
* `min_breaches`: сколько из них должны быть нарушены перед срабатыванием alert (по умолчанию 1)

`1 of 1` (по умолчанию) — это срабатывание при первом нарушении. `3 of 5` означает срабатывание, когда правило нарушено в 3 из последних 5 оценок, полезно для нестабильных сигналов, где одно плохое измерение является шумом. Диспетчер поддерживает кольцевой буфер для каждого alert; вам не нужно управлять состоянием.

***

## Интервал оценки

`eval_interval_secs` контролирует, как часто диспетчер запускает ваше правило. Ограничено `[30, 86400]`. Предустановки на панели мониторинга: 1m / 5m / 15m / 1h. Выберите интервал, соответствующий скорости изменения основного сигнала: alert об ошибке за 5 минут, оцениваемый каждые 15 секунд, тратит ЦП впустую; alert per-event нуждается в коротком lookback или он будет молча пропускать события между тиками.

***

## Каналы

Каждый alert может использовать любую комбинацию из этих четырех. Учетные данные по каналам (URL Slack webhook, generic webhook URL + signing secret, получатели email по умолчанию) настраиваются один раз в **`/settings`** и ссылаются по ключу из каждого alert. Таким образом, один канал Slack может служить множеству alerts без сохранения собственной копии URL webhook.

Три внешних типа каналов (email, Slack, webhook) также контролируются общим для организации переключателем отключения, `alerts.enabled_channels`. Когда срабатывающий alert присоединяет тип канала, который не входит в этот набор, диспетчер пропускает его и записывает строку `alert_notifications` со статусом `skipped_disabled` и целевым `<channel_disabled>` (позволяя вам глобально приостановить, например, всю доставку Slack без редактирования каждого правила). Канал внутри панели всегда разрешен. Смотрите [Конфигурация](#configuration).

### Email

Повторно использует тот же SMTP-транспорт, который доставляет email-ы входа OTP. Получатели разрешаются в порядке:

1. Переопределение `recipients[]` для каждого канала (когда не пусто).
2. Параметр `alerts.email_default_recipients` (массив строк email).

Если SMTP не настроен, канал — это no-op; диспетчер все еще записывает строку `alert_notifications` с целевым `<smtp_unconfigured>`, так что журнал аудита делает неправильную конфигурацию видимой.

### Slack

Отправляет Block Kit-сообщение на [incoming webhook URL](https://api.slack.com/messaging/webhooks).

* URL по умолчанию: `alerts.slack_default_webhook` (установлено в `/settings`).
* Переопределение для каждого alert: установите `webhook_setting_key` канала на любой другой ключ параметра типа URL, например, `alerts.slack_oncall`, `alerts.slack_costs`.

Заголовок включает emoji серьезности (`:rotating_light:` / `:warning:` / `:bell:`), и сообщение содержит кнопку, которая глубоко ссылается на страницу инцидента.

### Generic webhook

Интеграция JSON-POST для PagerDuty, Opsgenie или вашей собственной конечной точки приема. Форма тела:

```json theme={null}
{
  "schema_version": 1,
  "event": "alert.firing",
  "incident": { "id": "uuid", "url": "https://…/incidents/uuid", "opened_at": "2026-…" },
  "alert":    { "id": "uuid", "name": "errors > 50/hr", "severity": "critical" },
  "breach":   { "value": 73.0, "summary": "ErrorCount > 50 (observed 73.000)", "evidence": { … } }
}
```

Когда установлен `alerts.webhook_signing_secret`, запрос включает заголовок `X-AgentEye-Signature: sha256=<hex>`, HMAC-SHA256 тела с использованием секрета. Проверьте его на стороне получателя перед доверием payload.

Заголовок `X-AgentEye-Event` содержит `alert.firing` / `alert.test`. (`alert.resolved` зарезервирован для планируемой функции авторазрешения и в настоящее время не передается.)

### Внутри панели

Без внешней доставки: alert просто записывает строку `alert_notifications`, которую страница инцидентов панели отображает. Полезно при настройке правила и вы не хотите спамить внешнюю систему, или для неспешных alerts, которые операторы проверяют при обычной сортировке.

***

## Жизненный цикл инцидента

```
firing  ──ack──▶  acknowledged
   │                    │
   └────────────────────┴───── operator resolve ───▶  resolved
```

* **firing** — диспетчер только что открыл инцидент или обнаружил другое нарушение. Уведомление о срабатывании разветвляется ровно один раз (контролируется временной меткой `notified_firing_at` инцидента).
* **acknowledged** — оператор нажал *ack* на `/incidents/:id`. Инцидент по-прежнему считается открытым; последующие нарушения обновят его доказательства без повторного уведомления.
* **resolved** — оператор нажал *resolve*. Автоматическое разрешение при прекращении нарушения правила планируется, но в настоящее время не включено, поэтому открытый инцидент остается открытым, пока оператор его не разрешит.

Новый инцидент может снова открыться на одном и том же alert в любой момент после разрешения предыдущего.

**Временная шкала активности.** Каждое действие на инцидент — открыт, подтвержден, разрешен — записывается в журнал активности только для добавления и показывается на временной шкале *activity* инцидента, каждая запись приписывается оператору, который выполнил это действие (по email) или к **automated** для действий, которые диспетчер выполнил самостоятельно (автоматическое открытие при нарушении). Подтверждение является общим: несколько операторов могут подтвердить один инцидент, и каждое появляется как отдельная, приписываемая запись.

Входящий список **Incidents** группирует открытые инциденты по состоянию и позволяет фильтровать по серьезности и назначенному лицу:

<img src="https://mintcdn.com/exosphere/RgxYS1UZshqb4m7m/agenteye/images/incidents.png?fit=max&auto=format&n=RgxYS1UZshqb4m7m&q=85&s=2ec7841f0329c15974b52a761b6dcdcc" alt="Входящий список Incidents, показывающий alert-связанные и ad-hoc карточки инцидентов со значками серьезности и назначенными лицами" width="2880" height="1800" data-path="agenteye/images/incidents.png" />

Открытие инцидента показывает доказательство нарушения, назначенные лица и подписчики, приписываемую временную шкалу активности и ветку комментариев:

<img src="https://mintcdn.com/exosphere/RgxYS1UZshqb4m7m/agenteye/images/incident-detail.png?fit=max&auto=format&n=RgxYS1UZshqb4m7m&q=85&s=d49c0814049fa568eca794743ceea7e3" alt="Представление детали инцидента: родительский alert, резюме нарушения, назначенные лица, подписчики, журнал приписываемой активности и разговор" width="2880" height="1800" data-path="agenteye/images/incident-detail.png" />

***

## Требуемые разрешения

Создание alert-*правил* и сортировка *инцидентов* — это отдельные проблемы с отдельными разрешениями, поэтому вы можете дать доступ к инцидентам дежурной ротации без передачи ей возможности переписывать правила.

* `alerts:read`: просмотр alert-правил.
* `alerts:write`: создание, редактирование, удаление alert-правил и активирование тестового уведомления.
* `incidents:read`: просмотр инцидентов.
* `incidents:write`: открытие ручных (ad-hoc) инцидентов, не связанных с alert.
* `incidents:ack`: подтверждение, назначение, комментирование и разрешение инцидентов.

> **Устаревший `alerts:ack`.** Ключи и операторы, которым было предоставлено более старое разрешение `alerts:ack`, продолжают работать: оно принимается как `incidents:ack` (и подразумевает `incidents:read`), поэтому существующие дежурные операторы сохраняют свой доступ без переизданий учетных данных. Выпускайте новые разрешения с семейством `incidents:*`.

Предоставьте на API-ключи (`POST /keys`) и операторов (`PUT /users/:id`). `PermGate` панели блокирует соответствующие кнопки при отсутствии разрешения; вы увидите `// 403` рядом с действием.

> **Средство выбора получателя Email.** Средство выбора получателей редактора alert отображает членов вашей организации, так что вы можете выбрать их по имени. Он загружается для любого оператора, имеющего `alerts:read` или `alerts:write`; просмотр каталога вашей команды для этой цели **не** требует `users:read`, и средство выбора возвращает только адреса email членов, никогда полные записи пользователей.

***

## Конфигурация

Переменные окружения, используемые диспетчером:

| Переменная                 | По умолчанию                 | Назначение                                                                                                    |
| -------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `ALERT_WORKERS`            | `1`                          | Рабочие задачи на экземпляр сервера. Большинство развертываний нуждаются только в одной.                      |
| `ALERT_CLAIM_BATCH`        | `16`                         | Макс alert-ы, которые один рабочий тик обрабатывает.                                                          |
| `ALERT_POLL_IDLE_SECS`     | `5`                          | Сон рабочего при пустой очереди.                                                                              |
| `ALERT_REQUEST_TIMEOUT_MS` | `15000`                      | Тайм-аут оценки на триггер.                                                                                   |
| `DASHBOARD_URL`            | `https://app.befailproof.ai` | Источник, используемый для построения magic-link инцидента в уведомлениях. Установите на вашего хоста панели. |

После временного сбоя оценки (ClickHouse недоступен, тайм-аут запроса), диспетчер повторяет правило с экспоненциальной задержкой. Как только правило накопит **5** последовательных временных сбоев, оно переплан ируется на нормальный ритм вместо продолжения задержки, так что постоянно неправильное правило все еще продолжает переоцениваться. Этот потолок фиксирован и не настраивается оператором.

Параметры канала (управляются из `/settings`, не env):

* `alerts.email_default_recipients` (`email_list`): JSON-массив строк email — получатели по умолчанию для email-каналов.
* `alerts.slack_default_webhook` (`url`): URL Slack incoming-webhook по умолчанию.
* `alerts.webhook_default_url` (`url`): URL generic-webhook по умолчанию.
* `alerts.webhook_signing_secret` (`secret`): ключ HMAC-SHA256. Всегда возвращается как `""` в ответе GET; введите новое значение для ротации.
* `alerts.enabled_channels` (`channel_set`): набор внешних типов каналов для организации, которые отправляются при срабатывании alert; по умолчанию все три (`email`, `slack`, `webhook`). Удаление типа здесь глобально подавляет этот канал для каждого alert без редактирования каждого правила. Канал внутри панели всегда доставляется и не затрагивается этим параметром.

***

## Проверка нового alert

Перед использованием нового alert:

1. Сохраните его как включенный с как минимум одним каналом уведомления.
2. Выберите **test** на странице деталей alert и подтвердите, что каждое настроенное место назначения получает синтетическое уведомление.
3. После первого реального нарушения подтвердите, что инцидент появляется под **Incidents** и его измеренное значение соответствует соответствующему запросу панели.

Инциденты не разрешаются автоматически при очистке условия. Оператор должен разрешить их со страницы детали инцидента.

***

## Устранение неполадок

| Симптом                           | Вероятная причина                                                                                                                                                                                                                                                                                                               |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Alert никогда не срабатывает      | `enabled = false`, или нет прикрепленных каналов, или основной запрос CH возвращает 0 строк. Используйте *test* для подтверждения каналов; используйте `/queries/run` для подтверждения метрики.                                                                                                                                |
| Уведомление Slack отсутствует     | `alerts.slack_default_webhook` (или ключ переопределения для каждого alert) не установлен: проверьте `alert_notifications.target` на строках `<unset:…>`; или тип `slack` глобально отключен в `alerts.enabled_channels`: проверьте строки `alert_notifications` со статусом `skipped_disabled` и целевым `<channel_disabled>`. |
| Generic webhook 401               | Получатель требует подписи, но `alerts.webhook_signing_secret` не установлен. Проверьте на получателе, что HMAC соответствует `hmac_sha256(secret, body)`.                                                                                                                                                                      |
| Email "from all sends failed"     | SMTP-учетные данные неправильны или адрес `from` отклоняется вашим реле. Та же поверхность, которая доставляет email-ы OTP: если те работают, SMTP-транспорт в порядке.                                                                                                                                                         |
| Инцидент переоткрывается повторно | Составные параметры слишком агрессивны: попробуйте увеличить `min_breaches` или `eval_window`, чтобы временные всплески не переоткрывали разрешенные инциденты.                                                                                                                                                                 |
