Понедельник, 9 утра. Начало рабочей недели.

API OpenAI лёг. Или лимиты закончились. Или интернет в офисе пропал.

Что делает AI-агент? Ничего. А процесс, который он обслуживал, встаёт. Заявки копятся, договоры не согласовываются, клиенты ждут.

И хуже всего — люди не знают, что агент не работает. Думают, что всё идёт по плану.


Реальные сценарии сбоев

За год работы с AI-агентами в проде я собрал коллекцию того, что ломается.

Сбои провайдера LLM. OpenAI: 2-3 крупных сбоя в год плюс периодические замедления. Anthropic: реже, но бывает. GigaChat: стабильнее, но тоже не без проблем.

Сетевые проблемы. Интернет в офисе, проблемы с DNS, блокировки (привет, РКН).

Лимиты и квоты. Закончились токены, rate limiting, превышен бюджет.

Проблемы с данными. Недоступна база знаний, упала CRM, сломалась интеграция с почтой.

Внутренние ошибки. Баг в коде агента, некорректные данные на входе, бесконечный цикл.

Каждый из этих сценариев может парализовать работу. И каждый нужно обработать.


Принцип 1: Graceful degradation

Система должна деградировать плавно, а не падать полностью. Каждый уровень сохраняет какую-то функциональность.

Уровень 0 (норма): Агент работает, всё автоматически
Уровень 1: Основной LLM недоступен → переключение на резервный
Уровень 2: Все LLM недоступны → задачи в очередь, уведомление оператору
Уровень 3: Очередь > 50 задач → эскалация руководителю, ручной режим
Уровень 4: Критический сбой → полная остановка, аварийное уведомление

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


Принцип 2: Circuit breaker

Если сервис начал сбоить — временно прекращаем к нему обращаться. Зачем тратить время на заведомо неудачные запросы и нагружать и так перегруженный сервис?

Три состояния:

Closed (норма) → запросы идут как обычно
  ↓ 5 ошибок подряд
Open (сбой) → запросы не отправляются, сразу fallback
  ↓ через 60 секунд
Half-open (проверка) → пропускаем один тестовый запрос
  ↓ успех → Closed
  ↓ неудача → Open

Реализация на Python:

from datetime import datetime, timedelta


class CircuitBreaker:
    """
    Circuit breaker для защиты от каскадных сбоев.
    Отслеживает ошибки внешнего сервиса и временно
    прекращает запросы, если сервис «лёг».
    """

    def __init__(self, failure_threshold: int = 5, recovery_timeout: int = 60):
        self.failure_threshold = failure_threshold
        self.recovery_timeout = recovery_timeout
        self.failures: dict[str, int] = {}
        self.state: dict[str, str] = {}       # closed / open / half-open
        self.last_failure: dict[str, datetime] = {}

    def can_execute(self, service: str) -> bool:
        """Можно ли отправлять запрос к сервису?"""
        state = self.state.get(service, "closed")

        if state == "closed":
            return True

        if state == "open":
            # Проверяем, не пора ли попробовать снова
            elapsed = datetime.now() - self.last_failure[service]
            if elapsed > timedelta(seconds=self.recovery_timeout):
                self.state[service] = "half-open"
                return True  # Один тестовый запрос
            return False

        # half-open — пропускаем запрос для проверки
        return True

    def record_success(self, service: str):
        """Запрос прошёл — сбрасываем счётчик."""
        self.failures[service] = 0
        self.state[service] = "closed"

    def record_failure(self, service: str):
        """За��рос упал — считаем ошибки."""
        self.failures[service] = self.failures.get(service, 0) + 1
        self.last_failure[service] = datetime.now()

        if self.failures[service] >= self.failure_threshold:
            self.state[service] = "open"

Использование:

breaker = CircuitBreaker(failure_threshold=5, recovery_timeout=60)

async def call_llm(prompt: str) -> str:
    if not breaker.can_execute("openai"):
        # OpenAI «в отключке» — сразу идём на fallback
        return await call_fallback_llm(prompt)

    try:
        result = await openai_client.complete(prompt)
        breaker.record_success("openai")
        return result
    except Exception:
        breaker.record_failure("openai")
        return await call_fallback_llm(prompt)

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


