КейсыРастИИшка
Внедрение ИИ

Отмена долгой задачи ИИ-агента: остановить ожидание и проверить действия

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

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

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

Пользователь нажимает «Отменить» на карточке поручения, интерфейс мгновенно гасит спиннер, а через сорок минут в CRM появляется новый контакт, которого никто не просил создавать. Это условная сцена, но она точно описывает разрыв, с которым сталкиваются команды, отдавшие ИИ-агенту длинную цепочку действий. Кнопка отмены управляет ожиданием на экране, а не миром по ту сторону интерфейса.

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

Общий маршрут отмены поручения агента
Общий маршрут отмены поручения агента. Авторская схема 404ai.

Почему «Отменить» на экране не отменяет запрос в чужом сервисе

Классическая ошибка проектирования — считать, что отмена задачи и отмена HTTP-запроса это одно и то же. Когда браузер или серверный клиент обрывает соединение через AbortController, он перестаёт ждать ответ. Согласно документации MDN по AbortController, сигнал отмены лишь сообщает запросу, что результат больше не нужен; он не гарантирует, что удалённая сторона прекратила обработку. Сервер мог уже принять данные, записать строку в базу или поставить сообщение в очередь.

Для ИИ-агента это критично, потому что его шаги часто идут во внешние системы: CRM, календарь, почтовый шлюз, платёжный сервис, мессенджер. Прекращение ожидания ответа от такого сервиса не откатывает побочное действие. Более того, асинхронные сценарии по своей природе предполагают, что клиент отвязывается от результата и забирает его позже — об этом прямо говорит шаблон Asynchronous request-reply в документации Microsoft. Если агент построен на такой схеме, «отмена» на клиенте вообще не адресована исполнителю.

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

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

Карточка поручения как рабочий объект, а не лог чата

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

Форма рабочего объекта, который стоит завести, выглядит примерно так (все поля условные, это иллюстрация структуры, а не готовый продукт):

Поле Что хранит Зачем нужно при отмене
job_id Устойчивый идентификатор поручения Связывает экран, журнал и внешние вызовы
step_id Идентификатор шага внутри поручения Позволяет отменять не всё, а конкретный шаг
step_state planned / started / done / unknown / compensated Отделяет «не начали» от «не знаем, что вышло»
idempotency_key Ключ для повторного вызова Защищает от дублей при повторном поручении
external_ref Идентификатор объекта в чужой системе Нужен, чтобы откатить или найти созданное
cancel_requested_at Момент запроса отмены Отделяет отмену от факта остановки
cancel_confirmed_at Момент подтверждения остановки Доказывает, что исполнитель реально встал

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

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

Точки отмены: где агент реально может остановиться

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

  • До старта шага. Шаг ещё в очереди, ничего не отправлено. Отмена здесь дешёвая и полная: шаг просто снимается с плана.
  • Между шагами. Предыдущий шаг завершён, следующий не начат. Отмена останавливает цепочку, но уже сделанное остаётся.
  • Внутри шага, до внешнего вызова. Агент прочитал данные, готовится писать. Отмена безопасна, если внешний вызов ещё не ушёл.
  • Внутри шага, после внешнего вызова. Самый опасный участок. Запрос ушёл, ответа нет или он потерялся. Здесь отмена превращается в вопрос «а что там на самом деле произошло».
  • После записи, до подтверждения. Действие совершено, но система ещё не зафиксировала результат. Это зона unknown.

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

Два эпизода: когда отмена сработала и когда сделала хуже

Эпизод первый, условный. Менеджер отдела продаж поручает агенту «подготовить подборку по десяти контактам и разослать приглашения на вебинар». Агент начинает с чтения карточек, формирует список, затем по одному отправляет письма. На третьем письме менеджер понимает, что выбрал не тот сегмент, и жмёт «Отменить». Здесь всё зависит от того, как устроены точки отмены. Если между отправками есть проверка сигнала отмены, агент останавливается после третьего письма, а карточка показывает: два письма ушли, третье в состоянии unknown (ушло или нет — надо проверить), остальные сняты с плана. Менеджер получает список того, что реально произошло, и решает, писать ли извинения двум адресатам. Отмена сработала не потому, что была волшебной, а потому что шаги были разбиты и состояние каждого фиксировалось.

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

