Skip to main content

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

ChannelDirectionApproval controls
TelegramTwo-wayInline Allow / Deny buttons
DiscordTwo-wayAllow / Deny buttons
WhatsAppTwo-wayAllow / Deny reply
MatrixTwo-wayAllow / Deny reply
MattermostTwo-wayAllow / Deny reply
SlackTwo-wayBlock Kit Allow / Deny buttons
ntfyNotify-only
Microsoft TeamsNotify-only
WeComNotify-only
Generic webhookNotify-only
TerminalTwo-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 a deny. 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:

  1. Start pairing (from the setup wizard, the Desktop App Messaging tab, or the owner IPC admin). Belay shows a one-time code.
  2. The approver DMs the bot with pair <code>.
  3. 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.