Notifications
How OpenQuok creates in-app notifications and sends notification emails (immediate vs digest), including BullMQ worker setup and troubleshooting.
Connect your agent today
Draft from chat, review in your calendar, and publish only what you approve.
Notifications (in-app + email)
OpenQuok notifications have two layers:
- In-app notifications — always persisted to the database and shown in the UI.
- Notification emails — optional; sent immediately or batched into a digest depending on the caller.
Where the code lives
- API entrypoint: backend/services/NotificationService.ts (
inAppNotification) - Recipient + digest logic: backend/services/TransactionalNotificationEmailService.ts
- Email HTML fragments: backend/emails/notificationTransactionalEmailHtml.ts
- Flowcraft “send plain” + “digest flush” workflows:
- orchestrator/blueprints/notificationEmailBlueprint.ts
- orchestrator/nodes/notificationEmailNodes.ts
- orchestrator/activities/emailActivities.ts (organization helpers; similar role to OpenQuok activities)
- BullMQ worker (executes queued email sends + periodic digest flush):
- orchestrator/worker/runNotificationEmailBullMqWorker.ts
Behavior: sendEmail and digest
The API always writes the in-app row first. Email is only attempted when:
sendEmail === true, and- email is enabled (EMAIL_ENABLED), and
- the user’s org-member preferences allow that type (success vs failure).
Digest vs immediate
Digest mode (
digest: true) stores entries in Redis and relies on the notification-email worker to flush them on an interval. Immediate mode (digest: false) sends one email per call.Current callers (production code)
- Scheduled post success →
sendEmail: true,digest: true(avoid spam when many channels publish). - Scheduled post errors / preflight blocks →
sendEmail: true,digest: false(action needed now). - Integration refresh failure →
sendEmail: true,digest: false(match OpenQuok “needs attention” urgency).
Setup (local development)
Enable email sending
Follow the email provider setup guide, then ensure the backend has email enabled.
EMAIL_ENABLED=true See Resend - Email Setup for the full provider configuration.
Run Redis locally
Notification email digest + BullMQ transport require Redis.
docker compose -f infra/docker-compose.yml up -d redis See Docker (local Redis) for the recommended local Redis settings.
Choose transport (BullMQ vs in-process)
The backend supports two transports for notification email:
in_process— send directly from the API process (no queue).bullmq— enqueue sends to Redis and run a worker to deliver them.
Override the transport at runtime with:
- ORCHESTRATOR_NOTIFICATION_EMAIL_TRANSPORT
Run the notification-email worker (BullMQ transport)
When transport is bullmq, you must run the worker:
pnpm orchestrator:dev:worker:notification-email-bullmqTroubleshooting: “I don’t receive notification emails”
- Check email is enabled: EMAIL_ENABLED must be true.
- Check transport: if
bullmq, the notification-email worker must be running. - Check Redis: worker and API must point at the same Redis (REDIS_*).
- Check user preferences: success/fail emails may be opted out per member (digest flush emails are type
infoand are always eligible). - Check digest timing: digest entries flush on an interval (default ~5 minutes) from the worker process.
- Check Resend HTTPS: production outbound mail uses
POST https://api.resend.com/emails(not SMTP :465). If the worker can reachapi.resend.comover HTTPS, send should work even when SMTP is blocked. - Failed digest sends retry: Redis digest entries are acknowledged only after a successful send; a failed flush leaves them for the next interval.