Принцип 3: Retry with backoff

Если запрос не прошёл — повторяем. Но с умом: с увеличивающейся задержкой и ограниченное число раз.

Попытка 1: сразу
Попытка 2: через 1 сек
Попытка 3: через 2 сек
Попытка 4: через 4 сек
Попытка 5: через 8 сек
После 5 попыток: отказ → fallback или эскалация

Экспоненциальный backoff + jitter (случайный разброс) — чтобы при массовом сбое все клиенты не ретраили одновременно.


Принцип 4: Fallback LLM

Резервный провайдер. OpenAI лёг — используем Anthropic. Или GigaChat. Или локальную модель.

Важный нюанс: fallback нужно тестировать заранее. Нельзя в момент сбоя узнать, что резервная модель не понимает ваши промпты или выдаёт мусор.

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


Принцип 5: Persistent queue

Задачи, которые не удалось обработать, должны где-то храниться. Не в памяти приложения — она умрёт вместе с процессом. В надёжном хранилище: Redis, PostgreSQL, RabbitMQ.

Когда сервис восстановится — обработаем накопившееся. Ни одна задача не должна потеряться.


Мониторинг и алерты

Отказоустойчивая архитектура бесполезна без мониторинга.

Что мониторить:

  1. Доступность внешних сервисов (LLM API, интеграции)

  2. Латентность запросов (резкий рост — признак проблем)

  3. Процент ошибок (выше порога — алерт)

  4. Размер очереди (растёт — не успеваем)

  5. Текущий уровень деградации

Кому алертить:

Уровень 1 (fallback LLM):     инженеру в Slack
Уровень 2 (очередь):          оператору + инженеру
Уровень 3 (ручной режим):     руководителю
Уровень 4 (критический сбой): всем + SMS

SLA для AI-системы

У любой production-системы дол��ен быть SLA. AI-агент — не исключение.

99.5% — не более 3.6 часов простоя в месяц. Базовый мониторинг, ручное переключение. Достаточно для большинства бизнес-процессов.

99.9% — 43 минуты в месяц. Нужен дежурный инженер, автоматическое переключение, резервирование.

99.99% — 4 минуты в месяц. Распределённая архитектура, мульти-регион, автоматическое восстановление. Для AI-агентов обычно overkill.

SLA определяет, сколько ресурсов вкладывать в отказоустойчивость. Зафиксируйте его явно.


Сколько стоит отказоустойчивость

Это дополнительные расходы, но считаются они просто.

Резервный LLM: +30-50% к стоимости inference (тестирование на двух моделях).

Мониторинг: 50-100к на настройку + 10-20к/месяц.

Очередь и хранилище: 5-10к/месяц.

Поддержка: 10-20% от времени разработки.

В сумме: +10-15% к бюджету проекта. Это не траты — это страховка. Стоимость одного серьёзного сбоя обычно кратно превышает эти расходы.


Чеклист вопросов подрядчику

Если вам внедряют AI-агента — задайте эти вопросы:

  1. Что произойдёт, если API провайдера LLM станет недоступен?

  2. Есть ли резервный провайдер? Протестирован ли он?

  3. Как система обрабатывает таймауты?

  4. Где хранятся задачи, которые не удалось обработать?

  5. Как я узнаю, что система деградировала?

  6. Какой SLA вы гарантируете?

  7. Что происходит при превышении лимитов?

  8. Как выглядит процедура восстановления после сбоя?

Нет чётких ответов — получите систему, которая упадёт в самый неподходящий момент.


Выводы

AI-агент в продакшене должен быть отказоустойчивым. Это не опция — это требование.

Graceful degradation, circuit breaker, fallback LLM, persistent queue, мониторинг — минимальный набор.

Если интегратор не может ответить на вопросы про отказоустойчивость — ищите другого.



Серия «Почему AI-проекты проваливаются»:

  1. 6 проблем, о которых молчат интеграторы

  2. Инструкция для человека vs инструкция для AI

  3. Кто отвечает за ошибки AI-агента

  4. Что делать, когда AI-агент «упал» ← вы здесь

  5. Как передать агенту неявные знания

  6. Пошаговый план внедрения

Анатолий Лапков. Telegram: @futex_ai