From 1bef5e0627f305d00dbf5580c275680b8160be53 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:36:59 -0700 Subject: [PATCH] docs: notification routing guide (closes #50) Concise docs page for multi-channel notification routing. Covers pub-sub routing, supported providers (Slack, Teams, Discord, webhooks), routing rules configuration, and real-world severity-based routing example. - Added notification-routing.md with ~140 lines - Updated navigation.ts to include new feature page - Updated test/docs-build.test.ts with 'notification-routing' in EXPECTED_FEATURES Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/features/notification-routing.md | 142 ++++++++++++++++++ docs/src/navigation.ts | 1 + test/docs-build.test.ts | 1 + 3 files changed, 144 insertions(+) create mode 100644 docs/src/content/docs/features/notification-routing.md diff --git a/docs/src/content/docs/features/notification-routing.md b/docs/src/content/docs/features/notification-routing.md new file mode 100644 index 000000000..b3c9bdecc --- /dev/null +++ b/docs/src/content/docs/features/notification-routing.md @@ -0,0 +1,142 @@ +--- +title: "Notification routing" +description: "Route agent notifications across channels by severity, agent, or topic." +--- + +## Problem: Alert fatigue + +When you run 8+ Ralph instances funneling alerts into one Slack channel, the noise becomes overwhelming. You need a way to route notifications to the right people, channels, or systems based on severity, agent, or topic. + +## Pub-sub routing + +Squad's notification system decouples agents (producers) from notification consumers. Routes are defined as **routing rules** that match against notification metadata and forward messages to configured channels. + +**Key benefits:** +- **Decouple agents from channels** — Agents don't know where alerts go +- **Filter by severity, agent, or topic** — Route critical alerts to PagerDuty, info logs to Discord +- **Provider-agnostic** — Route to Slack, Teams, Discord, webhooks, or custom endpoints +- **Reuse rules across squads** — DRY routing configurations + +## Supported providers + +| Provider | Use case | +|----------|----------| +| Slack | Team chat, channel notifications | +| Microsoft Teams | Enterprise messaging | +| Discord | Community, dev team channels | +| Webhooks | Generic HTTP endpoints, custom logic | +| Custom endpoints | Your infrastructure (Datadog, PagerDuty, etc.) | + +## Configuration + +Routing rules are defined in `.squad/notification-routes.yaml`: + +```yaml +routes: + - name: critical-alerts + match: + severity: critical + destinations: + - type: slack + channel: "#emergency" + mention: "@incident-commander" + + - name: ralph-verbose + match: + agent: ralph + severity: debug + destinations: + - type: discord + channel: "dev-logs" + + - name: pagerduty-integration + match: + severity: [critical, warning] + destinations: + - type: webhook + url: https://events.pagerduty.com/v2/enqueue + auth: token +``` + +## Real-world example + +**Scenario:** You have 3 Ralph agents running load tests in production. You want: +- **Critical errors** → PagerDuty + Slack #incident-response +- **Warnings** → Slack #alerts +- **Info/debug** → Discord #dev-logs (for post-analysis) + +```yaml +routes: + - name: ralph-critical + match: + agent: ralph + severity: critical + destinations: + - type: webhook + url: https://pagerduty.api.example.com/v2/events + - type: slack + channel: "#incident-response" + mention: "@on-call" + + - name: ralph-warnings + match: + agent: ralph + severity: warning + destinations: + - type: slack + channel: "#alerts" + + - name: ralph-debug + match: + agent: ralph + severity: [info, debug] + destinations: + - type: discord + channel: "load-test-logs" +``` + +## Rule matching + +Routes are evaluated top-to-bottom. The first rule that matches handles routing. If no rule matches, the notification is logged but not routed. + +**Match operators:** +- **Exact match:** `severity: critical` +- **List match (OR):** `severity: [critical, warning]` +- **Wildcard:** `agent: ralph*` (matches ralph-1, ralph-staging, etc.) +- **Negation:** `NOT severity: debug` + +## Destination configuration + +Each destination supports provider-specific options: + +```yaml +- type: slack + channel: "#alerts" # Required + mention: "@team" # Optional: mention users/groups + emoji: ":warning:" # Optional: message emoji + thread: true # Optional: reply in thread + +- type: teams + channel: "Notifications" # Required + importance: high # Optional: message priority + +- type: webhook + url: https://example.com/alerts + auth: token # Optional: bearer or api-key + timeout: 10 # Optional: timeout in seconds +``` + +## Testing routes + +Use the CLI to test a routing configuration: + +```bash +squad notification-routes validate +squad notification-routes test --agent ralph --severity critical +``` + +## See also + +- [Notifications](/docs/features/notifications/) — Message templates and formatting +- [Ralph](/docs/features/ralph/) — Load testing agent +- [Source PR: bradygaster/squad#625](https://github.com/bradygaster/squad/pull/625) diff --git a/docs/src/navigation.ts b/docs/src/navigation.ts index 5e7cbfdfc..7cc15139e 100644 --- a/docs/src/navigation.ts +++ b/docs/src/navigation.ts @@ -67,6 +67,7 @@ export const NAV_SECTIONS: NavSection[] = [ { title: 'Plugins', slug: 'features/plugins' }, { title: 'MCP', slug: 'features/mcp' }, { title: 'Notifications', slug: 'features/notifications' }, + { title: 'Notification Routing', slug: 'features/notification-routing' }, { title: 'Enterprise Platforms', slug: 'features/enterprise-platforms' }, { title: 'Squad RC', slug: 'features/squad-rc' }, { title: 'Streams', slug: 'features/streams' }, diff --git a/test/docs-build.test.ts b/test/docs-build.test.ts index 702a4274d..03764450d 100644 --- a/test/docs-build.test.ts +++ b/test/docs-build.test.ts @@ -68,6 +68,7 @@ const EXPECTED_FEATURES = [ 'memory', 'model-selection', 'notifications', + 'notification-routing', 'parallel-execution', 'plugins', 'prd-mode',