Notifications & channels
When a verdict is ask, Belay can fan the approval prompt out to a chat channel and take your Allow / Deny reply straight back — so you can answer a paused agent from your phone, without a desktop or a terminal in front of you. On a headless VPS the chat bot effectively is the interface.
Channels come in two flavours:
- Two-way approval channels deliver the prompt with tappable Allow / Deny controls and read your reply back into the decision.
- Notify-only channels deliver a heads-up but cannot carry a decision.
When to use
- You run agents on a headless VPS with no desktop, and want approvals delivered to a chat app instead of a tray popover.
- You want a durable, phone-friendly audit trail of the prompts that paused an agent.
- You want a passive heads-up (notify-only) even when approvals are answered elsewhere.
For local, at-a-glance approvals you can also use the terminal or the Desktop App Messaging tab — the same approval queue backs all of them.
Supported channels
| Channel | Direction | Approval controls |
|---|---|---|
| Telegram | Two-way | Inline Allow / Deny buttons |
| Discord | Two-way | Allow / Deny buttons |
| Two-way | Allow / Deny reply | |
| Matrix | Two-way | Allow / Deny reply |
| Mattermost | Two-way | Allow / Deny reply |
| Slack | Two-way | Block Kit Allow / Deny buttons |
| ntfy | Notify-only | — |
| Microsoft Teams | Notify-only | — |
| WeCom | Notify-only | — |
| Generic webhook | Notify-only | — |
| Terminal | Two-way (local) | Local Allow / Deny prompt |
How the router works
Belay fans a single ask out to every configured channel at once. The first real
Allow / Deny answer wins; if nobody answers before the prompt expires, the decision
fails closed to deny — the same fail-closed rule as everywhere else in Belay
(timeout or error never becomes a silent allow).
- Auto-expiry. Prompts carry a deadline (
BELAY_APPROVAL_TIMEOUT_MS). A stale prompt is auto-denied, and the buttons stop accepting late answers. - Deny still wins. Approving through a channel only clears an
ask; it can never downgrade adeny. Verdict priority is Deny > Ask > Allow throughout.
Authorized approvers (owner-gating + default-deny)
Channels are default-deny: an incoming reply is honored only if it comes from an enrolled approver. Nobody can approve a Belay prompt just by messaging the bot.
Enrollment is done through an interactive pairing handshake, owner-gated over the daemon's IPC:
- Start pairing (from the setup wizard, the Desktop App Messaging tab, or the owner IPC admin). Belay shows a one-time code.
- The approver DMs the bot with
pair <code>. - Belay enrolls that chat identity as an authorized principal. From then on, only that principal's Allow / Deny replies are accepted on that channel.
The owner can list (redacted), add, and remove allowed principals at runtime; the allowlist
persists owner-only (0600) and takes effect live.
Configuring channels
Channels are configured through the setup wizard (belay setup) or the
Desktop App Messaging tab, and stored under
~/.belay/channels.json. The channels subcommand prints how the channels run — inside
the daemon's ASK fan-out, not as a standalone server:
belay channels
Once a channel and at least one approver are configured, ambiguous (ask) verdicts are
automatically routed to it while the agent is paused.
Privacy
Consistent with Belay's privacy posture, notifications are privacy-safe: the Desktop App's native system notifications carry the category only and never the underlying path or command. Belay does not phone home by default; channel messages go only to the chat platform you configured.