Signals & Notifications — Overview¶
Audience: Business stakeholders, product owners, analysts, new team members.
What This Module Does¶
The Signals & Notifications module is Swisper's outbound communication system. While the main chat interface requires users to open the app, Signals pushes messages to them proactively — through Telegram or Threema — when something important happens. This includes daily morning briefings, urgent email alerts, upcoming meeting preparations, commitment reminders, and follow-ups on emails awaiting a response.
The system does not decide what to send — that logic lives in the background jobs. Signals is the delivery layer: it takes a NotificationMessage (title + content + target user), determines which channels the user has enabled, formats the message for each channel, and delivers it.
Who It Serves¶
| Persona | Need |
|---|---|
| End users | Receive timely, relevant notifications on their preferred messaging platform without opening Swisper |
| Product owners | Understanding which channels are supported, what controls users have, and how notifications are delivered |
| Backend developers | Sending notifications from new jobs or features using the SignalsService API |
Key Capabilities¶
- Multi-channel delivery — Messages are sent in parallel to all of a user's enabled notification channels. Currently supported: Telegram (Markdown v1) and Threema (plain text).
- Two-level preference model — A global
signals_enabledtoggle (stored inuser_preferences) controls whether the user receives any notifications at all. Per-channelnotifications_enabledflags (onUserIntegration) let users selectively enable or disable individual channels. - Channel-specific formatting — Each channel implementation formats the
NotificationMessageappropriately: Telegram uses Markdown with bold titles and character escaping; Threema uses plain text with emoji prefixes. - Retry and rate-limit handling — The Threema channel uses exponential backoff (3 attempts) for timeout and server errors, and gracefully handles HTTP 429 rate-limit responses without retrying.
- Convenience methods —
send_email_notification()provides a preformatted notification for new email alerts, which is the most common notification type.
How It Fits in the Platform¶
- Background Jobs — Daily briefing, pre-meeting prep, important email, commitment reminder, and awaiting-response jobs all call
SignalsService.send_notification()as their delivery mechanism. - Integrations — Telegram and Threema channels read their delivery address (
chat_id,threema_id) from theUserIntegrationrecords managed by the Integrations module. - Notification Preferences API — The frontend settings page reads and writes preferences through dedicated endpoints that the
SignalsServicerespects at delivery time. - Greeting System — Operates independently; the greeting system uses the chat interface, not the signals pipeline.
Limits and Edge Cases¶
- Two channels only. The system currently supports Telegram and Threema. Adding a new channel requires implementing the
NotificationChannelABC and registering it in theSignalsService. - No delivery receipts. The system logs success or failure of the API call but does not track whether the user actually read the notification.
- Threema is one-way. Users cannot reply to Swisper via Threema. Threema Gateway only supports outbound messages.
- Global toggle is workspace-scoped. The
signals_enabledflag is stored inuser_preferences.standard_rules, which is a workspace-level setting.
FAQ¶
Q: What happens if a user has no notification channels connected?
A: get_user_channels() returns an empty list, and the notification is silently skipped. The background job logs that no channels were available.
Q: Can I add a new notification channel (e.g., email, SMS)?
A: Yes. Implement the NotificationChannel ABC (from notification_channels/base_channel.py), adding send(), get_user_id(), and is_notifications_enabled() methods. Then register the channel instance in SignalsService.__init__().
Q: Does disabling signals_enabled affect all channels?
A: Yes. When signals_enabled is False, no notifications are sent regardless of per-channel settings.
Q: Are notifications batched or sent individually?
A: Each notification is sent individually. If a background job generates multiple notifications (e.g., for multiple users), each is a separate send_notification() call.