На главную

Почему бот SalesMachine «подтвердил» встречу, которой не было

Классификатор ответов лидов принял отказ за согласие — виновата цитата письма. Разбираем баг и два одновременно сломанных канала уведомлений.

Нашли это случайно, проверяя совсем другой сигнал — и хорошо, что проверили, потому что вскрылось сразу две независимые проблемы, каждая из которых по отдельности легко могла бы остаться незамеченной месяцами. Система показывала подтверждённую встречу с лидом через страницу услуг: дата, время, статус “готов к встрече”. По документам всё выглядело как маленькая победа автоматизации SalesMachine. На деле оказалось, что об этой встрече никто не узнал вовремя, а потом — что самой встречи не было вообще.

Оба канала уведомлений упали одновременно

Первая проблема: ни один из двух автоматических каналов оповещения не сработал. Создание события в календаре падало с ошибкой авторизации, а токен обновления доступа сам не продлевался — судя по коду ответа, это было похоже не на обычное истечение срока действия, а на отозванный или недействительный токен, требующий полного повторного входа. Второй канал, уведомление в Telegram, падал по совершенно другой причине: токен бота в переменных окружения проекта оказался мёртвым, зашитым и забытым — из другого класса багов, чем протухший токен доступа, но с тем же результатом. Оба канала отказали в одно и то же время, и на протяжении двух дней о предположительно подтверждённой встрече не пришло ни единого сигнала ни в календарь, ни в мессенджер. Telegram-часть починили в той же сессии, переключив уведомления на уже работающий общий канал бота, которым в проекте пользуется другой процесс — и проверили реальной тестовой отправкой, что сообщение доходит. Календарная часть требует личного повторного входа в аккаунт Google — автоматически пройти это агент не может, это тот шаг, который обязан сделать только человек, которому принадлежит аккаунт.

Встречи не было вообще

Разбор переписки, чтобы вручную поставить встречу в календарь на время, пока не работает автоматика, вскрыл вторую, более глубокую проблему: самой встречи не существовало. Лид на предложенный слот времени ответил прямым отказом — но письмо classифицировалось системой как согласие. Причина оказалась в том, как устроена проверка ответа по ключевым словам: она сканировала весь текст письма целиком, включая процитированный оригинал сообщения бота внизу письма. А в этой цитате был тот же вопрос про предложенное время — и именно он создал ложное совпадение по ключевым словам, хотя реальный ответ лида означал ровно противоположное.

Тихая ошибка классификации опаснее явного отказа

Это тот класс ошибок, что страшнее прямого отказа: система не просто не поняла ответ — она уверенно поняла его неправильно и на этом основании создала запись, которая потом попала бы в статистику как успешная бронь. Нашли и починили корень: добавили обрезку цитируемого текста перед любой классификацией ответа, и по ключевым словам, и в промпте для более сложного анализа — письма в этой системе приходят с уже схлопнутыми переносами строк, поэтому обычная проверка “это строка начинается с цитаты” не сработала бы, понадобилась проверка по первому вхождению маркера цитирования в тексте. Отдельно добавили явную фразу отказа в список стоп-слов. На реальном тексте того самого письма классификация после фикса дала верный результат.

Проверили не только один случай

Одного найденного случая недостаточно, чтобы считать проблему закрытой — если баг сработал один раз на реальных данных, разумно предположить, что он мог сработать и раньше, просто незамеченным. Проверили этим же паттерном все недавние ответы лидов на предмет того же типа ошибки. Нашлось ещё несколько похожих по структуре писем, но там ложное совпадение по ключевым словам случайно всё равно указывало на верный результат — реальные слова лида сами по себе означали то же самое, что и совпавшая цитата, вреда не было, трогать не стали. Ложную запись о встрече убрали из системы, а статус конкретного письма в статистике поправили на настоящий — чтобы будущие ежедневные отчёты не подсвечивали расхождение, которого на самом деле уже нет, и не считали лида готовым к брони, которой никогда не будет.

Похожая история — про то, как холодные письма ломаются на ровном месте — в посте про частые ошибки в холодных рассылках.