Неделя 160. Один код, два контура

Разбор этой статьи
Эту тему разобрали в подкасте. Слушай параллельно с чтением.
Это сто шестидесятая неделя с момента, как мы запустили Botseller в августе 2023 года. Период: с 17 августа 00:00 до 24 августа 00:00 по Москве.
В прошлом выпуске я рассказал, как самая объёмная неделя августа показала цену темпа: тарифы и модули, залп рассылки и суббота восстановлений, и пообещал две правки той недели откатить сам.
Откатил. Блокировку отправки рассылки при нехватке баланса во вторник вечером заменили предупреждением: клиент видит цену и сам решает, пополнять сейчас или потом. Вкладку «История операций» в субботу спрятали от клиентов, пока она не научится объяснять, за что списано.
По международным платежам ничего нового. На этой неделе все руки были заняты другим контуром.
Неделя шла как обычная: понедельник, вторник, среда в привычном ритме, ночь на четверг ещё десяток правок. Пятница почти пустая. А потом суббота на 110 записей. Половина недели уложилась в одни сутки: платформа научилась разворачиваться второй раз, на серверах в России, из того же кода. Есть клиенты, для которых вопрос «а где стоит сервер» решает всё, и в эти выходные у меня появился ответ.
Не подвиг, а перекос: всё, что касалось контура, легло в одни сутки, и всё остальное в эти сутки ждало. Обращения клиентов в ту субботу я разбирал в паузах между службами, а что можно было отложить, отложил до понедельника. Отсюда и 31 рабочий контур в счётчике вместо привычных восьми-девяти: за сутки мы тронули почти всё, что у нас есть, а в обычную неделю живёт несколько направлений.
Сырой счётчик недели: 221 запись разработки в 31 рабочем контуре, из них 99 объединённых задач и 122 прямые правки. По объёму 5,5 тысячи добавленных строк.
Меня зовут Дмитрий Дьяконов, я основатель и CEO Botseller AI. Мы делаем платформу с AI-продавцом, CRM, мессенджерами, автоматизациями, рассылками, календарём и звонками. Каждую неделю я разбираю, что реально сдвинулось в продукте и зачем это нужно бизнесу. Поехали по 160-й.
Пульс недели

| Направление | Записей разработки | Что это значит простыми словами |
|---|---|---|
| Российский контур: сборка и выкат всех служб | 88 | платформа умеет развернуться второй раз, в России, из того же кода |
| AI-продавец: инструменты у сценариев, база знаний, российская модель | 25 | у бота свой набор инструментов на каждый сценарий диалога |
| MAX, задержка отправки, Telegram: импорт аккаунтов и «прочитано» | 25 | рассылка через MAX, а аккаунты заводятся пачкой |
| Рассылки в Telegram: очередь и честные причины недоставки | 20 | рассылка больше не зависает на одном номере |
| Тарифы, партнёрские выплаты и лишнее в логах | 19 | выплаты партнёрам наконец проходят |
| Рассылки WhatsApp: картинки, видео и документы в шаблонах | 17 | шаблон с картинкой наконец уходит |
| Российский контур: регистрация, вход, мониторинг | 14 | на новом контуре можно зарегистрироваться и войти |
| Интеграции: Bitrix24, голосовой канал, WhatsApp по QR | 9 | Bitrix24 ведёт лиды и сделки вместе |
Главная мысль недели: всё, что мы считали «общим» между двумя площадками, оказалось наполовину чужим. Платформа развернулась второй раз из того же кода, и главные ошибки были не в коде, а в умолчаниях, которые давно никто не проверял.
Российский контур за одни выходные
Переписка с покупателями у части бизнесов не имеет права уезжать за границу: это требование закона о персональных данных, и слова «данные в безопасности» тут не работают, пока сервер физически не в России. Пять недель назад я открыл международную компанию и развёл контуры по юрлицам. Тогда развели документы. Теперь развели серверы.
Я шёл в эти выходные с простой картиной: код общий, настройки общие, значит, работа сводится к тому, чтобы поменять адреса. Код действительно оказался общим. Всё вокруг него оказалось наполовину чужим.