Разница между эпизодами не в кнопке, а в гранулярности шагов и в том, признаёт ли система состояние unknown. В первом случае отмена дала проверяемый результат, во втором — ложное чувство завершённости.

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

Исход «неизвестно»: как с ним жить, а не прятать

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

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

Второй инструмент — сверка по external_ref. Если агент записал объект во внешнюю систему и сохранил её идентификатор, при разборе unknown можно пойти и посмотреть, существует ли объект. Это не отменяет действие, но превращает неизвестность в факт, с которым можно работать.

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

Компенсация требует согласования, а не молчаливого отката

Соблазн сделать «отмену» умной и автоматически откатывать всё, что успели, понятен, но опасен. Откат записи в CRM может стереть данные, которые кто-то уже использовал. Обратное письмо может уйти клиенту. Удаление созданной сущности может нарушить связи, на которые ссылаются другие объекты.

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

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

Отмена поручения агента на экране сотрудника

Экран отмены решает одну задачу — не дать человеку обмануться. Хороший интерфейс здесь скучный и конкретный.

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

Чего не должно быть: анимации, которая гаснет раньше, чем пришло подтверждение; слова «готово» рядом с незавершённым шагом; автоматического закрытия карточки после нажатия отмены. Карточка живёт, пока есть шаги в состоянии started или unknown.

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

Журнал и след: чем доказывать, что отмена произошла

Спор «я же нажал отмену» решается журналом. В нём фиксируются: момент запроса отмены, момент, когда исполнитель увидел сигнал, момент подтверждения остановки, а также все внешние вызовы с их идентификаторами и ответами. Журнал должен быть доступен не только инженеру, но и тому, кто разбирает последствия.

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

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

Тесты отмены: проверять не кнопку, а последствия

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

Сценарий Что проверяем Ожидаемый результат
Отмена до старта Шаг не ушёл во внешнюю систему Нет внешних вызовов, состояние cancelled
Отмена между шагами Цепочка остановилась, сделанное сохранено Выполненные шаги в done, следующие сняты
Отмена во время чтения Ожидание прервано, чтение не пишет Нет записи, состояние шага cancelled
Отмена после записи Запись состоялась, откат не автоматический Состояние done, компенсация предложена отдельно
Потеря ответа Исход неизвестен Состояние unknown, есть external_ref для сверки
Повторное поручение Нет дублей Повтор с тем же ключом не создаёт второй объект
Компенсация без согласования Откат не выполняется молча Требуется подтверждение уполномоченного сотрудника

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

Практикум: поручение на пять шагов
Практикум: поручение на пять шагов. Авторская схема 404ai.

Практикум: разбор одного поручения на пять шагов

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

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

Затем решите, что происходит при отмене на каждом участке. На чтении — стоп без последствий. На записи — стоп с пометкой «создано N задач, откатить?». На уведомлениях — стоп с честным «отправлено M, отменить нельзя». На отчёте — просто стоп.

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

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

Что остаётся за рамками и почему это нормально

Не всякую отмену можно довести до полного отката, и это не повод отказываться от честного интерфейса. Отправленное письмо не вернуть, созданную сделку можно только пометить, а иногда и вовсе нельзя. Задача системы — не притворяться всемогущей, а точно показать, где остановка возможна, где она частична, а где уже поздно.

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

Проверка на практике: отмена поручения агента

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

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

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

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

  1. Внедрение ИИ

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

  2. MDN: AbortController

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

  3. Microsoft: Asynchronous request-reply pattern

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

  4. Microsoft: Circuit Breaker pattern

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

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

Почему обрыв HTTP-запроса не отменяет действие во внешней системе?

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

Что должно хранить поручение агента, чтобы отмена была проверяемой?

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

Что делать, если запрос ушёл, а ответ не вернулся?

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

Почему компенсацию нельзя делать молчаливым автоматическим откатом?

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

Как проверить отмену поручения агента на тестах?

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

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

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

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

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

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

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

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

Подробнее: Внедрение ИИ
Разбор задачи — бесплатноОтвет за 15 минут
Разобрать задачу