Коротко: Устойчивое выполнение для AI‑агентов означает, что план агента и его побочные эффекты переживают перезапуски, сетевые разрывы, нестабильные инструменты и ожидания человека, не теряя корректности. Мы оформляем цикл агента как устойчивый воркфлоу, изолируем побочные эффекты в идемпотентные инструменты, делаем чекпойнты состояния на каждом решении и используем реплей для отладки и оценки. Рантаймы а‑ля Temporal или управляемые воркфлоу‑сервисы дают таймеры, сигналы и детерминированную оркестрацию, которых нет у ноутбуков и простых очередей. Human‑in‑the‑loop становится полноценным состоянием ожидания со SLA, а не случайной паузой. Так мы закрываем разрыв «хайп vs продакшен»: агенты реально доводят дело до конца — хоть через несколько дней — ровно один раз.
Устойчивое выполнение для AI‑агентов: определение и рамки
Большинство демо агентов предполагают быстрый, непрерывный цикл: подумать, вызвать инструмент, снова подумать — готово. В продакшене так не бывает. Агенты координируют долгие процессы через API, пользователей и системы с разной задержкой и сбоями.
Устойчивое выполнение даёт три конкретные гарантии:
- Прогресс переживает сбой. Если воркер упал или вышел новый деплой, агент продолжит с последнего безопасного чекпойнта, не повторяя нежелательных побочных эффектов.
- Семантика «ровно один раз». Внешние эффекты (письма, тикеты, платежи, записи в файлах) происходят один раз, даже если мы ретраим внутри много раз.
- Аудит и реплей. Мы можем восстановить, что решил агент, какие инструменты вызывал, что вернулось и почему он выбрал следующий шаг.
Для AI‑агентов эти гарантии накладываются на недетерминированные компоненты (LLM и сторонние API). Мы не пытаемся сделать LLM детерминированной. Мы делаем детерминированной оркестрацию и записываем недетерминированные выходы как события. Это даёт надёжный прогресс и честный разбор.
Сценарии сбоев, которые ломают наивных агентов
Когда команды несут прототип в прод, повторяются одни и те же поломки. Мы проектируем устойчивое выполнение, чтобы их нейтрализовать.
- Смерть процессов и деплои. Эфемерные воркеры умирают. Без сохранённого состояния и таймеров многочасовой агент тихо исчезает посреди выполнения.
- Сетевые разрывы и «шатающиеся» API. Вызовы инструментов длятся минуты, таймаутятся, завершаются поздно или дважды. Наивные ретраи создают дубликаты и неконсистентное состояние.
- Недетерминизм LLM. Сэмплинг на ретрае даёт другие вызовы инструментов, поэтому продолжать после сбоя опасно, если мы не зафиксировали решения.
- Человеческая задержка. Шаги согласования стоят часами или днями. Если состояние агента в RAM, к моменту клика Approve его уже нет.
- Дрейф часов и расписаний. Паузы cron и слипы не переживают перезапуски и не имеют устойчивых хэндлов; таймеры теряются.
- Дрейф схем. Payload'ы инструментов меняются. Без версий состояния и миграций старые прогоны становятся нечитаемыми и непригодными для реплея.
- Частичные побочные эффекты. Шаг записал данные в одну систему и не смог — в другую. Нет компенсаций и нет реестра для сверки.
Устойчивое выполнение делает всё это первоклассными сущностями: время, идемпотентность, ожидания человека и компенсации живут в оркестраторе, а не в разбросанных try/catch.
Паттерны, которые делают агентов устойчивыми
Цель проста: оркестрация детерминирована, побочные эффекты идемпотентны, время — устойчиво. Вот паттерны, на которые мы опираемся.
Саги и компенсирующие действия
У агентов редко бывают ACID‑транзакции между сервисами. Мы используем паттерн Саги: разбиваем работу на шаги с прямыми действиями и компенсациями. Если шаг N+1 безнадёжно падает, запускаем компенсации для шагов 1..N, чтобы восстановить согласованное бизнес‑состояние.
- Прямые действия: создать тикет, записать запись, отправить письмо.
- Компенсации: закрыть/откатить тикет, удалить запись или пометить как недействительную, отправить корректирующее письмо.
- Реестр: хранить, какие компенсации ещё допустимы; сами компенсации должны быть идемпотентны.
Саги держат внешний мир агента консистентным, даже когда инструменты дают сбой или после частичного выполнения человек отклоняет изменение.
Идемпотентные инструменты и дедупликация
Каждый побочный эффект мы оборачиваем в интерфейс инструмента, который принимает ключ идемпотентности и возвращает стабильный внешний ID. Если оркестратор ретраит инструмент, провайдер либо вернёт исходный успех, либо ничего не сделает.
- Ключи идемпотентности на логическое действие, а не на попытку.
- Натуральные ключи где возможно (например, «инвойс для order‑123»).
- Кэши дедупликации на нашей стороне, если апстрим‑сервисы без идемпотентности; маппим наши логические ключи на ответы провайдера.
- Версионированные инструменты, чтобы менять payload'ы без порчи реплея старых прогонов.
Идемпотентность — разница между безопасными ретраями и дубликатами эффектов. Без неё мы не шипим.
Чекпойнты состояния и решений
Мы сохраняем состояние агента после каждого значимого шага: план, выбранный инструмент, аргументы, сырые и разобранные выходы, а также любые человеческие вводы. Мы не полагаемся на «черновик» LLM для восстановления контекста.
- Журнал выполнения: структурированный лог шагов с таймстемпами, промптами, ответами, вызовами инструментов и артефактами.
- Результаты шага: успех, запланирован ретрай, запланирована компенсация, ожидание сигнала, прервано.
- Разделение данных: хранить PII и секреты вне общего транскрипта, подтягивать по ссылке при необходимости; шифровать на диске.
- Версия схемы: фиксировать версию схемы состояния на каждом шаге для поддержки миграций.
С чекпойнтами перезапуск продолжает с последнего зафиксированного решения. Мы избегаем повторно спрашивать LLM одно и то же, если только не хотим этого явно.
Детерминизм реплея и event sourcing
Недетерминированные выходы мы считаем событиями. При «холодном» реплее подаём записанные события обратно в воркфлоу, а не генерируем их заново. Это даёт пошаговый детерминизм без «заморозки» модели.
- Один раз записывать каждый недетерминированный результат: выходы LLM, случайные ID, значения, зависящие от времени, ответы внешних API.
- Чистый код оркестрации, который при реплее использует записанные события; тот же код работает и в лайве, читая из журнала событий.
- Избирательный перезапуск когда намеренно хотим другой исход (например, политика теперь запрещает ранее разрешённый инструмент). Мы помечаем событие недействительным и продолжаем с этой точки.
Реплей позволяет отлаживать с хирургической точностью, запускать офлайн‑оценки на реальной истории и воспроизводить продакшен‑баг без угадывания промптов или таймингов.
Устойчивое время: таймеры, хартбиты и лизы
Асинхронной работе нужно устойчивое представление времени и владения. Мы не усыпляем потоки; мы ставим таймеры и хартбиты в оркестраторе.
- Устойчивые таймеры будят воркфлоу через минуты, часы или дни. Таймеры переживают перезапуски и деплои.
- Хартбиты от активностей (обёрток инструментов) позволяют отменять или ретраить долгие вызовы и обнаруживать застрявшие воркеры.
- Лизы на внешние ресурсы не дают двум воркерам одновременно работать с одним и тем же элементом.
С устойчивым временем агент может ждать ответа пользователя или окна бэкоффа у вендора, не держа вычислительные ресурсы и не теряя позицию.
Человек‑в‑контуре как первоклассный сигнал
Согласования и уточнения — не исключения. Мы моделируем их как сигналы, которые разблокируют состояние ожидания со SLA и путями эскалации.
- Состояния ожидания с дедлайнами. Если дедлайн прошёл, автоэскалация, автоотказ или маршрут на запасной путь.
- Диффы артефактов для ревью (например, предлагаемые изменения в PR, черновики писем, детали платежа) — для быстрых и безопасных апрувов.
- Контроль доступа на то, кто может одобрять какие действия; апрувы становятся подписанными событиями в журнале выполнения.
Устойчивые человеческие шаги предотвращают классический ступор: агент бесконечно ждёт нажатия кнопки, которое так и не случится.
Бэкофф, circuit breaker'ы и бюджеты
Когда инструменты шалят, мы быстро «ломаемся» и защищаем систему.
- Экспоненциальный бэкофф с джиттером и потолками на инструмент.
- Circuit breaker'ы открываются при всплеске ошибок; перевод в очереди на ручное ревью.
- Бюджеты ошибок на каждую способность агента. Если бюджет исчерпан, деградируем плавно или отключаем рискованные действия.
Это оберегает надёжность агента и сдерживает радиус поражения во время падений вендора или смены схем.
Выбор исполнительной платформы
Нужен рантайм, который хранит состояние воркфлоу, даёт устойчивые таймеры и сигналы и детерминированно исполняет код оркестрации при сбоях. Есть несколько вариантов; выбор зависит от стека и операционных ограничений.
- Temporal: code‑first устойчивые воркфлоу с сильными гарантиями детерминизма, таймеров, сигналов и реплея. Отлично для долгоживущих агентов. Требует оперировать сервисом или использовать managed‑предложение, плюс дисциплину при эволюции кода воркфлоу.
- AWS Step Functions: управляемые воркфлоу с сервисными интеграциями. Хорошо для AWS‑центристских стеков и более коротких логических потоков. Менее естественно для итеративных LLM‑циклов инструментов, но жизнеспособно при аккуратном дизайне состояния и внешних активностях.
- Azure Durable Functions / GCP Workflows: языково‑интегрированные устойчивые паттерны в их экосистемах. Похожие компромиссы, как у Step Functions.
- Zeebe/Camunda: BPMN‑центричный движок с сильным моделированием процессов и масштабированием. Полезно, когда вы уже моделируете бизнес‑процессы визуально и можете сопоставить состояния агента с BPMN.
- Argo Workflows: контейнер‑ориентированные DAG'и на Kubernetes. Лучше для батча и дата‑задач; может поддерживать шаги агента с кастомными контроллерами, но из коробки нет детерминированного реплея.
- Встроенная во фреймворк персистентность: некоторые агент‑фреймворки и библиотеки дают граф‑исполнение и чекпойнты. Полезно на старте, но проверьте гарантии по таймерам, идемпотентности и межверсионному реплею, прежде чем на них ставить.
Мы избегаем ад‑хок‑смесей очередей, cron'ов и таблички «runs» в БД, если только не готовы построить пол‑движка воркфлоу. Кажется просто, а потом тихо съедает месяцы на краевых случаях: потерянные таймеры, двойные доставки, неконсистентные ретраи и неотслеживаемые дедлоки.
Критерии выбора:
- Языковое соответствие вашему ядру сервисов и навыкам команды.
- Детерминированный реплей и история миграций при изменениях кода воркфлоу.
- Таймеры и сигналы, переживающие перезапуски и дающие сильные гарантии доставки.
- Операционная модель: managed‑сервис против self‑hosted; латентность, пропускная способность и наблюдаемость.
- Трение интеграций с вашими секретами, идентификацией и границами VPC.
Путь миграции: от прототипа к устойчивому продакшену
У большинства команд уже есть рабочий прототип агента. Отлично. Мы сохраняем поведение, но меняем «скелет», чтобы он переживал реальный мир таймингов и сбоев. Таков наш путь.
- Зафиксируйте бизнес‑критический путь. Опишите минимальный набор действий, без которых ценность не доставляется. Остальное можно отложить.
- Вынесите побочные эффекты в инструменты. Оборачивайте каждый вызов, который меняет мир (тикеты, письма, платежи, репозитории), за границу инструмента с ключами идемпотентности.
- Добавьте журнал выполнения. Введите структурированный лог для промптов, вызовов инструментов, выходов и человеческих вводов. PII и секреты — по ссылке, не инлайн.
- Подключите устойчивый оркестратор. Перенесите цикл (plan‑act‑observe) в движок воркфлоу с таймерами и сигналами. Инструменты оставьте как активности, которые могут ретраиться и слать хартбиты.
- Старайтесь чекпойнтить после каждого решения. Фиксируйте план, выбранный инструмент, аргументы и выходы. На сбое продолжайте из чекпойнтов, а не переспросом LLM.
- Смоделируйте человеческие шаги как сигналы. Замените ад‑хок блокировки на устойчивые ожидания, дедлайны и правила эскалации. Показывайте артефакты для ревью.
- Сделайте инструменты по умолчанию идемпотентными и безопасными. Добавьте ключи идемпотентности, таймауты, бэкофф и circuit breaker'ы. Логируйте стабильные внешние ID для аудита.
- Проведите наблюдаемость. Добавьте trace‑ID по воркфлоу, LLM‑вызовам и инструментам. Публикуйте метрики: доля успеха, ретраи, длительности ожиданий, частота компенсаций.
- Включите реплей и песочницы. Храните недетерминированные события. Постройте реплей‑хранилище, которое может проигрывать историю продакшена офлайн на последнем коде.
- Определите SLA и бюджеты ошибок. Установите цели по латентности, доле завершений и максимуму дубликатов эффектов. Автоматизируйте деградацию при срабатывании бюджетов.
- Спланируйте эволюцию схем и кода. Версионируйте состояние, инструменты и промпты. Пишите шими миграций для активных прогонов перед выкатыванием несовместимых изменений.
Типичные ловушки, которых стоит избегать:
- Отказ от идемпотентности потому что провайдер «редко» дублирует запросы.
- Сваливание всего в транскрипт вместо моделирования структурированного состояния и артефактов.
- Использование sleep для многочасовых ожиданий вместо устойчивых таймеров.
- Объединение вызовов инструментов внутри шага LLM — так нельзя ретраить или компенсировать их отдельно.
- Хардкод изменений промптов без версий, делая реплей невозможным, а аудиты — неполными.
Ведите миграцию срезами. Начните с одной способности end‑to‑end, докажите устойчивость, затем расширяйтесь на соседние потоки.
Как Moai Team подходит к этому
Мы строим агентов, которые доходят до продакшена и там остаются. Устойчивое выполнение — не «после» в наших проектах; туда уходит инженерное внимание сразу после первого удачного демо. Подход прагматичный: сохранить рабочее, заменить «скелет» под ним и вывести в прод с «ограждениями безопасности» в первый день.
- Фокусировка на критическом пути. Режем способность до кости, чтобы спроектировать идемпотентные инструменты и компенсации для немногих важных действий.
- Каркасирование. Формализуем петлю агента как детерминированный воркфлоу с чекпойнтами, таймерами и сигналами. Избегаем скрытого состояния в памяти и изолируем побочные эффекты.
- Укрепление инструментов. Оборачиваем внешние системы идемпотентностью, политиками ретраев, бэкоффом и circuit breaker'ами. Добавляем наблюдаемость и стабильные внешние ID для аудита.
- Replay‑first отладка и оценки. Записываем недетерминированные исходы и строим стенд реплея, чтобы воспроизводить проблемы и замерять улучшения до релиза.
- Человек‑в‑контуре по дизайну. Делаем согласования и уточнения устойчивыми — с дедлайнами и эскалацией. Показываем компактные артефакты для быстрого ревью.
- Говернанс и SLA. Определяем бюджеты ошибок, гейты раскатки и режимы деградации. Если бюджет исчерпан, агент отступает или переключается на более безопасный путь автоматически.
- Глубина интеграции. Подключаемся к реальным системам учёта и безопасно двигаем данные через границы идентификации, секретов и комплаенса. Мы не шипим теневые базы.
Результат прост в формулировке и труден в подделке: агент завершает долгую работу ровно один раз, с бумажным следом и планом отката. Это и есть разрыв между демо и продакшеном. Это разрыв, который мы закрываем.
Часто задаваемые вопросы
Чем устойчивое выполнение отличается от очереди с ретраями?
Очередь с ретраями перезапускает всю задачу при сбое. Устойчивое выполнение сохраняет машину состояний работы, поэтому мы продолжаем с последнего безопасного шага, а не с начала. Оно также даёт устойчивые таймеры, человеческие сигналы и семантику «ровно один раз» для побочных эффектов через идемпотентные инструменты. Очереди хороши для независимых, коротких задач. Долгоживущим агентам нужен рантайм воркфлоу.
Нужен ли Temporal, чтобы получить устойчивое выполнение для AI‑агентов?
Нет. Temporal — сильное попадание, но вы можете добиться устойчивого выполнения с управляемыми опциями вроде AWS Step Functions, Azure Durable Functions или GCP Workflows и даже с BPM‑движками вроде Zeebe/Camunda. Ключ — выполнить требования: сохранённое состояние, устойчивые таймеры и сигналы, детерминированная оркестрация и история реплея. Мы выбираем платформу исполнения, которая подходит вашему стеку и операционной модели.
Как сохранить детерминизм, если LLM недетерминирована?
Мы делаем оркестратор детерминированным и считаем каждый недетерминированный исход записанным событием. На реплее подаём записанные события вместо генерации заново. Текст промптов и схемы инструментов — с версиями. Это позволяет воспроизвести любой прошлый прогон в точности, при этом в лайве система продолжает свободно сэмплировать.
Как добавить шаги согласования, не останавливая агента?
Моделируйте согласования как устойчивые состояния ожидания с дедлайнами. Используйте таймеры для автоэскалации или безопасного дефолта, когда дедлайн проходит. Упакуйте артефакты для быстрого ревью и ограничьте, кто может одобрять какие действия. Агент «спит» в хранилище, а не в потоке, и просыпается, когда приходит сигнал или срабатывает таймер.
Что на самом деле значит «ровно один раз» для внешних систем?
Мы приближаем «ровно один раз» через идемпотентные инструменты и дедупликацию. Каждое логическое действие использует стабильный ключ идемпотентности, а мы храним полученный внешний ID. Если случается ретрай, провайдер возвращает тот же результат или мы обнаруживаем прежний успех и пропускаем действие. Это устраняет двойные письма, дубли тикетов и повторные записи.
Можно ли «прикрутить» устойчивое выполнение к прототипу без переписывания?
Часто да. Начните с выделения побочных эффектов в идемпотентные инструменты, добавления журнала выполнения и переноса петли оркестрации в воркфлоу. Сохраните промпты и схемы инструментов, но добавьте версионирование. Перенесите одну способность end‑to‑end, извлеките уроки и расширяйтесь.
Есть прототип, который застревает «в полях», или дорожная карта, где нужно устойчивое выполнение? Пишите нам: Moai Team — контакты. Мы наметим кратчайший путь от демо к продакшену.