Перейти к основному содержимому

ADR-006: WebSocket для уведомлений

  • Статус: Принято
  • Дата: 16 апреля 2026
  • Автор: CTO Agent (KALA-133)

Контекст

В AgentCore уже была WebSocket-инфраструктура для прогресса agent-tasks. Новым продуктовым флоу понадобились realtime-уведомления пользователей про approvals, упоминания и сгенерированные документы. Нужно было выбрать: расширять существующий WebSocket-плагин, добавлять server-sent events или полагаться на REST-polling.

Решение

Добавить /ws/notifications в тот же Fastify WebSocket-плагин.

Канал уведомлений:

  1. аутентифицируется той же JWT-моделью, что и REST;
  2. поддерживает query-token или first-message аутентификацию;
  3. подписывается на notification-события аутентифицированного userId;
  4. шлёт notification.created, когда продюсер вызывает emitNotification();
  5. держит durable-состояние в таблице notifications.

Рассмотренные альтернативы

Только REST-polling

Отклонено. Polling простой, но добавляет задержку в approval и document-ready флоу и раздувает количество запросов с активных дашбордов.

Отдельный SSE-эндпоинт

Пока отклонено. SSE хорош для server-to-client событий, но в приложении уже есть проверенный WebSocket с аутентификацией. Добавлять ещё один транспорт — это дублировать auth- и lifecycle-логику.

Расширить /ws/agent-tasks

Отклонено. Прогресс agent task привязан к namespace/task scope. Уведомления — к user inbox scope. Разные пути позволяют не смешивать семантику подписок.

Последствия

Плюсы

  • Переиспользует существующий WebSocket-плагин и JWT verify-путь.
  • Доставка уведомлений привязана к текущей identity пользователя.
  • REST inbox остаётся source of truth после переподключения.
  • Тесты могут проверять сокет через те же WebSocket-хелперы.

Минусы

  • Текущий EventEmitter-бродкаст — in-process.
  • Multi-replica production потребует Redis pub/sub или другую shared event bus.
  • Клиентам всё равно нужна REST-синхронизация для пропущенных во время disconnect событий.

Заметки по реализации

  • src/lib/notifications.ts владеет emitNotification() и subscribeUserNotifications().
  • src/plugins/websocket.ts регистрирует /ws/notifications.
  • Продюсеры сначала создают запись в БД, потом emit-ят событие.
  • Сокет закрывается с кодом 4001 при auth-таймауте или невалидном токене.