
Concetti
- Avviso — la regola. Dice cosa verificare (il trigger), con quale frequenza (l’intervallo di valutazione), quando considerarla rotta (logica composta), quanto è urgente (severità), e chi/dove notificare (canali).
- Incidente — quello che accade quando un avviso si attiva. Un avviso ha al massimo un incidente aperto per volta. Le violazioni ripetute aggiornano le evidenze dello stesso incidente. Gli incidenti vengono risolti da un operatore; la risoluzione automatica quando la regola smette di attivarsi è pianificata ma non attualmente abilitata.
- Canale — dove va una notifica: email, Slack, webhook generico, o in-dashboard. Ogni avviso può collegare qualsiasi combinazione.
default). Gli incidenti possono essere assegnati a un singolo operatore per il triage.
Tipi di trigger
Cinque tipi, ciascuno con la propria specifica JSON. Scegli quello che corrisponde a come vuoi descrivere “rotto”. La forma nuovo avviso della dashboard costruisce la stessa specifica per te, passando l’editor della condizione in modo che corrisponda al tipo di trigger che scegli:
1. metric_threshold
Il più semplice. Scegli una metrica da un elenco chiuso, un operatore, una soglia e una finestra temporale.
| Metrica | Cosa conta |
|---|---|
event_count | Eventi totali nella finestra |
error_count | event_type = 'error' O qualsiasi evento con error_type IS NOT NULL |
error_rate | error_count / event_count (0..1) |
p95_latency_ms | quantile(0.95)(duration_ms) su tutti gli eventi con duration_ms |
p99_latency_ms | quantile(0.99)(duration_ms) |
token_sum | SUM(input_tokens + output_tokens) |
>, >=, <, <=, == (accettati anche come gt, gte, lt, lte, eq).
Filtri opzionali: environment, event_type.
Esempio di specifica:
2. custom_sql
Per qualsiasi cosa le metriche preimpostate non coprano. L’SQL fornito dall’operatore passa attraverso la stessa protezione /queries/run (solo SELECT/WITH, singola istruzione, limite di 10.000 righe) prima che il dispatcher lo esegua. Due modalità:
- modalità righe (nessun
op/value): l’avviso si attiva non appena la query restituisce almeno una riga. - modalità valore: la query deve alias una colonna come
metric_value; il dispatcher confronta ilmetric_valuedella prima riga rispetto avalueusandoop.
3. evaluation_score
Legge agenteye.evaluations e confronta la media di un punteggio denominato su una finestra.
min_count protegge da outlier a singolo campione; il dispatcher non si attiva finché non esistono almeno N valutazioni nella finestra.
4. eval_compound
Cattura una regressione della qualità che si manifesta solo attraverso diversi punteggi degli evaluator contemporaneamente. Dove evaluation_score osserva un singolo punteggio denominato, eval_compound compone più condizioni di valutazione in un avviso e combina i loro risultati con una logica scelta; quindi una regola può esprimere “attivati se l’utilità scende o l’allucinazione sale”, “attivati solo se l’utilità e l’efficienza dello strumento scendono entrambe”, o “attivati se almeno 2 di questi tre controlli violano”.
Ogni condizione legge la media di un punteggio denominato da agenteye.evaluations nella finestra condivisa e lo verifica con il suo operatore e soglia. I risultati booleani vengono quindi combinati dal combinator:
| Combinator | Logica | Si attiva quando |
|---|---|---|
"any" | OR | almeno una condizione viola |
"all" | AND | ogni condizione viola |
{ "at_least": N } | M-of-N | almeno N condizioni violano |
combinator:"any","all", o{ "at_least": N }.conditions[]: ogni{ score_key, op, value }, usando gli stessi operatori degli altri trigger (>,>=,<,<=,==).window_secs: il lookback condiviso applicato a ogni condizione (predefinito3600).min_count: numero minimo per-condizione di valutazioni prima che quella condizione possa violare; una condizione con troppi pochi campioni nella finestra conta come “non violata” (predefinito1).environment: opzionale; limita ogni condizione a un ambiente.
5. per_event
Per avvisi “qualsiasi evento che corrisponde a X è arrivato”. Nessuna aggregazione; il dispatcher si attiva non appena vede una corrispondenza nella finestra di lookback.
| Campo | Scopo |
|---|---|
agent_id | Limita agli errori da un agente specifico (quello mostrato nella riga /errors). |
error_type | Limita a una classe di errore specifica (ad es. TimeoutError) piuttosto che ogni errore. |
message_contains | Corrispondenza di sottostringa case-insensitive rispetto a payload.message. Utile per catturare una modalità di errore specifica (ad es. prompt is too long) senza avvertire ogni errore dello stesso agente. Limitato a 200 caratteri; abbinato come stringa letterale, non come pattern. |
lookback_secs per corrispondere approssimativamente all’eval_interval_secs dell’avviso in modo da non notificare due volte lo stesso evento.
Scorciatoia da /errors: la riga rappresentativa di ogni gruppo di errori nella vista errori (e il pannello di dettaglio dell’evento della sessione per un evento di errore) ha un pulsante + alert che apre /alerts/new precompilato con un trigger per_event basato su event_type + ambiente di quella riga, incluso un nome generato da error_type del payload se presente. Scegli ancora i canali e conferma il lookback, ma il matcher è compilato per te. Gli operatori hanno bisogno di alerts:write affinché il pulsante compaia.
Logica composta (M of N)
Ogni avviso ha due manopole intere in aggiunta al trigger:eval_window: quante valutazioni recenti guardare (predefinito 1)min_breaches: quante di queste devono violare prima che l’avviso si attivi (predefinito 1)
1 of 1 (il valore predefinito) è “attivati sulla prima violazione”. 3 of 5 significa “attivati quando la regola ha violato 3 delle ultime 5 valutazioni”, utile per segnali tremolanti dove una singola misurazione negativa è rumore. Il dispatcher mantiene un ring buffer per avviso; non devi gestire lo stato.
Intervallo di valutazione
eval_interval_secs controlla con quale frequenza il dispatcher esegue la tua regola. Vincolato a [30, 86400]. Preimpostazioni nel dashboard: 1m / 5m / 15m / 1h. Scegli un intervallo corrispondente a quanto velocemente il segnale sottostante si muove: un avviso di tasso d’errore a 5 minuti valutato ogni 15 secondi spreca CPU; un avviso per evento ha bisogno di un lookback breve o silenziamente perderà gli eventi tra i tick.
Canali
Ogni avviso può collegare qualsiasi combinazione di questi quattro. Le credenziali per-canale (URL webhook Slack, URL webhook generico + segreto di firma, destinatari email predefiniti) sono configurate una sola volta in/settings e referenziate per chiave da ogni avviso. In questo modo un canale Slack può servire molti avvisi senza che ognuno memorizzi la propria copia dell’URL webhook.
I tre tipi di canale esterni (email, Slack, webhook) sono anche controllati da un interruttore di disattivazione a livello di organizzazione, alerts.enabled_channels. Quando un avviso attivato collega un tipo di canale che non è in questo set, il dispatcher lo salta e registra una riga alert_notifications con status skipped_disabled e target <channel_disabled> (permettendoti di sospendere globalmente, ad esempio, tutte le consegne Slack senza modificare ogni regola). Il canale in-dashboard è sempre consentito. Vedi Configuration.
- Override
recipients[]per-canale (quando non vuoto). - L’impostazione
alerts.email_default_recipients(un array di stringhe email).
alert_notifications con target <smtp_unconfigured> in modo che l’audit trail renda la misconfiguration visibile.
Slack
Invia un messaggio Block Kit a un URL webhook in arrivo.- URL predefinito:
alerts.slack_default_webhook(impostato in/settings). - Override per-alert: imposta il
webhook_setting_keydel canale a qualsiasi altra chiave di impostazione di tipo URL, ad es.alerts.slack_oncall,alerts.slack_costs.
:rotating_light: / :warning: / :bell:), e il messaggio include un pulsante che deep-linka alla pagina dell’incidente.
Webhook generico
Un’integrazione JSON-POST per PagerDuty, Opsgenie, o il tuo endpoint di ingestione. Forma del corpo:alerts.webhook_signing_secret è impostato, la richiesta include un’intestazione X-AgentEye-Signature: sha256=<hex>, l’HMAC-SHA256 del corpo usando il segreto. Verifica su chi riceve prima di fidarti del payload.
L’intestazione X-AgentEye-Event trasporta alert.firing / alert.test. (alert.resolved è riservato per la funzione di auto-resolve pianificata e non è attualmente emessa.)
In-dashboard
Nessuna consegna esterna: l’avviso scrive semplicemente una rigaalert_notifications che la pagina incidenti della dashboard mostra. Utile mentre stai sintonizzando una regola e non vuoi spammare un sistema esterno, o per avvisi a bassa urgenza che gli operatori controllano durante il triage normale.
Ciclo di vita dell’incidente
- firing — il dispatcher ha appena aperto l’incidente o ha rilevato un’altra violazione. La notifica di firing è diffusa esattamente una volta (controllata dal timestamp
notified_firing_atsull’incidente). - acknowledged — un operatore ha premuto ack su
/incidents/:id. L’incidente è ancora considerato aperto; le violazioni successive aggiorneranno le sue evidenze senza ri-notificare. - resolved — un operatore ha premuto resolve. La risoluzione automatica quando la regola smette di violare è pianificata ma non attualmente abilitata, quindi un incidente aperto rimane aperto finché un operatore non lo risolve.


