| 1 | --- |
| 2 | name: "notification-routing" |
| 3 | description: "Route agent notifications to specific channels by type — prevent alert fatigue from single-channel flooding" |
| 4 | domain: "communication" |
| 5 | confidence: "high" |
| 6 | source: "earned" |
| 7 | --- |
| 8 | |
| 9 | ## Context |
| 10 | |
| 11 | When a Squad grows beyond a few agents, notifications flood a single channel — failure alerts drown in daily |
| 12 | briefings, tech news buries security findings, and everything gets ignored. This is the pub-sub problem: |
| 13 | a single message queue for everything is a recipe for missed alerts. |
| 14 | |
| 15 | The fix is **topic-based routing**: agents tag notifications with a channel type, and a routing function |
| 16 | sends them to the appropriate destination. |
| 17 | |
| 18 | **Trigger symptoms:** |
| 19 | - Important alerts missed because they're buried in routine notifications |
| 20 | - Team members turning off notifications entirely (signal overwhelm) |
| 21 | - Onboarding friction: "where do I look for X?" |
| 22 | |
| 23 | ## Patterns |
| 24 | |
| 25 | ### Channel Config Schema |
| 26 | |
| 27 | Define a `.squad/teams-channels.json` (or equivalent) mapping notification types to channel identifiers: |
| 28 | |
| 29 | ```json |
| 30 | { |
| 31 | "teamId": "your-team-id", |
| 32 | "channels": { |
| 33 | "notifications": "squad-alerts", |
| 34 | "tech-news": "tech-news", |
| 35 | "security": "security-findings", |
| 36 | "releases": "release-announcements", |
| 37 | "daily-digest": "daily-digest" |
| 38 | } |
| 39 | } |
| 40 | ``` |
| 41 | |
| 42 | Place this in `.squad/` (git-tracked, shared across the team). For platforms that use channel IDs instead of |
| 43 | names (Teams, Slack), store the resolved ID alongside the name to avoid name-collision bugs: |
| 44 | |
| 45 | ```json |
| 46 | { |
| 47 | "channels": { |
| 48 | "notifications": { "name": "squad-alerts", "id": "channel-id-opaque-string" } |
| 49 | } |
| 50 | } |
| 51 | ``` |
| 52 | |
| 53 | ### CHANNEL: Tag Convention |
| 54 | |
| 55 | Agents prefix their output with `CHANNEL:<type>` to signal where the notification should go: |
| 56 | |
| 57 | ``` |
| 58 | CHANNEL:security |
| 59 | Worf found 3 new CVEs in dependency scan: lodash@4.17.15, minimist@1.2.5 |
| 60 | ``` |
| 61 | |
| 62 | ### Routing Dispatcher (shell pseudocode) |
| 63 | |
| 64 | ```bash |
| 65 | dispatch_notification() { |
| 66 | local raw_output="$1" |
| 67 | local channel="notifications" # default |
| 68 | |
| 69 | if echo "$raw_output" | grep -qE '^CHANNEL:[a-z][a-z0-9-]*'; then |
| 70 | channel=$(echo "$raw_output" | head -1 | cut -d: -f2) |
| 71 | raw_output=$(echo "$raw_output" | tail -n +2) |
| 72 | fi |
| 73 | |
| 74 | send_notification --channel "$channel" --message "$raw_output" |
| 75 | } |
| 76 | ``` |
| 77 | |
| 78 | ### Provider-Agnostic Adapter |
| 79 | |
| 80 | The routing layer is provider-agnostic. Plug in your platform adapter: |
| 81 | |
| 82 | ``` |
| 83 | .squad/notify-adapter.sh # Teams / Slack / Discord / webhook -- swappable |
| 84 | ``` |
| 85 | |
| 86 | The routing config and CHANNEL: tags never change. Only the adapter changes per deployment. |
| 87 | |
| 88 | ## Anti-Patterns |
| 89 | |
| 90 | **Never send all notification types to one channel:** |
| 91 | ``` |
| 92 | send_notification --channel "general" --message "$anything" |
| 93 | ``` |
| 94 | |
| 95 | **Never use display names as identifiers (name collision risk):** |
| 96 | ``` |
| 97 | send_to_team --name "Squad" --channel "notifications" |
| 98 | ``` |
| 99 | |
| 100 | Resolve channel IDs once at setup. Use IDs at runtime. |
| 101 | |
| 102 | ## Distributed Systems Pattern |
| 103 | |
| 104 | This is **pub-sub with topic routing** -- the same principle as Kafka topics, RabbitMQ routing keys, and |
| 105 | AWS SNS topic filtering. Route by type. Each consumer subscribes to the topics it cares about. |