TL;DR
Агент, который уверенно проходит задачу в спокойных условиях, после сбоя посреди работы с реальными системами (платежи, CRM, база данных, Git) справляется примерно вдвое реже. Исследователи сравнили два прогона одной задачи: без сбоя и с потерянным ответом от сервиса. Главный риск — слепой повтор: агент видит ошибку и просто вызывает инструмент ещё раз. Лучше всего сработала схема «сначала проверь состояние, потом решай, повторять ли». Идемпотентные ключи (уникальная метка запроса, по которой сервис отсекает дубль) помогли только там, где сервис их поддерживает.
Боль выглядит так. Агент вызвал «списать 1 200 ₽». Сервис списал, но ответ потерялся по дороге. Агент видит «таймаут» и не знает, прошла операция или нет. Он повторяет вызов, и клиент платит дважды. Из текста ошибки это не отличить от настоящего провала. При слепом повторе дубли возникали больше чем в половине прогонов. Более сильные коммерческие модели проблему не снимали: у них доля дублей была такой же или выше.
Метод простой: перед повтором мутирующего вызова (создать, списать, отправить, изменить) нужно прочитать текущее состояние и только потом решать — повторять, дозавершать или остановиться. В статье такая проверка подняла успешное восстановление после потерянного ответа с ~43% до 75%. Для сбоев посреди операции у остальных методов было 0%, с проверкой — около четверти. Важно: в статье это механизм рантайма агента. Перенос в инструкцию — ниже, и это наша адаптация.
Схема метода
Что делать зависит от того, в какой фазе случился сбой:
ФАЗА 1: сбой ДО изменения (не дошли до сервиса)
→ повтор безопасен, дублей нет
ФАЗА 2: сбой В СЕРЕДИНЕ изменения (часть шагов выполнена)
→ слепой повтор не работает (0%) → читай состояние,
дозавершай или откатывай недостающее
ФАЗА 3: сбой ПОСЛЕ коммита, ДО ответа (самый опасный)
→ НЕ повторяй вслепую → прочитай состояние →
если эффект уже есть, считай шаг выполненным
Всё это можно уместить в одну инструкцию агенту. Проверка состояния требует у агента инструмента для чтения (read-only).
Пример применения
Задача: Вы настроили агента в Bitrix24 для службы заботы онлайн-школы. Он оформляет возврат 4 900 ₽ через ЮKassa и закрывает сделку. Платёжный API иногда отвечает таймаутом. Деньги при этом могут уйти, а ответ потеряться. Без правила агент повторит возврат, и школа вернёт деньги дважды.
Промпт (фрагмент системной инструкции):
<ПравилаСбоев>
Инструменты делятся на два типа:
- ЧТЕНИЕ (get_refund_status, get_deal, list_payments) — повторять можно.
- ИЗМЕНЕНИЕ (create_refund, update_deal, send_email) — повторять вслепую НЕЛЬЗЯ.
Если вызов ИЗМЕНЕНИЯ вернул таймаут, обрыв связи или «неизвестный результат»:
1. НЕ вызывай его повторно сразу.
2. Скажи себе: «Я не знаю, прошла операция или нет».
3. Вызови инструмент ЧТЕНИЯ и проверь: появился ли возврат 4 900 ₽
по заказу {id_заказа}?
4. Если эффект УЖЕ есть — считай шаг выполненным, иди дальше.
Если эффекта НЕТ — повтори вызов один раз, передав тот же ключ
идемпотентности: {id_заказа}-refund.
5. Если проверить состояние нечем или результат неясен — остановись
и напиши оператору: что вызывал, с какими параметрами, что неизвестно.
Если операция из нескольких шагов оборвалась посередине: сначала
перечисли, какие шаги уже видны в системе, и выполни только недостающие.
ПравилаСбоев>
Результат: При таймауте агент не будет сразу вызывать возврат снова. Он сначала запросит статус возврата и по нему решит: закрыть сделку, повторить с тем же ключом или позвать человека. В ответе оператору будет видно, что проверено и почему принято такое решение.
Почему это работает
Слабость. Из текста ошибки «timeout» не видно, дошёл ли вызов до сервиса. Ошибка не говорит, прошло ли изменение. Если в инструкции нет правила, повтор — самое «естественное» поведение, которому учат и людей-программистов, и модели.
Сильная сторона. Модель хорошо следует явному порядку действий и отличает «читать» от «менять». Если выделить класс «неизвестный результат» и привязать к нему обязательное действие, модель его выполняет.
Как метод использует это. Мы подменяем вопрос «получилось ли?» (его нельзя решить по ошибке) вопросом «что сейчас в системе?» (его можно проверить прямым чтением).
Рычаги управления: - Список инструментов — сильнее всего влияет на результат. Чем точнее вы разметили чтение и изменение, тем надёжнее правило. - Число повторов (в примере «один раз») — для необратимых операций (деньги, письма клиентам) ставьте ноль и эскалацию человеку. - Ключ идемпотентности — работает, только если сервис его поддерживает. Проверьте документацию API. - Условие остановки (шаг 5) — расширьте или сузьте в зависимости от цены ошибки.
Шаблон промпта
В статье нет готового текстового промпта: проверка состояния реализована в рантайме. Шаблон ниже — перенос принципа в инструкцию агенту.
<ПравилаСбоев>
<Инструменты>
ЧТЕНИЕ (повторять можно): {список_инструментов_чтения}
ИЗМЕНЕНИЕ (повторять вслепую нельзя): {список_инструментов_изменения}
НЕОБРАТИМЫЕ (ошибка → сразу эскалация человеку): {список_необратимых}
Инструменты>
<ЕслиВызовИзмененияВернулОшибку>
Тип ошибки «до отправки» (DNS, отказ соединения, ошибка валидации):
→ безопасно исправь параметры и повтори.
Тип ошибки «неизвестный результат» (таймаут, обрыв, нет ответа):
1. Не повторяй вызов.
2. Вызови {инструмент_проверки} и найди ожидаемый эффект: {ожидаемый_эффект}.
3. Эффект есть → шаг выполнен, продолжай.
4. Эффекта нет → повтори один раз с ключом {ключ_идемпотентности}.
5. Не удалось проверить → остановись, напиши {кому_эскалировать}.
ЕслиВызовИзмененияВернулОшибку>
<ЕслиОперацияИзНесколькихШагов>
При обрыве посередине сначала перечисли шаги, уже видимые в системе,
затем выполни только недостающие. Не начинай с начала.
ЕслиОперацияИзНесколькихШагов>
<Отчёт>
После любого сбоя кратко запиши: что вызывал, что случилось,
что проверил, что решил.
Отчёт>
ПравилаСбоев>
Подставьте: названия ваших инструментов, ожидаемый результат (например, «возврат на 4 900 ₽ по заказу») и контакт для эскалации.
🚀 Быстрый старт — вставь в чат:
Вот шаблон правил обработки сбоев для агента. Адаптируй под мою задачу: [опиши, что делает твой агент и с какими системами работает].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какие у агента есть инструменты, какие из них меняют данные и чем можно проверить результат. Это нужно, потому что весь метод держится на разметке «чтение / изменение / необратимое» и на том, чем именно агент проверит состояние. Модель возьмёт структуру из шаблона и заполнит под вашу систему.
Ограничения
⚠️ Нужен инструмент чтения: если агент не может проверить состояние (нет read-only доступа к платёжной системе, CRM, базе), метод не сработает. Тогда остаются эскалация человеку или идемпотентные ключи.
⚠️ Идемпотентность — не волшебство: ключи защищают только там, где сервис их принимает. На остальных эндпоинтах агент делал дубли почти в каждом прогоне. Отправили ключ ≠ защитились.
⚠️ Сбой посреди операции остаётся тяжёлым: даже с проверкой состояния восстановление было только у четверти прогонов. Остальные методы не справлялись совсем. Для многошаговых изменений нужны откат и человек в петле.
⚠️ Проверена идея, не формулировка: в статье проверка состояния реализована в рантайме, а не текстом в промпте. Работает ли ваша инструкция так же надёжно — проверяйте на своих сценариях.
⚠️ Среда симулированная: задач немного, доверительные интервалы широкие, а выигрыш идемпотентности статистически не подтверждён. Берите как направление, не как точный прогноз. Также неполная часть текста: часть разделов с описанием Verify-Retry нам недоступна.
Как исследовали
Идея была простой: сравнить два прогона одной и той же задачи, с одинаковым «зерном» случайности. В первом сбоев нет, во втором ответ от сервиса теряется уже после того, как операция выполнена. Так отделяется «агент не справился с задачей» от «агент справился, но не пережил сбой». Это и называется условная доля успешного восстановления (CRSR): считаются только те случаи, где в спокойном прогоне агент задачу решил.
Собрали 36 рабочих процессов из 8 областей: облако, CRM, база данных, Git, мессенджеры, платежи, хранилище, тикеты. Главный эксперимент идёт на 12 отложенных процессах: две открытые модели Llama, два рантайма (прямой вызов и LangGraph), три способа восстановления, 20 прогонов. Всего 2 880 парных запусков. Отдельные «судьи» смотрели и на состояние среды, и на реальные вызовы по сети, то есть были ли двойные списания.
Результаты. В спокойных условиях агенты справлялись в ~84% случаев. С потерянным ответом успешное восстановление падало до ~47%, а при слепом повторе дубли возникали в 53% прогонов. Идемпотентные ключи дали +11 п.п., но весь выигрыш пришёл с трёх эндпоинтов, где сервис ключи реально поддерживал. Журнал мутаций на стороне агента без права проверить сервер оказался почти равен наивному повтору. Удивило, что LangGraph и прямой вызов дали практически одинаковые результаты: сложный рантайм не спасает.
Потом повторили на коммерческих моделях: разрыв остался, восстановление ~21%, дубли в половине и более прогонов. Более «умная» модель риск не снимает. Наконец сравнили три фазы на четырёх составных процессах. До изменения все методы ≈77%. Во время изменения почти все давали 0%, и только проверка состояния перед повтором (Verify-Retry) вытянула ~26%. После коммита, но до ответа проверка дала ~75% против 43–46% у остальных. Вывод для практики: лечить надо по фазе сбоя, универсального «повторить и надеяться» нет.
Адаптации и экстраполяции
🔧 Техника: убрать «одно общее правило» → разметить инструменты по обратимости
В статье инструменты делятся на обратимые, компенсируемые и необратимые. В CLAUDE.md или системной инструкции можно добавить разметку:
ОБРАТИМЫЕ (можно откатить): создание черновика, смена тега
КОМПЕНСИРУЕМЫЕ (можно исправить встречной операцией): возврат платежа, отмена заказа
НЕОБРАТИМЫЕ (одна ошибка = ущерб): отправка письма клиенту, перевод денег
Для необратимых: при любой неопределённости — стоп и вопрос человеку.
Экстраполяция: аудит собственного агента промптом. Это наша идея, в статье такого нет. Вставьте описание ваших инструментов в чат и попросите найти слабые места:
Вот список инструментов моего агента: {список с описаниями}.
Для каждого определи: меняет ли он данные во внешней системе, есть ли способ
проверить результат, поддерживает ли он ключ идемпотентности.
Затем смоделируй: «вызов выполнен, ответ потерян».
Покажи, где агент сделает дубль, и предложи правила для инструкции.
Ресурсы
- UndoBench: Separating Task Competence from Recovery Capability in Tool-Using AI Agents
- Авторы: Dolly Sah, Tanmay Sah, Harshul Jain, Tanya Sah (независимые исследователи)
- Код: github.com/tradertanmay/undobench
- Упомянутые отсылки: Reflexion (Shinn et al., 2023), Sagas (Garcia-Molina & Salem, 1987), Helland (2012) об идемпотентности, SWE-bench, ToolBench, AgentBench, WebArena