Permessi richiesti
La creazione di regole di avviso e il triage degli incidenti sono preoccupazioni separate con concessioni separate, quindi puoi dare a una rotazione on-call l’accesso agli incidenti senza anche darle la possibilità di riscrivere le regole.alerts:read: visualizza le regole di avviso.alerts:write: crea, modifica, elimina regole di avviso e attiva una notifica di test.incidents:read: visualizza gli incidenti.incidents:write: apri incidenti manuali (ad-hoc) non legati a un avviso.incidents:ack: acknowledges, assegna, commenta e risolvi incidenti.
LegacyConcedi su chiavi API (alerts:ack. Le chiavi e gli operatori a cui è stato concesso il tokenalerts:ackpiù vecchio continuano a funzionare: viene onorato comeincidents:ack(e implicaincidents:read), quindi gli on-caller esistenti mantengono il loro accesso senza ri-emettere credenziali. Emetti nuove concessioni con la famigliaincidents:*.
POST /keys) e operatori (PUT /users/:id). Il PermGate della dashboard blocca i pulsanti rilevanti quando manca un permesso; vedrai // 403 accanto all’azione.
Email-recipient picker. Il selettore di destinatari dell’editor di avviso elenca i membri della tua organizzazione in modo da poterli selezionare per nome. Si carica per qualsiasi operatore che detienealerts:readoalerts:write; visualizzare la directory del tuo team a questo scopo non richiedeusers:read, e il selettore restituisce solo gli indirizzi email dei membri, mai record utente completi.
Configurazione
Variabili d’ambiente consumate dal dispatcher:| Var | Predefinito | Scopo |
|---|---|---|
ALERT_WORKERS | 1 | Attività worker per istanza server. La maggior parte delle implementazioni ne hanno bisogno di una sola. |
ALERT_CLAIM_BATCH | 16 | Max avvisi che un singolo tick worker elabora. |
ALERT_POLL_IDLE_SECS | 5 | Sleep worker quando la coda è vuota. |
ALERT_REQUEST_TIMEOUT_MS | 15000 | Timeout di valutazione per-trigger. |
DASHBOARD_URL | https://app.befailproof.ai | Origine utilizzata per costruire il magic-link dell’incidente nelle notifiche. Impostala all’host della tua dashboard. |
/settings, non env):
alerts.email_default_recipients(email_list): array JSON di stringhe email — i destinatari predefiniti per i canali email.alerts.slack_default_webhook(url): URL webhook in arrivo Slack predefinito.alerts.webhook_default_url(url): URL webhook generico predefinito.alerts.webhook_signing_secret(secret): chiave HMAC-SHA256. Sempre restituita come""nella risposta GET; digita un nuovo valore per ruotare.alerts.enabled_channels(channel_set): il set a livello di organizzazione dei tipi di canale esterni che vengono inviati quando un avviso si attiva; di default tutti e tre (email,slack,webhook). Rimuovendo un tipo qui globalmente sopprimi quel canale per ogni avviso senza modificare ogni regola. Il canale in-dashboard è sempre consegnato e non è interessato da questa impostazione.
Verifica un nuovo avviso
Prima di affidarti a un nuovo avviso:- Salvalo come abilitato con almeno un canale di notifica.
- Seleziona test sulla pagina di dettaglio dell’avviso e conferma che ogni destinazione configurato riceva la notifica sintetica.
- Dopo la prima violazione reale, conferma che l’incidente appaia sotto Incidenti e che il suo valore misurato corrisponda alla corrispondente query della dashboard.
Risoluzione dei problemi
| Sintomo | Causa probabile |
|---|---|
| L’avviso non si attiva mai | enabled = false, o nessun canale collegato, o la query CH sottostante restituisce 0 righe. Usa test per confermare i canali; usa /queries/run per confermare la metrica. |
| Notifica Slack mancante | alerts.slack_default_webhook (o la chiave di override per-alert) non è impostata: controlla alert_notifications.target per righe <unset:…>; o il tipo slack è globalmente disabilitato in alerts.enabled_channels: controlla le righe alert_notifications con status skipped_disabled e target <channel_disabled>. |
| Webhook generico 401 | Il destinatario richiede una firma ma alerts.webhook_signing_secret non è impostato. Verifica nel destinatario che l’HMAC corrisponda a hmac_sha256(secret, body). |
| Email “from all sends failed” | Credenziali SMTP sbagliate o l’indirizzo from è rifiutato dal tuo relay. Stessa superficie che spedisce le email OTP: se quelli funzionano, il trasporto SMTP va bene. |
| L’incidente si riapre ripetutamente | Le manopole composte sono troppo aggressive: prova ad alzare min_breaches o eval_window in modo che i picchi transienti non riaprono gli incidenti che hai risolto. |

