Skip to content

GitHub Notification Routing

Daniel Ellison edited this page Sep 3, 2026 · 1 revision

GitHub Notification Routing

GitHub activity (pushes, PRs, issues, comments, reviews, plus the PR review and issue triage summaries) lands on a notification channel: an outbound-only Workshop channel (the ! kind in the sidebar) that acts as a feed. Which channel receives your GitHub activity is a per-person choice, and the delivery outbox fans each recorded notification out to the surfaces you use, including Telegram.

Routing is canonical and per person. There is no global env var that reroutes GitHub traffic; the retired GITHUB_NOTIFY_CHAT_ID is read nowhere and setting it does nothing.

The routing model

Every notification is recorded once, canonically, on a destination channel, then delivered. Three layers decide what reaches you where:

  1. Destination. Each integration class (github, generic) resolves to one channel per person: your personal selection when you have made one, otherwise the operator's protected policy. A Reset returns you to policy, not to a DM.
  2. Channel level. Every channel carries your notification level: All messages, Mentions and replies (the default), or Muted, with an optional "direct mentions override muted channels" and a do-not-disturb window.
  3. Adapter toggles. Per-adapter switches decide whether a delivery adapter (Telegram, say) alerts you at all.

Because the notification is recorded canonically first, changing your destination or muting a channel never loses history; it changes where new activity lands and what alerts you.

Where you control it

Workshop Settings is the primary surface:

  • Notification delivery has the per-integration-class destination pickers (with Reset to policy), the per-channel levels, the mention override, do-not-disturb, and the adapter toggles. See Workshop Settings.
  • GitHub has the review and triage toggles, your repo subscriptions, and the write-only token field. Edits are concurrency-checked; a conflicting save asks you to reload rather than overwriting.

On Telegram, /notifications covers the same ground: /notifications github lists your available destinations as a numbered list, /notifications github <number> picks one, and reset restores protected policy. /github notify is the GitHub-specific spelling of the same picker. Raw chat IDs are not accepted; destinations are canonical channels, chosen by number from the list.

Repo subscriptions

Kai only routes GitHub webhook events to people subscribed to the relevant repo. Subscriptions live canonically per person, with the users.yaml github_repos field as the admin-set baseline.

Effective repo list

(yaml baseline ∪ added at runtime) - removed at runtime

The yaml baseline is never modified; runtime additions and removals are stored as separate deltas, so admin changes to users.yaml propagate automatically unless you explicitly removed the repo. Admins with an empty github_repos list receive events from all repos as a wildcard fallback.

One boundary to keep straight: github_repos is also the authorization baseline for the PR review and issue triage agents. /github add grants notification routing for a repo; it never grants the agents authority to act on it. Only the admin editing users.yaml does that.

Commands

/github add owner/repo      subscribe (registers the webhook when a token is stored)
/github remove owner/repo   unsubscribe (removes the webhook when no subscribers remain)
/github                     show destination, subscriptions with source labels, toggles, token status

GitHub token

A personal access token lets Kai register and remove webhooks for you, and it is the credential the review and triage agents post with. Store it in Workshop Settings (write-only field) or with /github token <value>; clear it with /github token clear. The token needs the admin:repo_hook scope for webhook management (or write:repo_hook without delete), and repo access appropriate to what the agents do.

Without a token, /github add still subscribes you and prints manual webhook registration instructions pointing at https://your-domain/webhook/github with your GITHUB_WEBHOOK_SECRET.

Events with no subscriber

An event from a repo nobody is subscribed to falls back to the default admin route and is recorded there. If even that recording fails, the webhook answers 503, and GitHub retries the delivery later; nothing is silently dropped. Deliveries must carry GitHub's X-GitHub-Delivery header (GitHub always sends it); requests without it are rejected with a 400, and the ID is what makes redeliveries idempotent.

Group-backed channels from users.yaml

The github_notify_chat_id field in users.yaml survives with exactly one job: at startup bootstrap, a negative (group) ID seeds a Workshop notification channel with the matching members, so an install migrating from the old Telegram-group workflow gets an equivalent canonical channel. The field does not route live traffic; after bootstrap, routing follows the destination selection above.

Telegram commands summary

Command Effect
/github Show destination, repo subscriptions with source labels, toggles, token status
/github notify List numbered destinations; /github notify <number> picks one
/github notify reset Restore the protected-policy destination
/notifications The general surface: adapters, channel levels, muted-mentions, DND, destinations
/github add <owner/repo> Subscribe to a repo (registers webhook if token is stored)
/github remove <owner/repo> Unsubscribe (removes webhook if no other subscribers)
/github token <value> / clear Store or remove your GitHub token
/github reviews on|off Toggle the PR review agent for your account
/github triage on|off Toggle the issue triage agent for your account

Troubleshooting

Notifications landing somewhere unexpected:

  • Check your destination for the github class in Workshop Settings (Notification delivery) or /notifications github; remember Reset returns to the operator's policy, not to a DM
  • Check the destination channel's notification level; Mentions and replies (the default) will record activity without alerting you

Not being alerted at all:

  • Check the per-adapter toggles and do-not-disturb window in Notification delivery
  • The activity is still recorded on the channel either way; open it in the Workshop to see the feed

No notifications recorded at all:

  • Confirm the repo is in your effective subscription list (/github)
  • Confirm the GitHub webhook is delivering: check the recent deliveries on the repo's webhook settings page and that Kai's endpoint is reachable (see Exposing Kai to the Internet)
  • A repo with no subscriber routes to the default admin channel; check there before concluding the event was lost

Review or triage summaries missing:

  • Those follow the same github destination, but the agents themselves are gated separately: the per-person toggle, the github_repos authorization baseline, and a stored token. See PR Review Agent and Issue Triage Agent

Clone this wiki locally