КейсыРастИИшка
Диалоги · Дирижёр

Клиент пишет по частям: когда ИИ-продавцу пора отвечать

Обсудить задачу → Оставить заявку

Клиент пишет три короткие реплики, а бот отвечает на первую и теряет отрицание в третьей. Разбираем механику сборки серии: окно ожидания, порядок событий и правила исключений до отправки ответа.

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

Представьте условный диалог: в 10:02 клиент пишет «Здравствуйте, интересует интеграция», в 10:03 добавляет «но у нас два юрлица», а в 10:04 уточняет «и оплата только по счёту в конце месяца». ИИ-продавец отвечает на первую реплику приветствием и общим прайсом, вторую и третью не замечает и уходит в тишину. Через час менеджер видит в переписке три вопроса и один нерелевантный ответ — и уже не понимает, что именно бот пообещал.

Механизм проблемы не в «плохом ИИ», а в том, что каждое входящее сообщение обрабатывается как самостоятельный запрос. Мессенджер присылает события по одному, модель отвечает на то, что видит в моменте, а человек пишет мысль не одним абзацем, а очередями коротких реплик. Пока система не научилась собирать серию в один смысловой пакет и сохранять порядок, любой ответ рискует оказаться ответом на устаревшую часть разговора.

Маршрут серии: от трёх событий до одного ответа
Маршрут серии: от трёх событий до одного ответа. Авторская схема 404ai.

Почему событие в мессенджере — не сообщение, а строчка в очереди

В API мессенджеров входящее сообщение приходит как отдельное событие с идентификатором, временем и автором. Telegram Bot API, например, отдаёт обновления через getUpdates или вебхук, и каждое обновление — это самостоятельная запись, а не «письмо целиком». Если обрабатывать её сразу, система физически не знает, что через сорок секунд придёт продолжение. Это не баг платформы, а её контракт: бот получает поток событий, а не готовый диалог.

Дальше вступает второй слой — задержка ответа. Пока модель думает, пока идёт запрос к базе знаний, пока формируется текст, в очередь успевают лечь ещё две реплики. Классический паттерн асинхронного запроса-ответа (его описывает Microsoft в архитектурных материалах) прямо предполагает, что обработка занимает время и результат возвращается не мгновенно. Значит, проектируя ИИ-продавца, мы обязаны решить, что делать с событиями, которые пришли «в процессе».

Есть и третий слой — человеческий. Люди пишут так, как думают: сначала тема, потом ограничение, потом уточнение. Иногда наоборот — сначала эмоция, потом суть. Разбивка на реплики сама по себе несёт смысл: пауза между сообщениями часто означает «я ещё формулирую» или «я передумал». Если склеить всё в один текст без учёта времени, можно потерять именно эту интонацию.

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

Если ваша задача — настроить обработку серии сообщений, на странице соответствующего направления 404ai можно посмотреть опубликованные возможности и оставить описание текущего процесса. Конкретные подключения, исходные данные и критерии приёмки согласуем отдельно.

Окно сборки: сколько ждать и почему нельзя «просто подождать»

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

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

Параметр окна Что задаёт Риск при малом значении Риск при большом значении
Мягкий интервал Пауза тишины, после которой пакет считается завершённым Реплики «разрываются», бот отвечает на первую Клиент ждёт ответа дольше, чем готов
Жёсткий потолок Максимум от первой реплики до обработки Обрывает длинную мысль на середине Ответ приходит, когда тема уже сменилась
Минимум реплик для сборки Сколько сообщений склеивать перед ответом Лишние задержки на одиночных вопросах Сложнее предсказать поведение

Важно: окно — это не «пауза перед ответом вообще». Это правило, по которому несколько событий превращаются в один объект обработки. Если клиент написал одно сообщение и замолчал, окно всё равно закрывается по мягкому интервалу, и бот отвечает как обычно. Универсальной «правильной паузы» не существует — есть параметр, который настраивают и проверяют на своих сценариях.

Серия коротких реплик: пакет реплик, а не отдельное сообщение

Чтобы окно не превратилось в лоскутное одеяло из таймеров, вводится явная сущность — пакет реплик (conversation burst). Это запись, которая живёт между приходом первого события и отправкой ответа. Внутри неё хранится всё, что нужно, чтобы ответ был связным и проверяемым.

