Повторные попытки ИИ-агента: где продолжать
Повторные попытки ИИ-агента требуют чётких границ. На коде Norman проверяем восстановление запроса к модели с сохранением результатов предыдущих действий.
- Категория
- Общее
- Обновлено
- Автор
- Stan Kharlap
Агент сохранил документ, перешёл к следующей части задачи и потерял соединение. Кажется, достаточно запустить задачу заново. Но вместе с ней может повториться и операция, которая уже завершилась успешно.
Моё правило: повторять минимальную часть работы, последствия которой мы можем проследить. Иногда это незавершённый запрос к модели. Иногда это операция инструмента с устойчивым идентификатором. Иногда правильный следующий шаг заключается в проверке того, что уже произошло. Задержка перед повторной попыткой не принимает это решение за нас.
Вопрос становится практическим по мере того, как платформы агентов берут на себя управление исполнением. Salesforce 11 сентября представила архитектуру Enterprise AI Harness с общими средствами управления действиями и их ограничениями. Препринт READY, поданный 2 сентября, отделяет результат бенчмарка от пригодности к конкретному внедрению. Ни то ни другое не доказывает, что любого остановившегося агента можно безопасно запустить заново. Для восстановления нужны собственные правила и проверки.
Почему HTTP 200 не означает, что агент закончил работу?
Успешный HTTP-статус говорит об успешном начале потокового ответа. Он не гарантирует, что приложение получило законченный результат. Соединение может закрыться после первого события. Поток также может закончиться без события завершения, которого ожидает исполнитель агента.
Возникает неочевидный сбой: транспорт отработал штатно, но у агента нет полного результата для продолжения. Обработчик, который ловит только сетевые исключения, пропустит эту ситуацию. Отсутствие исключения даёт меньше оснований для вывода об успехе, чем получение ожидаемого финального события.
Поэтому завершение нужно определить на уровне протокола. Следует отслеживать, пришло ли обязательное событие успешного окончания. Если поток закрылся раньше, генерация остаётся незавершённой. Явное сообщение о неуспешном завершении представляет собой другой случай и должно сохранить свой смысл. Нельзя объявлять любой неуспех временным сетевым сбоем только потому, что так проще разрешить повторную попытку.
Что повторять: запрос к модели или всего агента?
Это разные операции. Один запуск агента может включать несколько обращений к модели и уже выполненные действия инструментов. Возврат к исходной инструкции способен снова поставить эти действия на исполнение. Повтор текущего запроса к модели позволяет оставить прежние результаты инструментов в его входных данных.
Но такая граница работает только при известном порядке вызова инструментов. Для обычных функций, которые мы использовали в проверке, исполнитель вызывает инструмент после получения полного ответа модели. Пока поступают аргументы, действие ещё не выполняется. Незаконченный проект вызова отличается от исполненной операции. Другой исполнитель или инструмент, который запускается внутри внешнего сервиса, может иметь другие правила.
В прежней статье о потоковом ответе AI-агента мы рассматривали консервативный запрет на повтор всего запуска. Здесь вопрос уже: можно ли восстановить только незавершённую генерацию, если предыдущая генерация успела привести к полезным действиям инструментов?
Что показала проверка восстановления в Norman?
Мы проверили обёртку ассистента Norman с настоящим исполнителем агента и искусственными инструментами. Тестовая задача сохраняет вымышленный документ, затем связывает его с другим объектом. Эти операции лишь добавляют отметки в локальный список. Они не создают бухгалтерские записи. Генерация прерывалась как до начала этих действий, так и после появления результата сохранения.
Прежняя обёртка не обнаруживала штатное окончание потока без финального события. В текущей реализации допустимая незавершённая генерация получает ограниченную повторную попытку с теми же входными данными. При прерывании на более позднем этапе во входе остаётся результат предыдущего инструмента. Тест доходит до финального ответа с ожидаемой последовательностью сохранения и связывания. Ранее созданная отметка не появляется повторно.
Мы также пропустили искусственный поток HTTP 200 через настоящий декодер HTTP/SSE и исполнитель. Отсутствие завершения было обнаружено, а следующая допустимая попытка восстановила генерацию. Это существенная часть проверки: подставной итератор сам по себе не показывает, что именно декодер передаёт обёртке.
| Локальный сценарий | Что установлено проверкой | Что не установлено |
|---|---|---|
| Пустой поток с успешным HTTP-статусом | Отсутствие завершения запускает проверку возможности восстановления | Частота такого сбоя в продакшене |
| Прерывание после прежнего действия инструмента | Текущая генерация повторяется с сохранением прежнего входа | Восстановление после потери рабочего процесса |
| Частично сформированный вызов функции | Незавершённый проект вызова не исполняется этим раннером | Безопасность любых инструментов внешнего сервиса |
| Пользователь уже видит начало ответа | Обёртка запрещает новый запуск генерации | Качество отображения частичного текста клиентом |
| Поток снова завершается преждевременно | Бюджет повторов исчерпывается без финального ответа | Будущий успех недоступного сервиса |
Это воспроизведение регрессии на коде Norman, а не бенчмарк надёжности продакшена. Мы не обращались к живым моделям и не запрашивали клиентскую базу данных. Полезный результат здесь заключается в проверенной границе, а не в проценте для рекламной страницы.
Какие события должны запрещать автоматический повтор?
Пустой поток и наполовину показанный ответ не взаимозаменяемы. Начало генерации с нуля может продублировать текст, запутать следующие компоненты или противоречить словам, которые пользователь уже прочитал. Само завершение тоже закрывает возможность перезапуска: последующий транспортный сбой не превращает готовый ответ в разрешение сгенерировать его ещё раз.
Действия внутри внешнего сервиса образуют отдельную границу. Приложение может видеть их последствия хуже, чем последствия собственных функций. В проверенной обёртке активность таких инструментов и неизвестные типы событий обрабатываются консервативно. Они не считаются безвредными просто потому, что локальная функция ещё не запускалась.
Отмена тоже должна оставаться отменой. Пользователь, который остановил работу, не просил механизм повторов продолжать её. Локальные проверки включают отмену и истечение срока запроса во время ожидания перед новой попыткой. Бюджет повторов должен помещаться в исходный бюджет исполнения. Он не должен незаметно выдавать задаче новый срок жизни при каждом сбое.
Значит ли это, что агент переживёт перезапуск процесса?
Нет. Сохранение прежнего результата инструмента внутри работающего процесса не доказывает восстановление после падения этого процесса. Для устойчивого возобновления нужны сохранённый прогресс и связь между ним и выполненными операциями. Статья об управлении исполнением агента описывает более широкий контекст. Наше воспроизведение проверяет лишь один его участок.
В документации агентов Apache Airflow проведено полезное различие: сохранённый результат можно использовать повторно, но если инструмент изменил внешнее состояние до записи результата, новая попытка может повторить изменение.
В такой ситуации «нет сохранённого результата» описывает наши записи. Это не доказательство отсутствия действия. Где возможно, нужны идентификатор операции, устранение дублей на стороне получателя или проверка фактического результата в системе, которая им владеет. Если выяснить результат нельзя, неопределённость следует сохранить. Исправление локального повтора потока не гарантирует однократное исполнение во всех внешних системах.
Что записывать в отчёт о повторной попытке?
Фраза «повтор завершился успешно» скрывает главное решение. Отчёт должен показать, какая часть работы была повторена, почему это разрешалось, какие предыдущие результаты сохранились и как проверялось итоговое состояние. Успешное завершение следует отличать от остановленной попытки и от невыясненного результата внешнего действия.
Ниже иллюстративная структура отчёта. Это не API Norman и не готовая к запуску конфигурация:
{
"retry_scope": "current_generation",
"completion_event": "missing",
"earlier_tool_results": "retained",
"restart_boundary": "still_open",
"verification": "synthetic_effect_sequence_checked"
}
Нужно также назвать границы проверки. Использовались настоящий декодер, настоящий исполнитель, постоянное хранилище или только имитация инструмента? Были ли сетевые соединения отключены? Какую ревизию проверяли? Здесь применима мысль из нашего разбора доказательств обучения агента: зарегистрированное событие подтверждает определённый вывод, а не любые желательные свойства всей системы.
Как проверять повторы AI-агента, не скрывая неудачи?
Размещайте сбои по обе стороны границы, которую обещаете защитить. Завершите поток до финального события, прервите позднюю генерацию после результата предыдущего инструмента и проверьте точную последовательность искусственных последствий. Затем проверьте случаи запрета: видимый текст, готовый результат, работу внешнего инструмента, явно неуспешное завершение и отмену.
Оставьте сценарий, в котором сбой переживает весь бюджет повторных попыток. Иначе тесты могут поощрять механизм, который бесконечно пробует снова и никогда не признаёт, что застрял. Сравните результат с прежней реализацией, чтобы убедиться: сценарий действительно различает поведение до и после изменения.
Наконец, назовите непроверенные области отказа. Наш тест не охватывает потерю рабочего процесса, неопределённый результат внешней записи и все способы отображения ответа. Для этого нужны другие сценарии. Я предпочту выпустить правило восстановления с точной границей, чем назвать любого прерванного агента восстанавливаемым. Эта граница подсказывает следующему инженеру, какие доказательства ещё предстоит получить.
Частые вопросы
- Когда можно безопасно повторить запуск ИИ-агента?
- Повторять можно только ту часть работы, для которой известны прежние последствия и состояние завершения. Незаконченный запрос к модели иногда допустимо повторить с результатами предыдущих инструментов во входе. Это не разрешает перезапуск всей задачи. Видимый ответ, завершённые действия, отмена и неопределённый результат внешней операции требуют отдельной обработки.
- Может ли агент остаться незавершённым после HTTP 200?
- Да. Потоковое соединение может успешно начаться и закончиться без обязательного события завершения, которое ожидает исполнитель. Его отсутствие нужно обнаруживать явно, а не полагаться только на транспортные исключения. Отдельно обрабатывайте явное неуспешное окончание и неожиданный конец потока. Повторная попытка должна укладываться в исходный срок исполнения запроса.
- Доказывает ли успешный повтор устойчивое восстановление задачи?
- Нет. Восстановление внутри работающего процесса не доказывает возобновление после его потери. Для этого нужны сохранённый прогресс и надёжная связь с завершёнными операциями. Внешнее действие также может произойти до записи результата. Проверяйте фактический исход или используйте подходящее устранение дублей. Отсутствие записи само по себе не доказывает отсутствия действия.
Norman берет операционную финансовую работу на себя
От invoicing до bookkeeping: Norman организует повторяющиеся финансовые процессы так, чтобы вы успевали к дедлайнам с меньшим объемом ручной работы.