Коротко: Устойчивое выполнение для ИИ‑агентов означает, что план агента и побочные эффекты переживают перезапуски, сетевые разрывы, нестабильные инструменты и ожидание человека без потери корректности. Мы оформляем цикл агента как устойчивый воркфлоу, изолируем побочные эффекты в идемпотентные инструменты, делаем чекпоинты состояния на каждом решении и используем реплей для отладки и оценки. Рантаймы в стиле Temporal или управляемые сервисы воркфлоу дают таймеры, сигналы и детерминированную оркестрацию — того, чего нет у ноутбуков и простых очередей. Human‑in‑the‑loop становится первоклассным состоянием ожидания со SLA, а не случайной паузой. Так мы закрываем разрыв между хайпом и продакшеном: агенты, которые действительно завершают работу, пусть и спустя дни, ровно один раз.

Устойчивое выполнение для ИИ‑агентов: определение и область

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

Устойчивое выполнение даёт три конкретные гарантии:

  • Прогресс переживает сбои. Если воркер упал или вышел новый деплой, агент продолжит с последнего безопасного чекпоинта без непреднамеренных побочных действий.
  • Интенция ровно‑один‑раз. Внешние эффекты (письма, тикеты, платежи, записи в файлах) происходят один раз, даже если внутри мы ретраим много раз.
  • Аудит и реплей. Мы можем восстановить, что решил агент, какие инструменты вызывал, что вернулось и почему он выбрал следующий шаг.

Для ИИ‑агентов эти гарантии накладываются на недетерминированные компоненты (LLM, сторонние API). Мы не пытаемся сделать LLM детерминированной. Мы делаем детерминированной оркестрацию и записываем недетерминированные выходы как события. Это даёт надёжный прогресс и честную форензику.

Режимы отказов, которые ломают наивных агентов

Когда команды несут прототип в прод, всплывают одни и те же поломки. Устойчивое выполнение их нейтрализует.

  • Смерть процесса и деплои. Эфемерные воркеры умирают. Без сохранённого состояния и таймеров многочасовой агент тихо исчезает посреди запуска.
  • Сетевые разрывы и нестабильные API. Вызовы инструментов длятся минуты, таймаутятся, успешно завершаются поздно или дважды. Наивные ретраи делают дубликаты и неконсистентное состояние.
  • Недетерминизм LLM. Сэмплинг даёт другие вызовы инструментов при ретрае, поэтому возобновление после сбоя небезопасно, если мы не зафиксировали решения.
  • Человеческая задержка. Шаги с одобрением ждут часы или дни. Если состояние агента в ОЗУ — к моменту клика Approve его уже нет.
  • Дрейф времени и расписаний. Паузы и слипы на cron не переживают перезапуски и не имеют устойчивых хэндлов; таймеры теряются.
  • Дрейф схем. Пейлоады инструментов эволюционируют. Без версии состояния и миграций старые запуски становятся нечитаемыми и невоспроизводимыми.
  • Частичные побочные эффекты. Шаг записал данные в одну систему и не записал в другую. Нет компенсации и нет реестра для сверки.

Устойчивое выполнение делает эти аспекты первоклассными: время, идемпотентность, ожидание человека и компенсации живут в оркестраторе, а не в россыпях try/catch.

Паттерны, которые делают агентов устойчивыми

Цель проста: сделать оркестрацию детерминированной, побочные эффекты — идемпотентными, а время — устойчивым. Вот паттерны, на которые мы опираемся.

Саги и компенсирующие действия

У агентов редко есть ACID‑транзакции между сервисами. Мы используем паттерн Saga: разбиваем работу на шаги с прямыми действиями и компенсациями. Если шаг N+1 безнадёжно падает, запускаем компенсации для шагов 1..N, чтобы вернуть согласованное бизнес‑состояние.

  • Прямые действия: создать тикет, записать запись, отправить письмо.
  • Компенсации: закрыть/откатить тикет, удалить запись или пометить как недействительную, отправить корректирующее письмо.
  • Реестр: хранить, какие компенсации ещё допустимы; сами компенсации тоже должны быть идемпотентны.

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

Идемпотентные инструменты и дедупликация

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

  • Ключи идемпотентности на логическое действие, а не на попытку.
  • Естественные ключи, где возможно (например, «invoice for order-123»).
  • Кэши дедупликации на нашей стороне, если апстрим без идемпотентности; маппим логические ключи на ответы провайдера.
  • Версионирование инструментов, чтобы эволюционировать пейлоады без порчи реплея старых запусков.

Идемпотентность — это разница между безопасными ретраями и дублирующими побочными эффектами. Без неё мы не шипим.

Чекпоинты состояния и решений