Минимальная форма такого объекта:

  • burst_id — идентификатор пакета, единый для всех склеенных реплик;
  • author_id и channel — кто и где пишет (важно для случая двух участников);
  • messages[] — упорядоченный список реплик с временем, текстом и вложениями;
  • first_seen_at и last_seen_at — границы окна;
  • order_key — правило сортировки (по времени события, с разрешением коллизий);
  • status — collecting, closed, processing, answered, escalated;
  • superseded_by — ссылка на пакет, который заменил этот (если клиент изменил первую реплику);
  • reply_ref — какой именно ответ ушёл по этому пакету.

Смысл status в том, чтобы никто — ни модель, ни оператор — не отвечал на пакет дважды. Смысл superseded_by в том, чтобы правка ранней реплики не терялась: если клиент отредактировал первое сообщение, старая версия помечается как заменённая, а не удаляется молча. Смысл reply_ref в том, чтобы после отправки можно было однозначно сопоставить ответ и исходную серию.

Такая форма решает главную проблему: ответ строится не по последнему событию, а по упорядоченной серии. Модель получает на вход весь пакет и инструкцию «ответь на всю серию, учитывая порядок», а не «ответь на это сообщение». Разница принципиальная: во втором случае отрицание в третьей реплике просто не попадает в контекст.

Пакет реплик: поля и статусы обработки
Пакет реплик: поля и статусы обработки. Авторская схема 404ai.

Когда реплики пришли не в том порядке

Порядок — не формальность. События могут прийти с разными временными метками из-за задержек сети, ретраев вебхука или потому, что клиент писал с двух устройств. Если система сортирует по времени получения, а не по времени отправки, «нет, подождите» может оказаться раньше «да, давайте», и смысл перевернётся.

Практическое правило: сортировать по времени, которое проставил мессенджер (поле в событии), а при равенстве — по порядку получения, и фиксировать оба значения в пакете. Если метки противоречат друг другу (например, событие пришло с временем раньше уже сохранённого), это повод не «угадывать», а помечать пакет флагом order_conflict и передавать оператору. Лучше показать человеку странность, чем построить уверенный ответ на перемешанных репликах.

Отдельный случай — ретраи. Мессенджеры могут повторно доставлять обновление, если бот не подтвердил получение. Без дедупликации по идентификатору сообщения одна и та же реплика попадёт в пакет дважды, и модель решит, что клиент настойчиво повторяет вопрос. Дедупликация — обязательная часть сборки, а не «оптимизация на потом».

Изменение первой реплики и редактирование на ходу

Клиент отправил «Нужна интеграция с CRM», потом передумал и отредактировал на «Нужна интеграция с 1С». Если система уже начала обработку по старой версии, ответ уйдёт про CRM — и это будет честная ошибка на устаревших данных. Здесь помогает не «умная модель», а механика: при редактировании ранней реплики пакет помечается как изменённый, а текущая обработка либо отменяется, либо доводится до конца с явной пометкой «ответ на предыдущую версию».

Есть тонкость: не всякое редактирование меняет суть. Исправление опечатки не должно сбрасывать окно и запускать всё заново — иначе клиент, поправивший запятую, получит задержку. Разумный компромисс — сравнивать версии и пересобирать пакет только при смысловом изменении, а мелкие правки применять «на месте», не трогая таймеры. Как именно определять «смысловое» — вопрос настройки; на старте достаточно правила «изменился текст длиннее N символов или появилось/исчезло отрицание».

Если пакет уже в статусе answered, а клиент отредактировал реплику, честнее не переписывать историю, а создать новый пакет со ссылкой superseded_by на старый. Тогда в переписке видно: был ответ на версию А, теперь обсуждается версия Б. Это защищает и клиента, и менеджера от путаницы «а что мы вообще обещали».

Проверка исключений: порядок, правки, дубли
Проверка исключений: порядок, правки, дубли. Авторская схема 404ai.

Длинная пауза: когда серия уже не серия

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

Это правило защищает от накопления «хвоста»: без него система может тянуть незакрытый пакет сутками и однажды ответить на вопрос недельной давности. Новый пакет при этом наследует контекст диалога (кто клиент, о чём говорили раньше), но не смешивает старые реплики с новыми в одном ответе.

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