От первой задачи сборки в 01:17 субботы до рабочего входа в 01:02 воскресенья прошло без четверти сутки. Суббота шла слоями, как строят дом: утром база и базовые службы, днём CRM и мониторинг, в 15:18 одной волной службы каналов, вечером конструктор сценариев, голосовой канал и рабочий кабинет. И один откат: аналитическая панель встала в 16:54 и была снята в 17:21, на новой операционной системе она пока не заводится.
Главное решение было принято до субботы. Можно было скопировать готовые сборки служб на новый сервер и настроить руками. Я хотел другого: чтобы пересоздание сервера стоило час, а не день. Поэтому каждую службу платформы научили выкатываться на российский контур по отдельной версии. Принцип для всех правок один: только добавления. Задачи международного контура не трогаем, значение по умолчанию у каждой настройки равно тому, что работает сегодня, а там, где общий файл пришлось сделать переменным, его вид без переменных сверялся с прежним посимвольно.
Мониторинг тоже отдельный: журналы работы платформы у российских клиентов не должны покидать страну. Файлы российского контура вынесены в отдельное хранилище. И мозг тоже российский: движок умеет работать с российской языковой моделью.
А теперь про то, где картина «поменять адреса» разошлась с жизнью.

Первое выяснилось ещё до субботы. Сертифицированная отечественная операционная система не даёт управлять службами с удалённой машины. Можно было ослабить защиту, и выкат стал бы таким же простым, как на международном контуре. Не стал: ради этой защиты система и выбрана. Цена: выкат пришлось перестроить, теперь он идёт с самого сервера, а не снаружи.
Во второй половине субботы дошли до служб каналов, и шесть из них не поднялись вовсе. Причина оказалась мельче некуда: список площадок в коде был закрытым, «российская» в нём не значилась, и проверка отказывалась стартовать. На практике это значило бы, что на новом контуре нельзя подключить ни Telegram, ни MAX, ни WhatsApp, ни чат на сайте. Ещё три службы поднялись, но честно считали себя международным контуром: имя площадки у них было зашито в настройках.
Самое неприятное заметили уже после выката. Логи большинства служб нового контура подписывались именем старого: подпись контура имела единственное значение, международное. Никуда логи не уезжали, они лежали в России, подпись это только надпись на конверте. Но конверт с чужим адресом это первое, за что цепляется глаз, и разделение, ради которого контур заводился, читалось неправильно. Починили в тот же день.
Ещё одна ловушка бытовая: сервер не достаёт сам себя по внешнему адресу, изнутри платформы собственный адрес недостижим. Я ошибся на этом дважды за один вечер: сначала переписал адреса внутренних вызовов бота на внешние, потом оставил команду перезапуска ботов по внешнему адресу. Оба раза служба звонила сама себе по номеру, который снаружи работает, а изнутри молчит.
Последняя могла стоить дороже всех. Скрипт запуска Telegram-ботов не пробрасывал адреса файловых хранилищ. Два контура делили бы одни данные входа Telegram-аккаунтов, а при входе с двух мест Telegram сбрасывает оба: выкат российского контура уронил бы Telegram-аккаунты у клиентов международного. Поймали до выката.
И одна вещь, которая просто удивила. Загрузчик настроек в задачах выката на всех контурах молча обрезал значения с пробелом: имя приложения из двух слов превращалось в одно. Ошибка живая, ни на что не влияла, и на международном контуре я её сознательно не тронул: боевой процесс «попутно» не меняют.
Открываешь второй ресторан по той же поварской книге, а через месяц видишь, что на каждой странице стоит адрес поставщика первого. Второй заказывает продукты в чужой район и не понимает, почему не привозят.
У салона с двумя точками та же книга: скрипт администратора с адресом первой точки, шаблон рассылки с её телефоном, CRM, где «филиал по умолчанию» всегда первый. Никто не проверяет, пока не откроет вторую. Общими оказались не только настройки. Общими оказались ошибки.
Рассылка, которая три часа крутилась на одном номере
Во вторник разбирали рассылку одного из клиентов.

