В понедельник в десять утра основателю сервиса позвонил клиент. Не написал в поддержку, а именно позвонил, потому что был зол. Накануне ему пришло письмо о том, что его подписка прекращается тридцатого числа. Он её не отменял. В субботу он отправил в поддержку короткое письмо: карта не проходит, помогите разобраться, отмените, пожалуйста, это списание и подскажите, как заплатить с другой карты.
К обеду выяснилось, что таких клиентов сорок. Все написали в выходные. Со всеми произошло одно и то же.
Никто в компании ничего плохого не сделал. Разбор входящих обращений отдали ИИ-агенту месяцем раньше, он работал, поддержка была довольна, ручной работы стало вдвое меньше. Ошибся ровно один шаг. Всё остальное отработало именно так, как его и просили работать: само, быстро и без человека.
Один неверный ярлык и пять систем, которые его повторили
Вот что произошло с письмом за первые полторы минуты после его получения.
-
Разбор письма. Шаг прочитал текст и определил тип обращения. В письме было слово «отмените», рядом стояло слово «списание», и весь смысл держался на этом соседстве. Агент выбрал тип «отказ от услуги». Одно слово перевесило целый абзац.
-
Приоритет. Отказ от услуги в этой компании не считается срочным, потому что клиент уже принял решение и торопить его незачем. Обращение получило обычный приоритет и ушло в очередь, где по выходным никого нет.
-
Задача в трекере. Заголовок «оформить прекращение подписки», исполнителем указан сам агент, потому что операция считается типовой и полностью автоматической.
-
Письмо клиенту. Шаблон подтверждения. «Мы приняли вашу заявку, подписка будет действовать до тридцатого числа». Вежливо, грамотно, мгновенно.
-
Отметка в биллинге. Подписка помечена как непродлеваемая, дата окончания проставлена, следующее списание отменено.
Дальше подключилась система, которую в этой истории вообще никто не вспоминал. Ночная выгрузка увидела в биллинге непродлеваемую подписку и перенесла сделку в CRM в статус «потерян». Менеджер, который обычно звонит таким клиентам, в понедельник их уже не увидел. А рассылка убрала сорок человек из писем для действующих клиентов и поставила в цепочку «возвращение ушедших», где первое письмо начинается со слов «мы заметили, что вы больше с нами не работаете».
Пять систем. В каждой из них действие было правильным. Каждая работала ровно по своему правилу. Ошибка была одна, в самом первом шаге, и после неё все остальные шаги отработали безупречно, просто исходя из неверного факта.
Вот главное, что стоит унести из этой истории. В цепочке из нескольких шагов результат предыдущего шага становится доверенным входом следующего. Поэтому считать риск по каждому вызову отдельно бессмысленно. Считать надо по всей цепочке.
Простая арифметика делает это наглядным. Допустим, каждый шаг ошибается в пяти случаях из ста. По отдельности это отличный результат, с таким шагом можно жить. Но пять таких шагов подряд дают цепочку, в которой примерно каждый четвёртый запуск содержит хотя бы одну ошибку. Шаги надёжные, цепочка ненадёжная.
Почему второй шаг не спорит с первым
Когда первый шаг читал письмо, сомнение у него было. Текст неоднозначный, слова противоречат друг другу, уверенность невысокая. Но наружу вышло не сомнение, а готовый ответ: тип обращения «отказ от услуги». Одно чистое слово в одном поле.
Второй шаг видит только это поле. Он не видит письма. У него нет ни текста клиента, ни оценки уверенности, ни повода усомниться. Даже если бы он увидел письмо, у него нет на это полномочий: его работа состоит в том, чтобы поставить приоритет по типу, а тип ему уже сообщили.
Сомнение живёт только там, где оно возникло. Дальше по цепочке идёт факт.
Это самая частая ошибка, которую я вижу в такой автоматизации, и она не в коде. Она в допущении, что раз предыдущий шаг отработал без сбоя, значит, он отработал правильно. Отсутствие ошибки и правильность это разные вещи. Первый шаг не упал, не вернул исключение, не превысил время ожидания. Он уверенно выдал неправильный ответ, и по всем техническим признакам это был успех.
Что с этим делать практически. Через цепочку надо тащить не только вывод, но и то, насколько он надёжен, и исходный текст, из которого он получен. Шаг, который делает что-то необратимое, обязан смотреть не на ярлык, а на источник. Дороже это ровно на одно поле в данных, которые и так ходят между шагами.
Сколько шагов и сколько попыток мы разрешаем
У длинной цепочки должен быть конец, назначенный заранее. Иначе она его придумает сама.
В другом продукте я разбирал случай, где агент не нашёл карточку клиента по номеру договора. Вместо того чтобы остановиться, он начал искать по фамилии, нашёл трёх однофамильцев, попытался уточнить по городу, не уточнил, решил создать новую карточку, потом попытался связать её со старым договором. Двадцать шагов на пустом месте, и каждый следующий опирался на всё более шаткое основание. Предел в восемь шагов превратил бы это в честную остановку и строку «не смог определить клиента».
Второй предел касается повторов. Когда шаг не срабатывает, естественное поведение это попробовать ещё раз. В одной компании агент упёрся в чужой складской сервис, который отвечал ошибкой, и повторял запрос каждые две секунды почти час. Сервис заблокировал ключ доступа компании. Вместе с ключом встали обычные заказы, к ИИ не имевшие никакого отношения.
Повтор без предела это не надёжность. Это усилитель. Он берёт одну неудачу и превращает её в тысячу обращений.
И есть отдельное правило, о котором забывают: повторять можно спокойно только тот шаг, который ничего не изменил снаружи. Если шаг мог уже что-то сделать, повтор требует механизма из следующего раздела. Без него повтор просто делает то же самое второй раз.
Система обязана узнавать уже сделанное
Представьте кассу в магазине, где вы дважды приложили карту, потому что первый раз терминал задумался. Хорошая касса понимает, что это одна и та же покупка, и не списывает деньги второй раз. Плохая списывает дважды, а вы идёте разбираться.
С автоматизацией ровно так же. Каждое действие должно нести на себе метку того, к какому случаю и к какому шагу оно относится. Номер обращения плюс название шага, этого достаточно. Перед тем как что-то делать, система смотрит в свой журнал и спрашивает: для этого обращения этот шаг уже выполнялся? Если да, она не делает ничего и возвращает прежний результат.
Без этого получается история, которую я видел своими глазами. Почтовый шлюз отвечал слишком долго, агент считал попытку неудачной и повторял. Клиент получил шесть одинаковых подтверждений подряд и решил, что с него шесть раз списали деньги. Поддержка потом разбирала уже не одну проблему, а две.
Честная оговорка. Метка работает надёжно, когда её понимает и та сторона, которая выполняет действие. Не все чужие сервисы это умеют. Тогда журнал придётся вести у себя и относиться к записи «уже отправлено» как к факту, даже если подтверждения от чужой стороны вы не получили. Это менее приятно и более правильно, чем отправить второй раз.
Проверить факт заново прямо перед необратимым шагом
В нашей истории всё держалось на одном факте: клиент хочет уйти. Этот факт установили на первом шаге и больше не трогали.
Проверять его надо было не там. Проверять надо прямо перед необратимым действием, то есть перед письмом клиенту и перед отметкой в биллинге. Между началом цепочки и её концом проходит время. За это время факт может устареть, а может оказаться, что он и не был верным, просто никто не смотрел.
Важное уточнение про слово «независимая». Спросить ту же модель «ты уверен?» это не перепроверка, это второй голос того же человека. Независимость означает другой источник. Перечитать исходное письмо отдельным правилом. Заглянуть в биллинг и увидеть там неоплаченный счёт, выставленный три дня назад. Спросить человека.
В этом случае хватило бы очень глупой проверки, написанной обычными правилами без всякого ИИ: если клиент числится уходящим, но за последние трое суток у него появился неоплаченный счёт и он писал в поддержку, значит, что-то не сходится. Уходящие клиенты редко спрашивают, как заплатить. Противоречие обнаружено, цепочка остановлена, обращение уходит человеку.
Такая проверка стоит копейки и не должна быть умной. Она должна быть независимой.
Что можно отменить, а что придётся разгребать людям
У каждого шага, который меняет что-то за пределами вашей системы, должно быть парное действие отмены. Написанное тогда же, когда и сам шаг, а не отложенное на потом.
Посмотрим, что реально удалось откатить в нашей истории. Задачу в трекере закрыли за полминуты. Приоритет вернули. Отметку в биллинге сняли, подписки продлились. Сделки в CRM вернули в работу руками, это заняло у менеджера полдня. Рассылку остановили.
А письма вернуть нельзя. Сорок человек уже прочитали, что их отключают. Часть из них потратила выходные на то, чтобы посмотреть на конкурентов. Двое успели написать, что заодно хотят вернуть деньги за предыдущий месяц. Эту часть разгребали люди, голосом, извиняясь, и никакая кнопка отмены здесь не помогла бы.
Поэтому я не стану утверждать, что отмену можно построить для любого действия в любой внешней системе. Это неправда. Отправленное письмо, переведённые деньги, сообщение в чужом чате, переданные подрядчику данные, поданный в государственный сервис документ необратимы по своей природе. Это не то, что решается позже, при доработке. Это меняет сам проект: такие шаги получают либо подтверждение человеком, либо окно задержки.
Окно задержки это самая дешёвая страховка, которую я знаю. Письма уходят не мгновенно, а через десять минут. Отмена, сработавшая в эти десять минут, ловит письмо в очереди, и клиент никогда не узнаёт, что произошло. Десять минут задержки стоят компании ничего. Сорок писем стоили ей двух потерянных клиентов и недели неприятных разговоров.
Где в этой цепочке стоят остановки
Вот как выглядит та же цепочка, если смотреть на неё как на набор мест, где можно остановиться.
| Шаг цепочки | Чем он опасен | Где ставим остановку |
|---|---|---|
| Разбор обращения | Ярлык уходит дальше как факт | Низкая уверенность ведёт к человеку |
| Приоритет и очередь | Ошибка становится порядком работы | Сверка с исходным текстом |
| Задача исполнителю | У действия появляется автор | Парное действие отмены и срок |
| Письмо клиенту | Вернуть нельзя, оно прочитано | Задержка отправки и проверка факта |
| Изменение в чужой системе | Последствия уже вне вашего контроля | Подтверждение человеком |
Кроме точечных остановок нужна одна общая. Цепочка должна следить за собой и останавливаться целиком, когда доля неудач или доля ручных исправлений резко вырастает.
В нашей истории признак появился в субботу утром. Обращений с типом «отказ от услуги» обычно бывает четыре за неделю. За выходные их стало сорок. Десятикратный скачок за сутки это не статистика, это авария, и её было видно за много часов до понедельника. Просто на это число никто не смотрел, потому что никто не договорился, что на него надо смотреть.
Отдельно про сигнал. В той компании автоматическая остановка формально существовала. Она писала в командный чат, отключённый от уведомлений ещё в июне. Сигнал, у которого нет имени конкретного человека и способа до него дозвониться, сигналом не является.
Здесь же лежит честный компромисс. Длинная самостоятельная цепочка удобна: она быстрая, дешёвая и не отвлекает людей. Частые контрольные точки медленнее и раздражают команду, зато такую цепочку можно остановить. Выбирать между ними по ощущениям не надо, есть простое правило. Контрольная точка ставится там, где действие выходит за пределы вашей системы или где его нельзя отменить. Внутри собственной базы данных можно быть щедрым на самостоятельность.
Нарисуйте самую длинную цепочку в четыре колонки
Возьмите одну цепочку. Не самую новую, а самую длинную из работающих.
Попросите команду нарисовать её на одном листе, в четыре колонки.
- Шаг.
- Что он меняет за пределами системы.
- Что это отменяет.
- Как мы узнаём, что он ошибся.
Одна страница, без схем и без архитектурных терминов. Если лист не помещается на одну страницу, вы уже узнали кое-что важное о своей автоматизации.
Потом отметьте на этом листе первый шаг, который выходит наружу. Всё, что до него, исправляется дёшево и незаметно. Всё, что после, исправляется временем людей и доверием клиентов.
Почти всегда лист отвечает сам. В колонке отмены оказываются две или три пустые клетки, и до этого момента никто в команде не произносил вслух, что они пустые.
А дальше стоит задать себе неприятный вопрос. Если завтра первый шаг этой цепочки ошибётся, сколько систем успеют повторить его ошибку до того, как её заметит живой человек, и как зовут этого человека?
Разберём вашу ситуацию
Опишите свою ситуацию. Обсудим подход, необходимый объём участия и следующий шаг.
Разобрать мой проект