Новый вопрос внутри серии: склейка не должна съедать смену темы

Бывает, что клиент в одной серии задаёт два разных вопроса: «Сколько стоит подключение?» и сразу «И ещё: есть ли мобильное приложение?». Формально это одна серия, но по сути — два запроса. Если ответить одним абзацем, один из вопросов утонет. Если разбить на два ответа — вернёмся к проблеме «бот отвечает по частям».

Рабочий приём — не склеивать всё в монолит, а размечать пакет на подтемы и отвечать структурно: сначала по первому вопросу, затем по второму, явно называя, на что отвечаешь. Модель получает инструкцию «если в серии больше одной темы, разбей ответ на части и не смешивай их». Это не гарантирует идеала, но снижает риск, что клиент увидит ответ только на половину.

Отдельно стоит вопрос приоритета: если в серии есть срочный вопрос («мы сейчас на встрече, нужен ответ в течение часа») и обычный, срочный обрабатывается первым. Это уже не про склейку, а про маршрутизацию — но маршрутизация опирается на тот же пакет, где срочность видна как часть серии, а не как отдельное сообщение.

Два участника в одном чате: чей пакет собираем

В групповом чате или в переписке, где пишут два представителя клиента, реплики разных авторов нельзя сваливать в один пакет. Иначе бот ответит «коллеге», который на самом деле уточнял деталь для своего руководителя, и запутает роли. Пакет привязан к автору: у каждого участника своя серия, свой таймер и свой ответ.

Но есть нюанс: иногда второй участник дополняет первого, и отвечать нужно на совместную мысль. Здесь помогает не автоматическая склейка, а правило «если реплики разных авторов пришли в пределах короткого интервала и ссылаются друг на друга, собрать общий контекст, но адресовать ответ конкретному человеку». Это сложнее, и на старте честнее ограничиться раздельными пакетами с явным указанием адресата в ответе.

Если в чате есть сотрудник компании-продавца, его реплики вообще не должны попадать в пакет клиента — иначе бот начнёт «отвечать сам себе». Фильтр по автору и по роли (клиент / оператор / бот) — обязательная часть сборки, а не приятное дополнение.

Приёмочные тесты сборки на условных сериях
Приёмочные тесты сборки на условных сериях. Авторская схема 404ai.

Система отправила два ответа: как это происходит и как не допустить

Самый неприятный сценарий — дубль ответа. Причин обычно две. Первая: пакет закрылся по таймеру, ответ ушёл, а запоздавшее событие запустило обработку ещё раз. Вторая: два воркера одновременно взяли один пакет в работу, потому что статус processing не был выставлен атомарно. Обе причины решаются механикой, а не «внимательностью модели».

Первое — идемпотентность отправки: у каждого ответа есть reply_ref, и повторная отправка по тому же пакету блокируется, если ответ уже зафиксирован. Второе — блокировка пакета при взятии в работу (условная транзакция «перевести из closed в processing, только если статус всё ещё closed»). Третье — дедупликация входящих событий по идентификатору сообщения. Вместе эти три правила закрывают большинство дублей.

Отдельно стоит проверять случай, когда ответ ушёл, но клиент его не увидел (ошибка доставки). Тогда система может решить, что ответа не было, и отправить снова. Здесь помогает журнал отправок с внешним идентификатором сообщения: если мессенджер подтвердил доставку, повтор запрещён, даже если клиент молчит.

Серия коротких реплик на экране сотрудника

Оператору не нужен внутренний burst_id. Ему нужно понимать три вещи: бот сейчас собирает серию и молчит намеренно; какие реплики вошли в пакет; что бот собирается ответить и на что опирается. Поэтому в интерфейсе переписки имеет смысл показывать компактную плашку «Собираю сообщения (3)» с раскрытием списка реплик и таймером до обработки.

Когда ответ готов, но ещё не отправлен (режим подтверждения), оператор видит черновик с подсветкой, на какие реплики он отвечает. Если какая-то реплика не учтена, это заметно сразу — и это дешевле, чем ловить пропущенное отрицание в переписке с клиентом. Для пакетов с флагом order_conflict или superseded_by плашка меняет цвет и просит решения человека.