Рассылка в Telegram на 20 контактов. Отправлено одно сообщение. Дальше три часа статус «идёт». Бот при этом проверил ровно два номера, один 228 раз, второй 98. Остальные 19 контактов не проверялись ни разу. Telegram разрешает боту проверить около 300 номеров в сутки, и почти весь запас ушёл на один номер: 99 из 300 и 291 из 300.
Причина обидная. Ответ «такого номера нет в Telegram» ставил на сообщение ошибку, но тут же возвращал его в очередь. Каждые 60 секунд оно бралось в работу заново, а поскольку из очереди берётся одна строка, дальше никого не пускало. Система не падала. Она тихо работала над одним номером.
Представьте оператора колл-центра, который весь день набирает один номер, где не берут трубку. Остальные 19 строк в списке не тронул. Вечером отчитался: работал.
Чинили в три захода за 13 часов: вторник 19:51, вторник 21:41, среда 09:08. И второй заход был ошибкой. Мы пометили ответ «номера нет» постоянным, чтобы мёртвый номер навсегда уходил из очереди. Логично? Да. Только Telegram отвечает ровно так же, когда не отказал, а придержал проверку из-за лимитов, и рабочие номера выбрасывались бы навсегда. Поняли наутро и развели два случая явным признаком.
Урок, который переносится куда угодно: одинаковый ответ на разные причины рано или поздно заставит вас выбрать неверное действие для одной из них.
В отчёте причина недоставки теперь называется «Номера нет в Telegram». Раньше там стояло «Номера нет в WhatsApp», потому что правило ловило общее «не найден»: одна из причин, которыми я хвалился в прошлом выпуске, оказалась не той. Появилась кнопка «Повторить ошибочные»: новая рассылка из номеров с временными ошибками одним нажатием.
Шаблоны WhatsApp с картинкой наконец уходят
Субботним вечером, параллельно с контуром, закрыли дефект. С какой недели он живёт, по данным не восстановить.

Шаблоны официального канала WhatsApp бывают с картинкой, видео или документом в шапке. Считается, что такие цепляют лучше голого текста. У нас они не уходили: рассылка падала с ошибкой формата заголовка на стороне канала, потому что платформа картинку из шапки просто не передавала, как почта, которая берёт у вас открытку, а картинку возвращает с пометкой «не тот формат». Клиент видел «ошибка формата» и мог принять её на свой счёт: не тот файл, не тот размер, попробовать ещё раз. Возможно, поэтому её так долго и не приносили в поддержку, но проверить это по данным я не могу.
Правка была в трёх местах сразу: CRM научилась собирать шаблон с картинкой в шапке, ядро принимать файл, кабинет показывать, что именно приложено, и давать отдельный шаг загрузки, файлом или ссылкой. Картинка до 5 МБ, видео до 16, документ до 100. К ночи страница рассылки начала показывать картинку из шаблона, а не только текст.
Не всё прошло гладко. В 22:23 чинили сбой при загрузке файла, он прожил около часа. А в ночь на воскресенье выяснилось, что прогноз стоимости рассылки, о котором я в прошлом выпуске написал как о сделанном, не показывался никому: кабинет спрашивал цену там, где её никто не считал. Посчитали прямо в кабинете по справочнику цен. Мелочь, но именно на таких мелочах клиент решает, что «оно не работает».
На такую ошибку не жалуются. От неё просто перестают пробовать, и в отчёте она выглядит как «шаблонами с картинкой никто не пользуется». Самая дорогая ошибка та, которую клиент принимает за свою.
Что вскрыл переезд: ключи в коде, лишнее в логах, панель с заводским паролем
Про безопасность я не собирался писать отдельную главу. Переезд не спросил.