Мы сохраняем состояние агента после каждого значимого шага: план, выбранный инструмент, аргументы, сырые и распарсенные выходы, а также человеческие вводы. Мы не полагаемся на «черновик» LLM для восстановления контекста.

  • Run record: структурированный лог шагов с таймстемпами, промптами, ответами, вызовами инструментов и артефактами.
  • Итоги шагов: успех, ретрай запланирован, компенсация запланирована, ожидание сигнала, прервано.
  • Разделение данных: PII и секреты хранить вне общего транскрипта и подтягивать по ссылке; шифровать «на диске».
  • Версия схемы: фиксировать версию схемы состояния на каждом шаге для поддержки миграций.

С чекпоинтами рестарт продолжает с последнего зафиксированного решения. Мы избегаем повторно спрашивать LLM принять то же решение, если только не хотим этого явно.

Детерминизм реплея и event sourcing

Мы трактуем недетерминированные выходы как события. При «холодном» реплее подаём записанные события обратно в воркфлоу, а не генерируем их заново. Так мы получаем пошаговый детерминизм без заморозки модели.

  • Один раз записывать каждый недетерминированный результат: выходы LLM, случайные ID, значения, зависящие от времени, ответы внешних API.
  • Чистый код оркестрации, который при реплее использует записанные события; тот же код работает и «вживую», читая журнал событий.
  • Выборочная пере‑экзекуция, когда намеренно хотим другой исход (например, политика теперь запрещает ранее разрешённый инструмент). Помечаем событие недействительным и продолжаем с той точки.

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

Устойчивое время: таймеры, хартбиты и лизы

Асинхронной работе нужно устойчивое представление времени и владения. Мы не «усыпляем» потоки — мы ставим таймеры и хартбиты в оркестраторе.

  • Устойчивые таймеры будят воркфлоу через минуты, часы или дни. Таймеры переживают перезапуски и деплои.
  • Хартбиты от активностей (обёрток инструментов) позволяют отменять или ретраить долгие вызовы и детектить зависшие воркеры.
  • Лизы (leases) на внешние ресурсы предотвращают конкурентные действия двух воркеров над одним элементом.

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

Human‑in‑the‑loop как первоклассный сигнал

Одобрения и уточнения — не исключения. Мы моделируем их как сигналы, которые разблокируют состояние ожидания со SLA и путями эскалации.

  • Состояния ожидания с дедлайнами. По истечении — автоэскалация, автоотклонение или маршрут на фолбэк.
  • Диффы артефактов для ревью (например, предлагаемые изменения PR, черновики писем, детали платежа) для быстрых и безопасных одобрений.
  • Контроль доступа к тому, кто может одобрять какие действия; одобрения становятся подписанными событиями в run record.

Устойчивые человеческие шаги устраняют классическую «вечную паузу»: агент бесконечно ждёт клик, которого нет.

Бэкофф, circuit breakers и бюджеты

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

  • Экспоненциальный бэкофф с джиттером и потолками на инструмент.
  • Circuit breakers, которые «открываются» при всплеске ошибок; маршрут в отложенные ручные очереди.
  • Бюджеты ошибок на способность агента. Если бюджет исчерпан — деградируем аккуратно или отключаем рискованные действия.

Это охраняет надёжность агента и ограничивает «радиус поражения» при сбоях провайдеров или изменениях схем.

Выбор субстрата выполнения

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

  • 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.

Путь миграции: от прототипа к устойчивому продакшену

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

  1. Заморозьте критический бизнес‑путь. Запишите минимальный набор действий, который агент обязан выполнить для ценности. Остальное можно отложить.
  2. Вынесите побочные эффекты в инструменты. Оберните каждый вызов, который меняет мир (тикеты, письма, платежи, репозитории), за границу инструмента с ключами идемпотентности.
  3. Добавьте run record. Введите структурированный лог промптов, вызовов инструментов, выходов и человеческих вводов. PII и секреты храните по ссылке, не инлайните.
  4. Внедрите устойчивый оркестратор. Переместите цикл (plan‑act‑observe) в движок воркфлоу с таймерами и сигналами. Инструменты оставьте как активности с ретраями и хартбитами.
  5. Ставьте чекпоинт после каждого решения. Сохраняйте план, выбранный инструмент, аргументы и выходы. Возобновляйтесь с чекпоинтов, а не переспросом LLM.
  6. Смоделируйте человеческие шаги как сигналы. Замените ад‑хок‑блокировки на устойчивые ожидания, дедлайны и правила эскалации. Публикуйте артефакты для ревью.
  7. Сделайте инструменты идемпотентными и безопасными по умолчанию. Добавьте ключи идемпотентности, таймауты, бэкофф и circuit breakers. Логируйте стабильные внешние ID для аудита.
  8. Подключите наблюдаемость. Прокиньте trace‑ID по воркфлоу, вызовам LLM и инструментам. Метрики: доля успеха, ретраи, длительность ожиданий, доля компенсаций.
  9. Включите реплей и песочницы. Храните недетерминированные события. Постройте хранилище реплея, чтобы гонять прод‑историю офлайн на последнем коде.
  10. Определите SLA и бюджеты ошибок. Цели по латентности, доле завершений и максимуму дубликатов побочных эффектов. Автодеградация при исчерпании бюджетов.
  11. Планируйте эволюцию схем и кода. Версионируйте состояние, инструменты и промпты. Пишите миграционные «шины» для запущенных флоу до выката несовместимых изменений.

