Skip to content

Webhook Notifications

Sia edited this page May 31, 2026 · 2 revisions

Webhook Notifications (Slack / Discord / Telegram)

Companion to the SMTP email notifier (Email Notifications). Same triggers fire both channels in parallel; either can be left disabled.

Configure at /settings/webhook.

Why webhooks alongside email

  • Email goes to your inbox; team chat goes to the room. Most operators want build failures in #dev-alerts and disk warnings in #ops.
  • No new infrastructure needed — Slack / Discord / Telegram all accept authenticated POST requests with a shared secret URL.
  • Zero new dependencies — WebhookNotifier uses JDK 11+ java.net.http.HttpClient and kotlinx.serialization already on the classpath.

Architecture

   Build complete                Disk > 85%               Claude usage > 80%
        │                             │                             │
        ▼                             ▼                             ▼
  ┌────────────────────────────────────────────────────────┐
  │              Notifiers (facade)                         │
  │   ┌──────────────────┐    ┌─────────────────────────┐  │
  │   │  EmailNotifier   │    │   WebhookNotifier        │  │
  │   │  (SMTP / Jakarta)│    │   (HttpClient)            │  │
  │   │                  │    │                           │  │
  │   └─────────┬────────┘    └─────────┬─────────────────┘  │
  └─────────────│──────────────────────│──────────────────────┘
                ▼                       ▼
           SMTP server         Slack / Discord / Telegram

Both notifiers are enabled=false by default. Failures are swallowed and logged — neither blocks the originating action (build, monitor tick, etc.).

Configuration

server.yml:

webhook:
  enabled: true                                          # Master switch
  slackUrl:    "https://hooks.slack.com/services/T../B../..."
  discordUrl:  "https://discord.com/api/webhooks/<id>/<token>"
  telegramBotToken: "123456:ABC-DEF..."
  telegramChatId:   "987654321"

Equivalent .env overrides:

VIBECODER_WEBHOOK_ENABLED=true
VIBECODER_WEBHOOK_SLACK_URL=https://hooks.slack.com/services/T../B../...
VIBECODER_WEBHOOK_DISCORD_URL=https://discord.com/api/webhooks/.../...
VIBECODER_WEBHOOK_TELEGRAM_BOT_TOKEN=123456:ABC-...
VIBECODER_WEBHOOK_TELEGRAM_CHAT_ID=987654321

Any individual provider can be left empty — only those with a URL/token are contacted. The enabled master switch must still be on.

Provider setup

Slack

  1. In the channel of your choice, Add apps → Incoming Webhooks.
  2. Pick the channel, click "Add".
  3. Copy the webhook URL — it always starts with https://hooks.slack.com/services/. Anything else is rejected by the SSRF whitelist.

Discord

  1. Server settings → Integrations → Webhooks → New Webhook.
  2. Name the webhook, pick the target channel, copy URL.
  3. URL must start with https://discord.com/api/webhooks/ or the legacy https://discordapp.com/api/webhooks/.

Telegram

  1. Talk to @BotFather on Telegram: /newbot → name, username → bot token.
  2. Start a chat with your new bot (so it can message you back).
  3. Find your chat id by visiting https://api.telegram.org/bot<token>/getUpdates in a browser after sending the bot a message — look for "chat":{"id":...}. For group chats, add the bot to the group and find the (often negative) group id the same way.
  4. Token format must match ^\d+:[A-Za-z0-9_-]+$.

Testing

/settings/webhook has a 🛎 테스트 메시지 전송 button. Click it to fire one message to every configured provider; the page reloads with a per-provider result string like slack=ok,discord=fail.

Security: SSRF whitelist

WebhookNotifier rejects any URL outside the three host families above and sets HttpClient.Redirect.NEVER to prevent cross-host hops. This means you cannot point vibe-coder at an arbitrary internal HTTP endpoint via the webhook URL field — even if you wanted to (logging to a local collector, etc.). If you need that, build a small adapter that subscribes to the audit log instead.

Triggers (same as SMTP)

Trigger Helper method Payload subject
Build success/failure buildResult(projectId, buildId, status, errorMessage) Build SUCCESS / Build FAILED
Claude usage transition claudeUsageWarn(remainingPercent, resetAt) Claude usage warning
Disk usage transition diskUsageWarn(usedPercent, freeGb) Disk usage warning

All payloads are kept short (Slack and Telegram cap text length around 3500 chars; Discord caps content at 2000).

Audit

No dedicated webhook.* action — the trigger (build/audit/etc.) is what gets logged. Send failures appear only in the server log (webhook send failed: ...).

Clone this wiki locally