Во вторник вечером первый шкаф. Платёжные шлюзы писали в журнал всё, что им попадалось, включая ключи доступа и данные плательщика, которым там не место. Убрали. В тот же вечер закрыли авторизацией три адреса пополнения баланса в сервисе данных: они её не требовали вовсе, а сервис доступен снаружи. Там, где считают деньги, вопрос «кто спрашивает» обязан стоять на каждой двери.
В среду второй. В ядре платформы лежали зашитые ключи от хранилища файлов и отпечаток пароля, а журнал одного из ботов писал ключ доступа к каналу как есть.
В субботу, разворачивая мониторинг для нового контура, нашли третий, и он был хуже двух первых: панель мониторинга международного контура была защищена только стандартной парой логин/пароль. Заводской. Сменили в тот же день, вынесли в настройки сервера. С оговоркой: настройка помогает при пересоздании сервера, а действующий пароль всё равно меняют руками.
Ключи убраны из кода, доступы меняем. Часть этих вещей лежала давно, и злит именно это: не то, что нашлось, а то, что нашлось случайно. Узнай я об этом от клиента, оправдываться было бы нечем. Если бы делал заново, аудит доступов стоял бы в плане переезда первым пунктом, до первой сборки, а не всплывал бы по дороге.
Это как переезжать и найти под шкафом ключи от квартиры, которые «потеряли» два года назад в метре от входной двери. У салона это выглядит так: пароль от Instagram знает уволенный администратор, касса с первого дня открывается кодом «1234», телефон бухгалтера лежит в общем чате. Никто не ищет, пока не переедет. И проверяет это не релиз, а переезд, так что лучше самому назначить его аудитом заранее.
В 157-м выпуске я гордился тем, как мы меняли ключи чата, не закрывая дверь. Там мы смотрели на одну дверь. Переезд заставил обойти весь дом.
Один плюс из той же серии. В российском контуре у CRM своя роль в базе, у движка своя: каждая служба видит только своё. После инцидента с семьюстами тысячами записей это уже не роскошь, и на новом месте такое проще заложить сразу, чем добавлять потом.
База знаний не создавалась 56 часов, а платформа жила не на той версии
История, в которой мы сломали клиентам вещь, ради которой они к нам приходят.

База знаний это то, что делает AI-продавца продавцом конкретного бизнеса. Она режется на куски, чтобы модель читала не всю книгу, а нужную страницу, а перехлёст это сколько строк соседних страниц повторяется, чтобы мысль не рвалась на границе. В понедельник в 11:07 мы сузили эти границы под ограничения российской языковой модели: перехлёст максимум 100 вместо 1000, размер куска до 1000 вместо 10 000. А рабочий кабинет по-прежнему предлагал по умолчанию перехлёст 200.
Итог: с понедельника 11:07 до среды 19:06 любой клиент, нажимавший «создать базу знаний» с настройками по умолчанию, получал ошибку. 56 часов. Редактирование старых баз работало, и это намеренно: сузь мы лимиты и там, сломались бы все базы с перехлёстом 200. Сколько клиентов упёрлось в ошибку, точно не скажу.
Ворота на складе сузили под новый грузовик, а в диспетчерской по-прежнему выписывали старые габариты.
Починили в среду: границы полей в кабинете приведены к серверным, и добавлена проверка, чтобы такое не повторилось. Урок бытовой: поменяли правило в одном окошке, проверьте бланк, который люди заполняют по умолчанию в другом. У нас бланк двое суток обещал то, что окошко уже не принимало.
Вторая история из той же среды, и она напугала меня больше первой. Во вторник мы приняли в основную линию большую работу: AI-продавец получает на каждый сценарий диалога свой набор инструментов, обновить статус лида, отправить файл, назначить встречу. В среду при сверке оказалось, что действующая платформа работает на более свежей версии этой работы, которая в основную линию не попадала, и что в ней две ошибки, которые автоматическая проверка обязана была поймать. Не поймала: проверка в сборку не входила, сборка светилась зелёным.
То есть клиенты пользовались версией, которой по бумагам не существовало. Известных поломок не случилось, и это везение, а не заслуга. Хвост приняли в два приёма, каждый прогнали руками. Поставку приняли по накладной, не открыв ни одной коробки: бумага сошлась, что внутри, никто не смотрел.
«Сборка прошла» и «код правильный» это два разных утверждения. У вас это звучит так: «отчёт сдан» и «работа сделана».
Тариф на виду, выплаты партнёрам и 7 дней, которых нет
Три коротких, все про деньги.

