Урок 19 · Блок 3 · ~14 минут

Надёжность: обвязка, которая спасает от двойных списаний

⌂ Все уроки · Актуально на 11 июня 2026 · источники — в тексте · термины — в глоссарии · ← урок 18
Главная мысль урока: LLM-шаг и внешние сервисы будут сбоить — это не «если», а «когда»: у команд с AI в проде именно отказы моделей и внешних API — причина №1 инцидентов. Надёжной автоматизацию делает обвязка из шести элементов: строгая схема ответа → проверка → повторные попытки → защита от двойных действий → лимит времени → запасная ветка. Эти шесть пунктов — готовый абзац для вашего ТЗ.

Почему это вопрос заказчика, а не только программиста

Свежий опрос 130 инженерных команд (май 2026): 74% команд с AI в проде словили инцидент, видимый клиентам, за последние 90 дней. Главная причина сбоев у них — не падение серверов, а отказы LLM и внешних API (~56% случаев). (Inngest, AI in Production 2026)

То есть ненадёжность — норма жизни, а не брак подрядчика. Брак подрядчика — отсутствие обвязки, которая превращает неизбежные сбои в незаметные. Пройдём её элементы по порядку — у каждого есть бытовой образ.

Элемент 1 · Строгая схема ответа: бланк вместо сочинения

Главный источник поломок LLM-шага — свободный формат: попросили модель «верни данные заявки», а она вернула текст с лирикой, и следующий шаг конвейера подавился. Лечение — structured outputs (структурированный вывод): модель заполняет бланк с полями, а не пишет сочинение.

Это не просьба в промпте «отвечай в JSON» — это режим API, где провайдер гарантирует: ответ будет соответствовать заданной схеме полей, всегда. У OpenAI и Anthropic это штатные функции. (OpenAI, Structured Outputs; Claude, Structured Outputs)

Гарантия формата ≠ гарантия смысла: в правильно заполненном бланке может стоять неправильная сумма. Поэтому за схемой идёт проверка обычным кодом: сумма положительная? email похож на email? курс из нашего каталога? Не прошло — на повторную попытку или человеку.

Элемент 2 · Повторные попытки — и кнопка лифта

Сбой сети или модели лечится повтором (retry): не получилось — подождали — попробовали ещё раз, с растущими паузами и лимитом попыток. Просто? Да, пока у шага нет последствий во внешнем мире.

🔥 Реальный сценарий: задача выполнилась — списала деньги, — но сеть моргнула на ответе. Система не получила подтверждения, посчитала шаг проваленным и повторила его. Списание прошло дважды. С рассылками то же: письмо ушло два раза — клиент получил два «поздравляем с покупкой». (разбор кейса, апр. 2026)

Защита называется идемпотентность — свойство «повтор не меняет результат». Образ — кнопка лифта: сколько ни жми, лифт приедет один раз. Технически: каждое действие с последствиями получает уникальный ключ, и сервис, увидев повтор с тем же ключом, не выполняет действие заново, а возвращает прежний результат.

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

Элемент 3 · Журнал шагов: сохранения в игре

Автоматизация из десяти шагов упала на восьмом. Перезапускать с начала? Это значит заново оплатить семь LLM-вызовов и, без идемпотентности, повторить их действия. У Anthropic это назвали прямо: «агенты накапливают состояние — ошибки нельзя лечить простым перезапуском». (Anthropic, Multi-Agent Research System)

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

У подхода есть имя — durable execution («живучее выполнение») и зрелые готовые платформы: Temporal (самая взрослая, интегрируется с агентными SDK), легче — Restate, Inngest. Вам не нужно их различать — нужно слово-маркер в ТЗ: «конвейер переживает сбой любого шага без повторных побочных действий и без повторной оплаты выполненного». (Restate, Durable AI Loops; Temporal for AI)

Элементы 4–6 · Лимит времени, запасная ветка, журналирование

🔬 Под капотом: как работает ключ идемпотентности

Откуда сервис «знает», что запрос повторный? Из ключа. Перед действием с последствиями автоматизация генерирует уникальную строку — например, оплата-заказа-1042 — и передаёт её вместе с запросом. Сервис хранит таблицу «ключ → результат».

Пришёл запрос: ключа в таблице нет → выполнить действие, записать результат под ключом. Ключ уже есть → не выполнять, вернуть записанный результат. Для вызывающего оба случая выглядят одинаково — «успех», но действие в мире произошло ровно один раз.

Тонкость в выборе ключа: он должен кодировать смысл действия («письмо-о-доступе-для-заказа-1042»), а не момент запуска. Ключ от времени запуска бесполезен: ретрай создаст новый ключ, и защита не сработает. Это деталь, которую заказчик не проверит сам — но вопрос «как устроены ключи идемпотентности?» покажет подрядчику, что демо без обвязки вы не примете.

Абзац для вашего ТЗ

Требования к каждому LLM-шагу с действиями: ответ по строгой схеме (structured outputs) → проверка значений кодом → повторные попытки с растущими паузами и лимитом → ключ идемпотентности на каждое действие с последствиями → таймаут → при исчерпании попыток эскалация человеку с контекстом.

Требования к конвейеру в целом: после сбоя работа продолжается с места падения (durable execution), выполненные действия и оплаченные вызовы не повторяются. Каждый прогон виден как трейс со стоимостью.

Проверьте себя

Повторение урока 18. В автоматизации «оплата → доступ → приветствие» подрядчик сделал все три шага агентными «для гибкости». Что не так?

Автоматизация рассылки упала и перезапустилась — 200 учеников получили письмо дважды. Какой элемент обвязки отсутствовал?

«Будем писать в промпте: отвечай строго в JSON» — чем это хуже structured outputs?

Конвейер из 10 шагов (семь из них — LLM-вызовы) упал на восьмом. Что должно произойти при правильной архитектуре?

Практика: проверьте обвязку на своём процессе

🛠 Задание на 10 минут

  1. Возьмите карту процесса из практики урока 18 (или сделайте её сейчас).
  2. Отметьте на ней шаги с последствиями во внешнем мире: письма, списания, выдача доступов, изменение данных. Это зоны, где нужны ключи идемпотентности.
  3. Спросите Claude Code: «Вот схема автоматизации: [схема]. Спроектируй обвязку надёжности по списку: схема ответа, проверки, ретраи, идемпотентность, таймауты, fallback. Покажи, что будет при сбое на каждом шаге».
  4. Прочитайте ответ через вопрос: «есть ли шаг, сбой которого ученик заметит?» Если да — обвязка неполная.

Что дальше

Обвязка защищает от технических сбоев. Но есть действия, которые нельзя доверять автоматике даже исправной: возвраты, массовые рассылки, публикации. Следующий урок — про человека в контуре и кейс Klarna, которая сначала заменила людей, а потом наняла их обратно.