Две вещи, называемые состоянием
Чекпоинт в рантайме агента обычно фиксирует механику прогона: какой узел графа выполнился, какой инструмент был вызван, что вернул инструмент, какое ребро ожидает. Это состояние выполнения. Его достаточно, чтобы ответить на вопрос «где была машина?»
Его недостаточно, чтобы ответить на вопрос «что машина пыталась сделать и на каких условиях?». Вторая вещь — это состояние намерения: цель в её текущем понимании, ограничения, которые прогон принял, допущения, которые он уже зафиксировал, и обязательства, которые он ещё не исполнил. Состояние выполнения — это курсор. Состояние намерения — это контракт.
Движки durable execution хорошо справляются с курсором. Они воспроизводят журнал шагов, пропускают завершённую работу и возвращают управление на первом незавершённом шаге. Это правильное поведение для workflow, смысл которого фиксирован в момент определения. Агент — не такой. Его смысл реконструируется на каждом шаге из истории, которую он видит, а история — не то же самое, что намерение, её породившее. Восстановите курсор без контракта — и прогон не упадёт. Он продолжится бегло, в неверном направлении, с тем же уверенным тоном, что и до прерывания.
Перепланирование из устаревшей цели
Прогон принимает ограничение на раннем этапе: работать только на чтение с продакшн-датасетом или ограничить область одним тенантом. В середине прогона оператор расширяет область, и ограничение обновляется в конфигурации оркестратора. Процесс умирает до следующего шага. При возобновлении чекпоинт содержит индексы шагов и выводы инструментов, но не ограничение, которое действовало. Агент заново выводит свой план из сохранившейся истории и текущей конфигурации, и эти двое расходятся. Ничто в транскрипте не отмечает шов. Полученный план внутренне согласован и внешне неверен.
Дублирование побочных эффектов
Классический случай: последний вызов инструмента завершился успешно, но подтверждение было потеряно. Движок durable execution, который возобновляется на первом незавершённом шаге, повторит вызов. Если вызов — это charge_card, send_email или create_ticket, у прогона теперь их два. Это не отказ рассуждения; это отказ контракта чекпоинта. Журнал зафиксировал намерение вызвать, а не факт эффекта, и эти двое различимы только если сам эффект несёт ключ, который распознаёт нижележащая система.

Дрейф допущений
При идентичных историях агент не всегда выведет идентичные планы. Сэмплирование, усечение контекста и изменения версии модели сдвигают распределение. Возобновление, которое воспроизводит историю и просит модель продолжить, породит план, правдоподобный при данной истории, но не тот план, который был в процессе выполнения. Дрейф допущений — это тихая версия отказа из-за устаревшей цели: конфигурация не менялась, изменилась только реконструкция. Прогон выглядит здоровым и расходится.
Работоспособный контракт чекпоинта
Решение — трактовать чекпоинт как сериализацию намерения, где состояние выполнения — лишь одно поле среди нескольких. Чекпоинт, который можно безопасно возобновить, должен нести вместе и атомарно:
- Цель в той форме, которой прогон сейчас привержен, а не в той, с которой он был запущен.
- Принятые ограничения, каждое с указанием точки прогона, в которой оно было принято, и источника, который его утвердил.
- Результаты инструментов, ключёванные по ключу идемпотентности, а не по порядку вызовов.
- Неисполненные обязательства: что прогон обещал сделать, но ещё не сделал.
- Версию схемы, чтобы чекпоинт, записанный более старым рантаймом, был распознаваем как таковой.
Механизм, который делает это работоспособным на практике, — это ключ идемпотентности в области прогона, выведенный из стабильных входов, а не из настенных часов или последовательности:
key = hash(run_id, step_name, canonical_args)
Каждый вызов инструмента с побочным эффектом несёт этот ключ. Нижележащая система или тонкий адаптер перед ней записывает ключи, которые уже выполнил, и при воспроизведении возвращает прежний результат вместо повторного выполнения эффекта. Ключ должен быть стабильным между повторными попытками и уникальным между различными намерениями; вывод его из имени шага и канонизированных аргументов, а не из счётчика, — это то, что делает воспроизведение безопасным после перезапуска, который переупорядочивает или пропускает шаги.
Второй механизм — отказ. Чекпоинт несёт версию схемы, и рантайм отказывается возобновляться между несовместимыми версиями, вместо того чтобы пытаться выполнить миграцию по мере возможности. Миграция намерения — это перепланирование, а перепланирование должно быть явной, логируемой операцией с человеком или