Полезно показывать и «соседние» пакеты того же клиента: если утром был один вопрос, а вечером другой, оператор видит, что это разные обращения, и не удивляется, почему бот ответил дважды. Интерфейс здесь не украшение, а способ сделать механику сборки наблюдаемой — иначе сотрудники начнут подозревать бота в произволе.

Практикум: настройка серии на условном примере
Практикум: настройка серии на условном примере. Авторская схема 404ai.

Где сборка ломается: трудные исключения

Первое исключение — срочность. Если клиент пишет «горит, ответьте сейчас», ждать полное окно нельзя. Нужен явный триггер срочности, который закрывает пакет досрочно и помечает ответ как приоритетный. Триггер лучше держать простым и проверяемым (ключевые слова, тип обращения, статус клиента), а не отдавать на откуп модели, которая «почувствует» срочность.

Второе — вложения. Клиент отправил текст, потом фото договора, потом уточнение. Пакет должен включать вложения, а обработка — уметь их учитывать или честно говорить «фото получил, разберу отдельно». Молча проигнорированное вложение — частая причина недоверия к боту.

Третье — язык и формат. Реплики могут быть на разных языках или содержать голосовые. Склейка текста и голоса в один пакет требует распознавания, а распознавание ошибается. Здесь разумно не обещать «полное понимание», а помечать пакет как требующий проверки человеком.

Четвёртое — юридические и финансовые формулировки. Если в серии клиент просит условия оплаты или ссылается на договор, ответ бота не должен превращаться в обязательство. В таких пакетах корректно передавать диалог уполномоченному сотруднику, а не генерировать условия самостоятельно. Конкретные требования стоит сверять по применимым документам компании и у ответственного за это сотрудника, а не по общим соображениям.

Как проверить сборку до запуска: тесты на сериях

Проверять сборку нужно не «на красивых диалогах», а на сериях, которые специально ломают порядок и ожидания. Ниже — набор тестов, которые можно прогнать на стенде с условными данными.

Тест Что подаём Ожидаемое поведение
Базовая серия Три реплики подряд с паузами меньше интервала Один пакет, один ответ на все три
Разрыв окна Две реплики, пауза больше порога Два пакета, два ответа
Правка первой Реплика, затем редактирование ранней Пакет помечен изменённым, ответ по актуальной версии
Перемешанный порядок События с противоречивыми метками Флаг order_conflict, передача оператору
Дубль доставки Одно и то же событие дважды Дедупликация, одна реплика в пакете
Два автора Реплики двух участников Раздельные пакеты, явный адресат
Дубль ответа Повторный запуск обработки закрытого пакета Блокировка по reply_ref
Срочность Реплика с триггером срочности Досрочное закрытие окна

Эти тесты не доказывают, что бот «умный». Они доказывают, что механика предсказуема: серия собирается, порядок сохраняется, дубли не проходят, исключения видны. Умность ответа проверяется отдельно — на качестве текста и на том, учтены ли все реплики пакета.

Полезно добавить «теневой» прогон: бот собирает пакеты и формирует черновики, но не отправляет, а оператор сравнивает черновик с тем, что ответил бы сам. Так накапливается понимание, где окно слишком короткое, а где слишком длинное, — без риска для реальных клиентов.

Практикум: настройка серии на условном примере

Возьмём условный сценарий: клиент пишет в мессенджер три реплики — «Добрый день», «Хотим подключить ИИ-продавца», «Но у нас два склада и разные номенклатуры». Наша задача — настроить сборку так, чтобы ответ учитывал все три и не терял ограничение про склады.

Шаг первый: определить автора и канал. Пакет привязан к конкретному клиенту в конкретном канале; реплики оператора и бота в него не попадают.

Шаг второй: задать окно. Мягкий интервал — условно 30 секунд, жёсткий потолок — условно 90 секунд от первой реплики. Числа берём как гипотезу и проверяем на тестах, а не как «истину».

Шаг третий: включить дедупликацию и сортировку по времени отправки с фиксацией конфликтов.

Шаг четвёртый: сформировать вход для модели — весь пакет с пометкой «ответь на все реплики, сохрани порядок, явно учти ограничения». В черновике ответа проверить, что упомянуты оба склада и разные номенклатуры.