Типичные ловушки:

  • Пропуск идемпотентности из‑за того, что провайдер «редко» дублирует запросы.
  • Сваливание всего в транскрипт вместо моделирования структурированного состояния и артефактов.
  • Использование sleep для многочасовых ожиданий вместо устойчивых таймеров.
  • Встраивание вызовов инструментов внутрь шага LLM, из‑за чего нельзя ретраить или компенсировать по отдельности.
  • Хардкодинг изменений промптов без версионирования — реплей невозможен, аудиты неубедительны.

Ведите миграцию слайсами. Начните с одной способности end‑to‑end, докажите устойчивость, затем расширяйтесь на соседние потоки.

Как это делает Moai Team

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

  • Фокус на критическом пути. Мы «обтачиваем» способность до сути, чтобы спроектировать идемпотентные инструменты и компенсации для нескольких важных действий.
  • Инжиниринг харднесса. Формализуем цикл агента как детерминированный воркфлоу с чекпоинтами состояния, таймерами и сигналами. Избегаем скрытого состояния в памяти и изолируем побочные эффекты.
  • Укрепление инструментов. Оборачиваем внешние системы идемпотентностью, политиками ретраев, бэкоффом и circuit breakers. Добавляем наблюдаемость и стабильные внешние ID для аудита.
  • Отладка и оценки через реплей. Записываем недетерминированные исходы и строим хранилище реплея, чтобы воспроизводить проблемы и мерить апгрейды до релиза.
  • Human‑in‑the‑loop по дизайну. Делаем одобрения и уточнения устойчивыми — с дедлайнами и эскалацией. Публикуем компактные артефакты для быстрого ревью.
  • Говернанс и SLA. Определяем бюджеты ошибок, «ворота» выкатов и режимы деградации. При ударе по бюджету агент отступает или переключается на более безопасный путь автоматически.
  • Глубина интеграций. Подключаемся к реальным системам учёта и безопасно двигаем данные через идентичность, секреты и комплаенс‑границы. Мы не шипим «теневые базы».

Результат просто сформулировать и сложно подделать: агент завершает долгую работу ровно один раз, с аудитным следом и планом отката. Это разница между демо и продакшен‑системой. Этот разрыв мы закрываем.

Frequently Asked Questions

В чём разница между устойчивым выполнением и очередью с ретраями?

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

Нужен ли Temporal, чтобы получить устойчивое выполнение для ИИ‑агентов?

Нет. Temporal отлично подходит, но устойчивость можно реализовать и на управляемых опциях — AWS Step Functions, Azure Durable Functions, GCP Workflows, а также BPM‑движках вроде Zeebe/Camunda. Ключ — выполнить требования: сохранённое состояние, устойчивые таймеры и сигналы, детерминированная оркестрация и стратегия реплея. Мы выбираем субстрат под ваш стек и операционную модель.

Как сохранять детерминизм, если LLM недетерминирована?

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

Как добавить шаги человеческого одобрения без «зависания» агента?

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

Что на практике значит «ровно‑один‑раз» для внешних систем?

Мы приближаем «ровно‑один‑раз» через идемпотентные инструменты и дедупликацию. Каждое логическое действие использует стабильный ключ идемпотентности, а мы храним полученный внешний ID. При ретрае провайдер вернёт тот же результат, либо мы обнаружим прежний успех и пропустим. Это устраняет повторные письма, двойные тикеты и дубли записей.

Можно ли «прикрутить» устойчивое выполнение к нашему прототипу без переписывания?

Часто да. Начните с выделения побочных эффектов в идемпотентные инструменты, добавьте run record и перенесите оркестрационный цикл в воркфлоу. Сохраните промпты и схемы инструментов, но версионируйте их. Мигрируйте одну способность end‑to‑end, извлеките уроки и расширяйтесь.

Есть прототип, который «застревает» в полях, или роадмап, которому нужна устойчивость? Свяжитесь с нами: Moai Team — контакты. Мы проложим кратчайший путь от демо к продакшену.