← К схеме

Telegram

чат-интеграция · знания в мессенджере

Знания компании — в переписке Telegram

Сотрудник пишет боту в личных сообщениях — отвечает Query Engine под его доступами, со ссылками на источники. Всё, что умеет веб-чат, не выходя из мессенджера.

Telegram — ещё одно тонкое окно в тот же диалог: думает и ищет Query Engine под личностью сотрудника, Telegram лишь приносит реплику и уносит ответ. Близнец Slack — расходятся в одном: беседу режет не тред, а команда /new. Одна модель диалога на все поверхности →

01

Подключение

Admin регистрирует бота у @BotFather один раз — bot-токен и webhook-секрет ложатся в telegram_settings, как SMTP у Email. Экран — настройки платформы, один тумблер включает бота.

Webhook-секрет Achilles генерирует сам при setWebhook — админ его не вводит, в отличие от signing secret у Slack.

02

Личность

Пишущего сводит к учётке identity_mapping (source='telegram') — личность входа. Telegram не отдаёт email, поэтому авто-матча нет: только код-привязка — вошедший в веб получает код и возвращает его боту. Учётку заводит только админ (приглашением) — знание бота доступа не даёт.

Публичный бот: непривязанному — нейтральный отказ, подбор кода ограничен. Дальше везде только user_id → роль → ACL.

03

Беседа

В личке тредов нет: команда /new открывает новую беседу, остальные сообщения продолжают текущую. /new — команда адаптера, в историю диалога не попадает. Контекст усекается по токенам — общий механизм движка.

Беседа живёт в conversations (ключ chat_id в meta), активную адаптер держит указателем в Redis. Группы · @mention · темы — v2.

04

Доставка

Webhook принимает апдейт, подтверждает сразу, обработка уходит в очередь interactive, ответ возвращается сообщением. Переживает рестарт и ретраи.

Повтор апдейта отсекается по update_id; публичный эндпоинт — под rate-limit.

Как это выглядит

Ответ под доступами Максима: что ему не видно — в ответ не попадёт. Следующая реплика продолжает беседу, /new открывает чистую.

Первый контакт — привязка аккаунта кодом:

Бот отвечает одинаково всем — известному и встречному, существование инстанса не выдаёт. Код виден только во вошедшем браузере и возвращается в бот — пересланная ссылка угнать учётку не даёт. Экран привязки →

Что в базе

identity_mapping Auth · правка + source='telegram' → мост личности входа
link_tokens Auth · общая одноразовый код привязки (вошёл в веб → вернул боту)
conversations.meta Query Engine ключ беседы chat_id
telegram:active-conv: Cache & Workers указатель активной беседы chat_id → беседа · /new сбрасывает
dedup:telegram-update: Cache & Workers идемпотентность повторов апдейтов
telegram_settings подключение к боту · общее ядро singleton · CHECK (id = 1)
id BigInteger PKCHECK всегда 1 · singleton
bot_token_enc Text NULL токен бота от BotFather (12345:ABC…), шифротекст AES-256-GCM
webhook_secret_enc Text NULL секрет вебхука (заголовок X-Telegram-Bot-Api-Secret-Token) · Achilles генерирует сам · шифротекст
bot_username Text NULL @имя бота для UI · из getMe
enabled Boolean NOT NULLDEFAULT мастер-выключатель · DEFAULT false · off → бот молчит
last_test_ok Boolean NULL итог последней проверки доставки: токен жив и webhook зарегистрирован — не просто валидный токен
last_test_at DateTime(tz) NULL когда проверяли · питает чип статуса на экране
created_at DateTime(tz) DEFAULT server_default=now()
updated_at DateTime(tz) DEFAULT server_default=now() · триггер set_updated_at()

is_available() — свойство модели, не колонка: enabled и заполнены bot_token_enc · webhook_secret_enc. Общее ядро со slack_settings; расходятся в одном — webhook-секрет генерируем мы, а не выдаёт провайдер.

Честное включение. Включение бота атомарно: Achilles вызывает setWebhook, и переключатель остаётся включённым только если Telegram принял регистрацию — отказ (отозванный токен) или недостижимый адрес откатывают enabled и возвращают причину, а не зелёный тумблер без доставки за ним. Telegram доставляет лишь на публичный HTTPS-адрес, поэтому localhost/приватный PUBLIC_BASE_URL отклоняется сразу. «Проверить соединение» читает ту же правду — getMe плюс getWebhookInfo — так что живой токен с незарегистрированным webhook показывается как не подключено.

Проверки: секрет вебхукарезолв личностидедуп update_id/new = новая беседаACL-проброснепривязанный пользовательлимит подбора кода

API

Вебхук анонимный по замыслу: замок — секретный токен в заголовке X-Telegram-Bot-Api-Secret-Token, который Achilles сгенерировал при setWebhook, а окно rate-limit работает fail-closed.