Во вторник в списке бизнесов у администратора вместо двух переключателей появилась одна колонка «Тариф». Переключатели были для CRM и для модуля работы с Telegram, и раньше их включали руками. С прошлой недели пробный период включает оба сам, так что переключатели стали лишними: новый клиент в первые три дня получает всё без участия администратора.
Вечером влили правку дефекта, за который мне неловко перед партнёрами. Заявка на партнёрскую выплату падала всегда. Всегда, с того дня, как выплаты появились: число начислений уходило нулём, а сервис данных требует хотя бы одно. Партнёры продают платформу под своим брендом, комиссия это их деньги, и отказ по нашей ошибке здесь хуже любого другого. Две недели назад я чинил партнёрскую ссылку, которая теряла клиента молча. Оказалось, что дальше по той же цепочке деньги партнёра не доходили вообще: начислить комиссию мы могли, выплатить нет. Сами начисления никуда не делись, отклонялась только заявка. Кто именно упёрся в отказ, я ещё не сверил. Теперь при реальных начислениях заявка проходит, а при нуле отказ честный, с причиной.
Тогда же нашли расхождение в тексте под галочкой согласия при регистрации: там ещё значились семь дней пробного периода, а у нас он три дня. Ту же семёрку мы две недели назад убирали из блога, здесь она чистку пережила. Поправили во всех языках интерфейса. У владельца салона это та же история: акция на сайте обещает «первый визит минус 20%», а администратор пробивает 15, потому что две строки никто не сверил.
И вкладка «История операций», которую я обещал откатить. В субботу её спрятали от клиентов. Она показывала список списаний без контекста: сумма, дата, и всё, чек без названий товаров. Вернём, когда каждая строка сможет объяснить себя.
Каналы: Telegram, MAX, Bitrix24 и телефония, которая молчала правильно
Короткие вещи для тех, кто живёт в этих каналах.

В среду у исходящих сообщений в Telegram появился статус «прочитано»: как две галочки в мессенджере, только видит их продавец, а не собеседник. «Прочитал и не ответил» и «не дошло» это разные разговоры, и теперь их можно вести по-разному.
Ночью на четверг появился массовый импорт Telegram-аккаунтов: загружаешь их списком, видишь таблицу с телефоном, именем и статусом, загрузка идёт с прогрессом. Раньше аккаунты заводили по одному.
Понедельник в основном ушёл на MAX: летом он научился писать первым в диалоге, теперь умеет рассылки. Той же ночью на четверг появилось поле «Задержка отправки» для ботов WhatsApp по QR и MAX: минимум единица, по умолчанию десять, раньше настроить её было нельзя. Почему именно десять, в данных не осталось, и я не помню сам.
Bitrix24 получил режим «лиды и сделки одновременно». Часть клиентов ведёт в нём и то и другое, а раньше при подключении приходилось выбирать одно; теперь в настройке видны все воронки, и автоматические дожимы не теряются.
WhatsApp по QR: если историю переписки вытащить не удалось, бот с понедельника отвечает на последнее сообщение, как будто история состоит из него одного, вместо того чтобы молчать. Ответит, но может не помнить, о чём говорили. Мы решили, что это лучше тишины.
И телефония. 12 августа телефонный движок голосового канала завершил работу штатно, без ошибки, и служба присмотра за процессами его не перезапустила: правило было «перезапускать только при сбое», а сбоя не было.
Охранник ушёл с поста, потому что «смена закончилась», а замену никто не вызвал.
Звонки перестали работать, и заметили это не сразу: служба ушла штатно, и в сводке состояний это не выглядело падением. Починили во вторник, правило для всех служб голосового канала сменили на «всегда». Для того, кто обязан работать круглосуточно, тихий выход это сбой. Просто без грохота.
Главный итог недели

