Перейти до основного вмісту

Канали

WhatsApp

Адаптер WhatsApp використовує офіційний Meta WhatsApp Business Cloud API (graph.facebook.com/v18.0). Вхідні повідомлення приходять через Meta webhooks; вихідні відправляються через REST-виклики до Cloud API.

Плагіни каналів читають свою рантайм-конфігурацію через app.channelService. Поточна реалізація — EnvChannelService на базі env-змінних; вона віддає один дефолтний WhatsApp-канал і один дефолтний Telegram-канал. Інтерфейс готовий до майбутньої мультиканальної реалізації з БД.

Архітектура

src/channels/whatsapp/
├── index.ts # Service factory (WhatsAppService)
├── plugin.ts # Fastify plugin (routes)
├── connection.ts # Cloud API client, webhook parsing, token lifecycle
├── handler.ts # Transport normalization + AgentTask creation
├── sender.ts # Rate-limited outbound sender
├── queue.ts # BullMQ inbound/outbound workers
├── auth-state.ts # OAuth token persistence in Redis
├── conversation-repository.ts # Prisma conversation store
└── types.ts # Config and message types

Конфігурація

ЗміннаЗа замовчуваннямОпис
WHATSAPP_APP_IDMeta app ID (використовується для оновлення токена)
WHATSAPP_APP_SECRETMeta app secret (використовується для оновлення токена)
WHATSAPP_PHONE_NUMBER_IDPhone number ID з дашборду Meta Business
WHATSAPP_ACCESS_TOKENПочатковий OAuth access token
WHATSAPP_WEBHOOK_VERIFY_TOKENWebhook verify token (задається в дашборді Meta)
WA_PHONE_NUMBER+380000000000Номер телефону відправника (як префікс Redis-ключа)
WA_RATE_LIMIT_PER_MIN60Макс вихідних повідомлень на хвилину

Налаштування

  1. Створіть Meta-застосунок з увімкненим продуктом WhatsApp Business.
  2. Додайте номер телефону і запамʼятайте Phone Number ID у дашборді.
  3. Згенеруйте long-lived access token і задайте WHATSAPP_ACCESS_TOKEN.
  4. Задайте WHATSAPP_WEBHOOK_VERIFY_TOKEN і налаштуйте webhook URL у дашборді Meta:
    • Verify endpoint: GET /api/v1/whatsapp/webhook
    • Events endpoint: POST /api/v1/whatsapp/webhook
  5. Задайте решту env-змінних і запустіть сервер.

Життєвий цикл підключення

  1. Сервер стартує; викликається WhatsAppConnection.connect().
  2. Збережений токен підтягується з Redis. Якщо його нема — сконфігурований WHATSAPP_ACCESS_TOKEN зберігається в Redis.
  3. Якщо термін дії збереженого токена спливає протягом 7 днів — він обмінюється на новий long-lived token через Meta Graph API.
  4. Проактивна перевірка виконується кожні 6 годин для ранньої ротації токенів.
  5. При шатдауні скидається refresh-планувальник.

Сканування QR не потрібне — автентифікація повністю через OAuth-токени.

Потік повідомлень

Вхідний

  1. Meta шле POST на /api/v1/whatsapp/webhook.
  2. Payload парситься у connection.ts (handleWebhookPayload).
  3. Кожне повідомлення витягується і передається зареєстрованим обробникам.
  4. Обробник ставить повідомлення у wa-inbound (BullMQ).
  5. Воркер:
    • шукає/створює User і Conversation за WhatsApp JID;
    • зберігає вхідне повідомлення;
    • створює AgentTask;
    • ставить завдання в чергу agent-tasks.

Маршрут одразу повертає { received: true }; обробка асинхронна, щоб влізти в таймаут відповіді Meta.

Спільний agent-task воркер виконує інʼєкцію профілю, RAG, генерацію, privacy-перевірки, ескалацію персони, обхід матриці довіри та HITL-маршрутизацію для WhatsApp і Telegram.

Вихідний

  1. Схвалене/автопропущене повідомлення ставиться у чергу wa-outbound.
  2. Воркер викликає WhatsAppSender.send().
  3. Rate limiter (token bucket) чекає на доступну квоту.
  4. Повідомлення відправляється через POST /{phoneNumberId}/messages у Cloud API.

Ендпоінти

МетодШляхОпис
GET/api/v1/whatsapp/statusСтатус підключення Cloud API
GET/api/v1/whatsapp/webhookВерифікація Meta webhook (hub.challenge)
POST/api/v1/whatsapp/webhookПрийом вхідних повідомлень від Meta

Форматування повідомлень

Відправник підтримує нативне форматування WhatsApp:

  • *bold*
  • _italic_
  • ~strikethrough~
  • `код` та ```code block```

Rate limiting

Token bucket на процес відправника. Налаштовується через WA_RATE_LIMIT_PER_MIN (дефолт: 60 повідомлень/хв).

Зберігання токенів

OAuth access-токени зберігаються в Redis під префіксом ключа <sessionKeyPrefix><phoneNumber>:. Для кожного токена — два ключі:

Суфікс ключаЗначення
access_tokenПоточна строка access token
token_expires_atUnix ms timestamp закінчення дії (порожній рядок, якщо невідомо)

Токени ротуються проактивно, коли до експірації лишилось менше 7 днів. Щоб скинути збережені токени (наприклад, після revoke) — викличте clearTokenState(redis, keyPrefix) з auth-state.ts.


Telegram

Адаптер Telegram використовує Grammy — Telegram Bot Framework для Node.js.

Архітектура

src/channels/telegram/
├── index.ts # Service factory
├── plugin.ts # Fastify plugin (routes)
├── bot.ts # Grammy bot initialization
├── handler.ts # Transport normalization + AgentTask creation
├── sender.ts # Outbound message formatting
├── queue.ts # BullMQ inbound/outbound workers
├── conversation-repository.ts # Prisma conversation store
└── types.ts # Config and message types

Конфігурація

ЗміннаЗа замовчуваннямОпис
TG_BOT_TOKENTelegram bot token від @BotFather
TG_RATE_LIMIT_PER_MIN30Макс повідомлень на хвилину

Налаштування

  1. Створіть бота через @BotFather у Telegram
  2. Скопіюйте bot token
  3. Задайте TG_BOT_TOKEN у .env
  4. Перезапустіть сервер

Поточний плагін запускає бота в режимі long-polling і експонує status-ендпоінт.

Потік повідомлень

Вхідний

  1. Grammy отримує повідомлення через long-polling
  2. Повідомлення стає в чергу tg-inbound (BullMQ)
  3. Воркер:
    • шукає/створює User і Conversation за Telegram user ID;
    • зберігає вхідне повідомлення;
    • створює AgentTask;
    • ставить завдання в чергу agent-tasks.

Далі спільний agent-task воркер вирішує: відправити автоматично, створити HITL-схвалення чи ескалувати до персони.

Вихідний

  1. Схвалене повідомлення ставиться у чергу tg-outbound
  2. Воркер форматує під Telegram MarkdownV2 / HTML
  3. Відправляє через Grammy bot API
  4. Rate limiter приглушує за потребою

Ендпоінти

МетодШляхОпис
GET/api/v1/telegram/statusСтатус бота

Форматування повідомлень

Telegram підтримує:

  • **bold**
  • _italic_
  • `inline code`
  • Блоки коду
  • HTML-форматування як fallback

Трекінг розмов

Кожен Telegram-користувач трекається за його tg_user_id. Conversation-репозиторій створює записи User і Conversation при першому контакті — аналогічно до WhatsApp-адаптера.