Журнал · Rit.work

Гарантию «ровно один раз» для LLM-агента должен обеспечивать API

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

Rit.work
Студия разработки
25 сентября 2026 г.3 мин чтения

Материал подготовлен автоматически по первоисточникам: ссылки на них — в конце статьи.

Гарантию «ровно один раз» нельзя надёжно переложить на LLM: при неясном исходе записи её должен обеспечивать API инструмента. К такому выводу пришёл Jiapeng Li из Microsoft в препринте, где числа получил сам автор и рецензирования ещё не было: с ключами идемпотентности, то есть стабильными идентификаторами операции, доля дублей снизилась с 28% до 4%. Для архитектуры агента это означает, что замена модели не исправит API, в котором повторный вызов снова списывает деньги, отправляет письмо или запускает развёртывание.

Как LIMBO отделяет ошибку модели от ошибки контракта

Автор создал LIMBO — детерминированную песочницу, где агент работает с платежами, почтой, публикациями, заявками, базой данных и развёртываниями. Эксперимент охватил 25 930 эпизодов, девять моделей и три промышленные агентские обвязки; обвязкой здесь называется программа между моделью и инструментами.

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

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

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

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

Модель справляется только с наблюдаемыми сбоями

Когда сервис выполнил запись, но потерял подтверждение, наиболее сильные модели с явной инструкцией действовать ровно один раз создавали дубли в 0,5% эпизодов. Они читали состояние сервиса, находили результат и пропускали повторный вызов. На таких сбоях выбор модели действительно влияет на надёжность.

При позднем выполнении исходного запроса те же модели дублировали операцию в 56% случаев. При повторной доставке запроса транспортом доля выросла до 74%. Модель не может рассуждением восстановить скрытое состояние, если оба возможных мира дают ей одинаковый тайм-аут и одинаковый пустой результат чтения.

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

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

Что менять в архитектуре агента

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

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

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

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

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

Источники

Пауза в чтении

Похоже на вашу задачу?

Расскажите, что собираете. За полчаса разложим на этапы и назовём сроки — это бесплатно и ни к чему не обязывает.

Rit.work

Студия разработки

Собираем мобильные приложения и помогаем командам получать от AI реальную пользу. Основатель и команда, работаем удалённо — с клиентами в России и за рубежом.

← Ко всем материалам
Понравилось? Обсудим вашу задачу