Hear about failures: alerts
Alerts tell you something broke without you opening the Runs page. They live on the project’s Alerts page in three tabs: Channels say where a message goes, Rules say what should alert and when, and History lists every message sent. In this lesson you connect a channel, write a rule for unattended runs, break a script on purpose and watch the Failed and Working again messages arrive.
- Connect a Slack, Teams, Discord, e-mail or webhook channel and send a test
- Write a rule: what alerts, on which outcomes, to which channels
- Understand grouping, Working again and a channel’s delivery health
- Verify a webhook’s signature on your own server
How alerts work
Waiso checks finished runs every few seconds. Every run of a script, flow or AI Scraper robot that is started at the top level is matched against the project’s active rules; a schedule that was due but could not start counts too. A match becomes a message on each of the rule’s channels — at most one per channel per event, however many rules match.
A message names the item, the first line of the error, the failing step of a flow, what started the run (a schedule, an API token, an event trigger) and a link to the run — never its inputs, outputs or variables. Steps inside a flow alert as their flow, not one by one, and a cancelled run never alerts.
Add a channel
- Where
On Alerts, open Channels and press Add channel (on an empty page, Add a channel). Where should alerts go? — Slack, Microsoft Teams, Discord, E-mail or Webhook. The kind cannot change after saving.
- Details
Give it a Name and its address. Slack: an Incoming Webhook URL. Teams: a Workflows webhook URL. Discord: channel settings → Integrations → Webhooks. E-mail: the addresses under Send to, sent through the project’s e-mail provider. Webhook: any public
https://address. URLs are stored encrypted and never shown again. - Save and test
Press Save channel, then Send test on its row: Test delivered to #ops-alerts. — or the reason it was not. For a webhook, the next step shows the signing secret once: copy it and press I copied it.
Write a rule
On Rules, press New rule. The wizard has four steps — What, When, Where, Review — and you can go back to any of them.
| Step | Choices | Default |
|---|---|---|
| What should alert? | Everything · Only unattended (runs started by a schedule, an API call or an event — not the ones a person starts from the editor) · Chosen items (scripts and flows you pick) | Everything |
| When: which outcomes? | Failed · Working again (the first good run after failures) · Didn’t start (a schedule was due but could not start) | Failed + Working again |
| Where should it go? | One or more channels, and Group repeats: 5, 15 or 60 min | 15 min |
| Review | A Name and a summary of what the rule will do; Save rule | — |
Each rule has an Active switch on its row; a paused rule sends nothing. Deleting a channel that rules use pauses any rule left with no channel, and the page says how many.
Grouping and Working again
The first failure of an item alerts at once (Failed: nightly-import). More failures of the same item are counted, and at most once per grouping window one follow-up goes out — Still failing: nightly-import failed 7 more times since the last alert. The first good run after failures sends Working again, with how long it was broken. So a schedule failing every minute all night is a handful of messages, not hundreds.
History and delivery health
History lists every message with its kind (Failed, Still failing, Working again, Didn’t start, Test, Summary), its status (Delivered, Sending, Failed, In a summary) and Open run. A failed delivery is retried after 30, 90 and 180 seconds. Each channel shows its delivery health: Not used yet, Delivering, Last try failed, or Not delivering after its last three deliveries failed — the Overview panel counts those.
The webhook channel
A webhook channel receives a JSON POST per message, signed with X-Waiso-Signature: t=<unix seconds>,v1=<hex>, where v1 is hmac_sha256(secret, "<t>.<body>") over the raw body. Check it before trusting the call, and reject old timestamps so a captured request cannot be replayed.
{
"type": "failed",
"project": {
"id": "p_7Hq2…",
"name": "Reports"
},
"item": {
"kind": "script",
"id": "…",
"name": "nightly-import"
},
"error": "RuntimeError: the upstream file was empty",
"step": null,
"startedBy": "schedule 'nightly'",
"count": 1,
"brokenForSeconds": null,
"runId": "…",
"runUrl": "https://<your-waiso-address>/projects/reports/runs?run=…",
"at": "2026-10-16T03:00:04Z"
}import hashlib, hmac, time
def verify(secret: str, header: str, body: bytes, max_age: int = 300) -> bool:
"""header = the X-Waiso-Signature value: "t=1760000000,v1=ab12…"."""
parts = dict(item.split("=", 1) for item in header.split(","))
t, v1 = parts.get("t", ""), parts.get("v1", "")
if not t.isdigit() or abs(time.time() - int(t)) > max_age:
return False # too old: a replayed request
expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)Limits
- Webhook addresses must be public
https://URLs (That address is not allowed: use a public https:// URL.). Each send is checked again, redirects are not followed, and a send times out after 10 seconds. - A channel sends at most 20 messages a minute; the rest of that minute is merged into one And 12 more alerts in this minute summary.
- An e-mail channel needs the project’s e-mail provider (Add one in Integrations → E-mail.).
- Only admins and the project’s creator can change alerts.