Один код, два контура. Я много раз произносил это как формулу и до субботы не понимал, что во второй половине фразы главное слово «два».
Параллельно переезд сделал то, чего не сделал бы плановый аудит: заставил открыть шкафы. Ключи в коде, лишнее в логах, панель с заводским паролем. Ничего из этого мы не искали.
Что я забираю с собой: слово «общее» надо читать построчно. Вторая площадка наследует не только рецепты, но и опечатки в них, и узнаёшь ты об этом ровно в тот день, когда она открывается.
От переезда клиент международного контура за эти выходные не заметил ничего: ни одна строка поведения на его стороне не изменилась. Заметить он мог только правки продукта из сюжетов выше. Наверное, это лучший результат недели, хотя в отчёте он выглядит как пустая строка.

Следующая неделя: первый рабочий понедельник российского контура, где страница воронок не открывалась, а выкат правки дважды блокировался из-за одного невидимого символа в настройках. И дефект основного продукта, из-за которого бот в 88% случаев не замолкал, когда менеджер отвечал клиенту из мессенджера.
Приходите в Telegram-канал
Если этот формат отчётов вам полезен, подпишитесь на наш Telegram-канал @botseller_ai. Там я каждую неделю выкладываю бортовые журналы и короткие заметки про продуктовые решения, эксперименты и инциденты. Без рекламы, без воды, только то, что мы сами считаем важным.
Если хотите попробовать Botseller в своём бизнесе, используйте кнопку регистрации в шапке сайта. Я не вставляю отдельную ссылку в текст: платформа сама выберет правильный путь входа в зависимости от контура и настроек.
FAQ
Что такое российский контур и кому он нужен?
Это вторая полная копия платформы у российского облачного провайдера: база, файлы, логи, мониторинг и языковая модель находятся в России. Он нужен компаниям, для которых хранение переписки с клиентами внутри страны это требование закона. Код у обоих контуров один, поэтому возможности не расходятся; исключение пока одно, аналитическая панель.
Я клиент международного контура. Для меня что-то изменилось?
Нет. Все правки для российского контура делались по принципу «только добавления», а значение по умолчанию у каждой настройки осталось прежним. Заметить вы могли только исправления в самой платформе, о которых рассказано выше.
У меня рассылка в Telegram висит со статусом «идёт» и отправила одно сообщение. Что делать?
До среды так вела себя любая рассылка, где в списке был номер, которого нет в Telegram: он занимал единственное место в очереди и не пускал остальных. Сейчас такой номер уходит в отчёт с причиной «Номера нет в Telegram», а рассылка идёт дальше. Если часть номеров помечена временной ошибкой, нажмите «Повторить ошибочные»: соберётся новая рассылка только из них.
Я загрузил картинку в шаблон WhatsApp, а рассылка падает с ошибкой формата. Это я что-то не так делаю?
Нет, до субботы это была наша ошибка: платформа не передавала картинку провайдеру официального канала, и тот отвечал ошибкой формата, хотя файл был в порядке. Теперь картинка, видео или документ загружаются на шаге переменных, файлом или ссылкой, и видны в предпросмотре до отправки.
Вы пишете, что панель мониторинга была защищена заводским паролем. Мои данные кто-то мог видеть?
Панель показывает графики нагрузки и журналы работы служб, а не переписку с вашими клиентами. Пароль сменили в тот же день, ключи убрали из кода, доступы меняем. И вывод я сделал не про пароль: аудит доступов теперь идёт у нас по расписанию, а не по случаю переезда.
Куда делась вкладка «История операций» из раздела баланса?
Мы временно спрятали её от клиентов. Она показывала суммы списаний без объяснения, за какую рассылку или диалог они произошли. Вкладка вернётся, когда каждая строка сможет объяснить себя.
Партнёрские выплаты теперь работают?
Да. Раньше заявка не проходила никогда: число начислений передавалось нулём, а сами начисления при этом сохранялись. Теперь заявка проходит, если начисления есть, а при нуле отклоняется честно, с причиной.