Шаг пятый: настроить исключения — срочность, вложения, финансовые формулировки. Для финансовых формулировок — передача уполномоченному сотруднику, а не генерация условий.

Шаг шестой: прогнать таблицу тестов выше и посмотреть, где поведение расходится с ожиданием. Расхождения — не повод «подкрутить модель», а повод поправить окно, сортировку или правила исключений.

Шаг седьмой: включить режим подтверждения оператором на первую неделю. Это не про недоверие к ИИ, а про наблюдаемость: пока механика сборки не проверена на живых сериях, лучше видеть черновики, чем ловить дубли в переписке.

Согласованный момент ответа на собранный пакет

Исходная задача — не «заставить бота отвечать быстрее», а сделать так, чтобы серия коротких реплик превращалась в один связный ответ, где учтены порядок, ограничения и смена темы. Для этого нужны три вещи: явное окно сборки с мягким интервалом и жёстким потолком, рабочий объект-пакет с порядком и статусами, и правила исключений, которые не дают механике ломаться на срочности, правках и двух участниках.

Дубли ответов, потерянные отрицания и ответы на устаревшие версии — это не «ошибки модели», а следствия отсутствия сборки. Когда пакет виден оператору, а отправка идемпотентна, большинство таких ситуаций либо не возникает, либо обнаруживается до того, как клиент их заметит.

Конкретный шаг проверки: возьмите пять реальных (обезличенных) серий из своей переписки, где клиент писал по частям, и прогоните их через стенд с окном сборки и таблицей тестов. Посмотрите, на каких сериях ответ расходится с тем, что ответил бы менеджер, и почему — из-за окна, порядка, дедупликации или правил исключений. Это даст не обещание роста, а понятную карту того, что именно нужно настроить в вашем случае.

Смежный вопрос разобран отдельно: Клиент замолчал в чате: как продолжить без давления.

Источники и границы разбора

Источники и статус проверки на 9 ноября 2026. Первичные документы поясняют указанные механизмы; доступность и границы каждого источника отмечены ниже. Методические рекомендации и условные примеры составляют самостоятельную часть разбора.

  1. Дирижёр: ИИ-продавец в мессенджерах

    Опубликованное направление работы 404ai. Предлагаемая в статье методика не означает, что каждое описанное действие уже доступно без настройки; состав решения согласуется отдельно.

  2. Telegram Bot API

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

  3. Telegram Bots FAQ

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

  4. Microsoft: Asynchronous request-reply pattern

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

Частые вопросы

Почему нельзя отвечать на каждое сообщение сразу?

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

Как задать окно сборки и не заставить клиента ждать?

Окно делают двойным: мягкий интервал сбрасывается при новой реплике, жёсткий потолок ограничивает ожидание от первой реплики. Потолок закрывает пакет принудительно, даже если клиент продолжает печатать. Оговорка: конкретные значения условны, их подбирают под канал и аудиторию и проверяют на стенде, а не берут как универсальную паузу.

Что делать, если клиент отредактировал раннюю реплику?

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

Как не допустить двух ответов на одну серию?

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

Как проверить сборку до запуска на реальных клиентах?

Прогоняют серии, которые ломают порядок и ожидания: базовую серию, разрыв окна, правку первой реплики, перемешанный порядок, дубль доставки, двух авторов, дубль ответа и срочность. Ожидаемое поведение фиксируют заранее. Оговорка: тесты доказывают предсказуемость механики, а не качество текста; умность ответа проверяют отдельно на черновиках.

404ai · задача вашей компании

Обсудим вашу задачу

Расскажите, какой результат нужен вашей компании и как задача решается сейчас. Уточним исходные данные, ограничения и подходящий формат работы. Состав работ, условия и сроки согласуем после оценки.

Укажите телефон или Telegram для ответа

Не присылайте пароли, ключи и клиентские базы. Для первого обсуждения достаточно описания задачи и контакта. Доступы и обработку данных согласуем отдельно, если они понадобятся.

Заявка принята. Свяжемся, уточним задачу и согласуем следующий шаг.

Можно также написать напрямую: Telegram 404ai.

Подробнее: Диалоги · Дирижёр
Разбор задачи — бесплатноОтвет за 15 минут
Разобрать задачу