Библиотека · Надёжность: мониторинг, сбои, резервные копии

Failure Recovery Patterns — что делать когда агент сломался в проде

Инженер60 минОбновлено: октябрь 2026
90 из 105 в библиотеке

Время: ~25 мин теории + 35 мин практики


Суть урока

Все курсы учат "как построить агента". Никто не учит "что делать когда он сломался в 3 ночи перед демо клиенту".

Production = не "запустил и забыл". Production = "запустил и теперь живёшь с этим". Hallucination, бесконечные loops, упавший MCP, context overflow, спайк счёта на API, prompt injection, тихий silent failure — это не "если случится". Это "когда случится".

Этот урок — 7 типичных failure patterns и recovery playbook для каждого. Tools, code patterns, чеклисты, incident response. Не теория — то что ты будешь делать в реальной паническ.

🎨 Образ: машина с двигателем = твой AI-агент. Все знают как купить, ездить, заправлять. Но когда заглох на трассе ночью — большинство просто звонят эвакуатор. Этот урок — как сменить колесо самому и доехать до сервиса. Семь типичных поломок + инструмент в багажнике.


Ключевые концепции

  • Hallucination — модель уверенно выдаёт неверный факт
  • Loop — агент застрял на одном действии, retry без прогресса
  • Tool failure — MCP сервер / внешний API не отвечает или возвращает ошибку
  • Context overflow — контекст раздулся, модель теряет инструкции (context rot)
  • Cost spike — счёт за API вырос в 5-10 раз без явной причины
  • Prompt injection — внешний input заставил агента сделать что-то против правил
  • Silent failure — pipeline отработал без ошибок, но результат неверный
  • Circuit breaker — паттерн отключения сломанной интеграции на N минут
  • Graceful degradation — fallback на упрощённую функциональность при сбое
  • Chaos engineering — намеренное провоцирование failures для проверки готовности
  • Postmortem — структурированный разбор инцидента: root cause, prevention

Теория

Failure 1: Hallucination (агент уверенно врёт)

Симптом: ответ выглядит правильно, форматирование чёткое, тон уверенный — но факт ложный. "В Эквадоре налог на недвижимость 5%" (на самом деле другая ставка). "Эта функция появилась в версии 3.2 библиотеки" (такой версии не существует).

Risk levels:

  • CRITICAL — medical, legal, financial advice (клиент действует на основе ответа)
  • HIGH — производственный код, sql queries, конфиги (выполняется без проверки)
  • MEDIUM — casual chat, brainstorm (последствия ограничены)

Recovery patterns:

  1. Ground truth verification (RAG) — добавь retrieval с verified sources. Модель отвечает не "из памяти" а на основе документов которые ты контролируешь
  2. Confidence scoring — в промпт: "Ответь + укажи confidence 0-100. Если < 70 — скажи 'не уверен'"
  3. Multi-LLM voting — два независимых вызова (Claude + GPT). Если ответы расходятся — escalate human
  4. "Cite or refuse" — модель ОБЯЗАНА указать источник (URL, doc id) или явно сказать "не знаю"

Detection: sample 5% outputs ежедневно + human review. Логируй вопросы где модель сказала "не знаю" — это твоя карта пробелов.

python
# Pattern: cite-or-refuse через system prompt
SYSTEM = """Отвечай только на основе предоставленных документов.
Каждый факт сопровождай источником в формате [doc_id:section].
Если информации нет в документах — отвечай ровно:
"Не могу подтвердить из доступных источников."
НЕ выдумывай. НЕ опирайся на общие знания."""

Failure 2: Loop (агент повторяется бесконечно)

Симптом: одна и та же фраза, тот же tool call, та же ошибка — повторяется. Logs забиваются одинаковыми записями. Счёт за API тикает.

Common cause: tool failed → агент пытается снова с теми же параметрами. Или модель "не понимает" что инструмент уже вернул "файл не найден" и повторяет вызов.

Recovery:

  • Iteration cap: max N attempts → fallback или abort
  • Error context на retry: передавать сообщение прошлой ошибки в следующий вызов
  • State diff: проверять что state изменился между итерациями
  • Stuck detection: одинаковый action 3 раза подряд → abort
python
MAX_ATTEMPTS = 5
previous_action = None
stuck_count = 0

for i in range(MAX_ATTEMPTS):
    result = agent.run(state)
    if result.action == previous_action:
        stuck_count += 1
        if stuck_count >= 3:
            raise StuckLoopError(f"Same action repeated 3x: {result.action}")
    else:
        stuck_count = 0
    previous_action = result.action
    if result.done:
        break
else:
    raise MaxIterationsExceeded(f"Hit cap {MAX_ATTEMPTS}")

Failure 3: Tool failure (MCP сервер не отвечает)

Симптом: timeout, HTTP 500, MCP server crashed, rate limit от внешнего API.

Recovery:

  • Circuit breaker: 3 errors подряд → отключи интеграцию на 5 минут, не дёргай впустую
  • Fallback strategy: Stripe MCP down → local DB lookup для basic billing info
  • Graceful degradation: feature недоступна → честно "сервис временно недоступен, попробуй через 5 мин". НЕ fake результат
  • Health checks: ping MCP каждые 60 сек, alert если down > 2 мин

Library: Tenacity (Python) — retry с exponential backoff из коробки.

python
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10),
    reraise=True
)
def call_external_api(payload):
    return requests.post(URL, json=payload, timeout=10)

Failure 4: Context overflow (агент забыл начало сессии)

Симптом: агент игнорирует instructions из system prompt, противоречит сам себе, "забывает" что обсуждали 20 сообщений назад.

Cause: context > 50K токенов → context rot. Модель хуже работает с информацией из середины, лучше — с началом и концом.

Recovery:

  • /compact в Claude Code, когда контекст растёт (можно с инструкцией, что сохранить: /compact сохрани решения по архитектуре); автоматическое сжатие тоже работает, его порог настраивается командой /autocompact
  • Sliding window: держи последние N сообщений + summary более ранних
  • Critical instructions в конец — модель лучше помнит recent context (recency bias)
  • System prompt каждое сообщение — если правило критично, повторяй
  • Move long data → RAG — не пихай 50K документации в контекст, делай retrieval

Failure 5: Cost spike (счёт за день в 10 раз больше нормы)

Симптом: $50/день вместо $5/день. Уведомление о приближении к месячному лимиту уже на 5-й день месяца.

Possible causes:

  • Loop bug (Failure 2 не пойман)
  • Missing cache (повторные одинаковые prompts без prompt caching)
  • Scraping attack (если public endpoint без auth)
  • Retry storm (failed → retry → failed → retry)
  • Чужой API key (leaked в git)

Recovery:

  • Daily budget kill switch: spend > $X/день → автоматический pause API
  • Spike detection: spend > 2x daily average → email/Telegram alert
  • Audit log: каждый API call → log в KV/DB (cheap, debuggable)
  • Disable + investigate before resume. Не "поднимай лимит чтобы продолжить" не разобравшись

Tools:

  • Anthropic Console — страница Usage и собственный лимит расходов (Settings → Billing → Spend limits)
  • Langfuse — open-source observability, cost per user
  • LangSmith — tracing для LangChain/LangGraph

Failure 6: Prompt injection

Симптом: агент отключил хук "по просьбе пользователя", передал секреты во внешний tool, отправил email от твоего имени, выполнил rm -rf из инструкции в Markdown файле который читал.

См. подробно урок Prompt Injection Defense. Здесь — recovery.

Recovery:

  • Изоляция: каждый risky tool через отдельного агента с минимальными permissions
  • Audit log everything: что было command vs что внешний input (разделяй явно)
  • Restoration: git revert + alert team + investigate breach
  • Lessons learned: добавь pattern в pre-tool-use-prompt-injection.sh хук
bash
# Минимальная защита — hook проверяет подозрительные паттерны
# .claude/hooks/pre-tool-use-prompt-injection.sh
grep -iE 'ignore (previous|all) instructions|disable.*hook|reveal.*system prompt' "$INPUT" \
  && exit 1

Failure 7: Silent failure (агент "работает" но output неправильный)

Самый коварный. Pipeline complete, exit code 0, никаких errors в логах. Но результат — мусор.

Примеры:

  • LLM вернул JSON с правильной структурой, но значения сгенерированы из воздуха
  • Перевод выглядит беглым, но смысл искажён
  • Финансовый расчёт — правильная формула, но цифры с потолка

Recovery:

  • Output validation: schema check каждого LLM output. Pydantic, JSON schema, zod
  • Smoke tests: каждый pipeline run → проверка 1-2 known cases дают expected output
  • User feedback loop: "это ответ правильный? 👍/👎" каждые 50 interactions → дашборд
  • Eval suite (урок Evals): regression tests после каждого изменения промпта
python
from pydantic import BaseModel, Field, ValidationError

class InvoiceExtraction(BaseModel):
    amount: float = Field(gt=0, lt=1_000_000)
    currency: str = Field(pattern="^(USD|EUR|RUB)$")
    invoice_date: str  # ISO 8601

try:
    parsed = InvoiceExtraction.model_validate_json(llm_output)
except ValidationError as e:
    # silent failure caught — escalate
    log_anomaly(llm_output, e)
    raise

Recovery toolkit (что иметь в багажнике)

Категория Tool Назначение
Logging Langfuse, LangSmith, structured logs в KV Каждый LLM call с input/output/tokens
Alerting Telegram webhook, PagerDuty, email Spike / down / anomaly
Monitoring Anthropic Console + custom dashboard (урок Production Observability) Cost, latency, error rate
Rollback Git tags + revert script Один command возврат к last-good
Communication Шаблоны ответов клиентам "Known issue, fix в течение 2 часов"
Validation Pydantic / zod / JSON schema Schema check каждого output
Retry logic Tenacity (Python), p-retry (JS) Exponential backoff из коробки

Production checklist (mandatory перед запуском в прод)

Запуск в прод без 8/8 — техдолг с первого дня.


Chaos engineering для AI (тестирование failure cases)

Подход Principles of Chaos применённый к агентам. Намеренно ломай систему в staging, чтобы убедиться что recovery работает.

Inject Как Что проверяешь
Hallucination Добавь в prompt "Always answer Y is true" → spike test Обнаружит ли verification layer
Loop Mock tool всегда возвращает ту же ошибку Сработает ли iteration cap
HTTP 500 Mock MCP возвращает 500 на каждый 3-й вызов Сработает ли circuit breaker + fallback
Context overflow Запихни 100K junk токенов Триггерится ли /compact
Cost spike Loop без break, дешёвый prompt × 10000 Сработает ли daily budget kill switch
Schema mismatch LLM возвращает поля с лишними/missing keys Pydantic поймает или silent fail?

Раз в месяц — chaos день в staging. Полчаса работы, спасает в проде.


Incident response — 4 шага

Когда что-то горит — не паникуй. Иди по шагам:

  1. Stop — отключи affected feature, prevent further damage. Feature flag off, или maintenance page
  2. Triage — что произошло, scope (1 user / все), blast radius (билинг? данные? репутация?)
  3. Stabilize — rollback к last-good tag ИЛИ temporary fix (hardcoded fallback) чтобы вернуть service
  4. Postmortem — после восстановления: root cause, что добавим в monitoring, как prevent

Шаблон postmortem (journals/incidents/YYYY-MM-DD-<name>.md):

Напиши в чат
# Incident: <название>

**Дата:** YYYY-MM-DD
**Длительность:** 14:32 - 15:47 UTC (1h 15m)
**Severity:** P1 / P2 / P3
**Impact:** N клиентов, $X loss / 0 data loss

## Timeline
- 14:32 — alert spike в Telegram (cost > 2x avg)
- 14:35 — investigation start, нашёл loop в agent X
- 14:50 — iteration cap deployed
- 15:47 — service stable

## Root cause
Tool Y возвращал empty string вместо null. Agent интерпретировал
как "не получилось" и retry'ил бесконечно.

## What went well
- Alert сработал через 3 минуты
- Rollback procedure работала

## What went wrong
- Iteration cap отсутствовал (MAX_ATTEMPTS не задан)
- Output validation не проверял empty string

## Action items
- [ ] Добавить MAX_ATTEMPTS=5 во всех агентов (owner: A, ETA: завтра)
- [ ] Pydantic check на tool Y output (owner: A, ETA: 3 дня)
- [ ] Chaos test на empty string (owner: A, ETA: неделя)

Без postmortem инцидент повторится. Гарантировано.


Anti-patterns (что НЕ делать в панике)

  • ❌ "Просто перезапущу" без понимания root cause. Через час повторится
  • ❌ Скрывать инцидент от клиентов. Они узнают сами и доверие подорвано
  • ❌ Hot fix без записи в audit log. Через месяц "почему здесь magic number?"
  • ❌ "Это случайность, забуду". Паттерны повторяются. Каждый incident → postmortem
  • ❌ Disable hook чтобы "проверить" (см. урок Hook-Deny-By-Design). Security risk + забудешь включить
  • ❌ Поднять API лимит чтобы продолжить не разобравшись в причине spike

Cost recovery (если уже потеряли деньги)

Реальность: recovery почти всегда incomplete. Превенция дешевле.

Сценарий Шанс возврата Действия
Anthropic billing bug (их side) Низкий, но реальный Support ticket с trace_id, logs. Иногда дают credit
Stripe billing error (клиент платит лишнее) Высокий Dispute через Stripe dashboard, refund тебе
Leaked API key (Github push) 0% Rotate ключ немедленно, audit все calls
Loop bug съел $200 0% Урок усвоен. Iteration cap навсегда

Lesson: монитор budget alerts. Recovery редкий бонус, не план.


Аудиенция: что осваивать когда

Новичок (первые 3 месяца в прод)

Только failures 1-3 — самые частые:

  • Hallucination базово (cite-or-refuse в промпте)
  • Iteration cap на каждом loop
  • Try/except + retry для tool failures

Базовое logging (просто print в файл сначала). Лимит расходов в Anthropic Console.

Средний (3-12 месяцев)

Добавляешь:

  • Failures 4-5 (context management + cost monitoring)
  • Langfuse / LangSmith для observability
  • Telegram alerts на spike
  • Postmortem culture (даже если работаешь один — записывай)

Профессионал (1+ год прод)

Все 7 паттернов:

  • Chaos engineering ежемесячно
  • Automated runbooks (incident → bot выполняет triage)
  • Multi-LLM voting на critical paths
  • Pydantic validation everywhere
  • Customer notification automation

Практика

Шаг 1: Добавь iteration cap во все агенты

Find в коде где есть while, for без верхней границы, recursive calls без depth limit.

python
# До
def agent_loop(state):
    while not state.done:
        state = step(state)
    return state

# После
MAX_ITERATIONS = 10

def agent_loop(state):
    for i in range(MAX_ITERATIONS):
        state = step(state)
        if state.done:
            return state
    raise MaxIterationsExceeded(
        f"Hit {MAX_ITERATIONS}. Last state: {state.summary()}"
    )

Шаг 2: Настрой лимит расходов и предупреждение

Anthropic Console → Settings → Billing → Spend limits → Adjust limit. Лимит один: месячный потолок. Когда он достигнут, API останавливается, пока ты не поднимешь лимит или не наступит новый месяц. Поставь его примерно в 3x от обычного месячного расхода.

Предупреждение («soft limit») сделай сам, ежедневной проверкой через cron. Порог — текущий средний дневной расход × 1.5.

bash
# scripts/check-daily-cost.sh
# Нужен Admin API key (sk-ant-admin01-...): он есть у организаций, у индивидуальных аккаунтов его нет —
# тогда смотри страницу Usage в Console вручную.
TODAY=$(date -u +%Y-%m-%dT00:00:00Z)
TOMORROW=$(date -u -v+1d +%Y-%m-%dT00:00:00Z)   # на Linux: date -u -d tomorrow +%Y-%m-%dT00:00:00Z

RESP=$(curl -s "https://api.anthropic.com/v1/organizations/cost_report?starting_at=$TODAY&ending_at=$TOMORROW" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $ANTHROPIC_ADMIN_KEY")

# Суммы приходят в центах строкой; точную структуру ответа проверь в Cost API reference
DAILY_SPEND=$(echo "$RESP" | jq '[.data[].results[].amount | tonumber] | add / 100')

if (( $(echo "$DAILY_SPEND > 20" | bc -l) )); then
  curl -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
    -d "chat_id=$CHAT_ID&text=⚠️ Daily spend: \$$DAILY_SPEND"
fi

Описание Cost API: platform.claude.com/docs/en/manage-claude/usage-cost-api.


Шаг 3: Добавь Pydantic validation на critical output

python
from pydantic import BaseModel, Field, ValidationError
from anthropic import Anthropic

client = Anthropic()

class CustomerReply(BaseModel):
    sentiment: str = Field(pattern="^(positive|neutral|negative)$")
    intent: str
    confidence: float = Field(ge=0, le=1)
    suggested_response: str = Field(min_length=10, max_length=500)

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "..."}]
)

try:
    validated = CustomerReply.model_validate_json("".join(b.text for b in response.content if b.type == "text"))
    use(validated)
except ValidationError as e:
    log_to_journal("".join(b.text for b in response.content if b.type == "text"), e)
    raise SilentFailureDetected(str(e))

Шаг 4: Прогонять один chaos test

Выбери самый страшный для тебя failure (обычно cost spike или silent failure). Сегодня в staging:

  1. Намеренно создай условия (mock возвращает плохой output / loop без break)
  2. Запусти агента
  3. Засеки время до alert / abort
  4. Если >5 минут — добавь detection. Если не сработало — фикси

После — запиши в journals/chaos-tests/YYYY-MM-DD.md:

  • Что injected
  • Что ожидал
  • Что случилось
  • Action items

Шаг 5: Шаблон customer notification

templates/customer-incident-notification.md:

Напиши в чат
Здравствуйте,

Сейчас наблюдаем проблему с <feature>: <краткое описание симптома>.

**Статус:** работаем над фиксом
**ETA восстановления:** <X минут>
**Что делать сейчас:** <workaround или "подождать">

Обновим письмом когда устраним. Извините за неудобство.

— Команда <название>

Один файл. Открыл, заполнил 3 поля, отправил. В incident не нужно "сочинять с нуля".


Инструменты и ресурсы

  • Tenacity — Python retry library с exponential backoff
  • Anthropic Console — usage tracking и собственный лимит расходов
  • Langfuse — open-source observability для LLM apps, cost per user, latency (Helicone с марта 2026 в режиме поддержки)
  • LangSmith — tracing для LangChain/LangGraph агентов
  • Pydantic — schema validation для Python (zod аналог в TS)
  • PagerDuty — incident management для серьёзных команд
  • Principles of Chaos Engineering — Netflix-подход к намеренным failures
  • Урок Prompt Injection Defense — prompt injection defense in depth
  • Урок Production Observability — custom dashboards для мониторинга агентов
  • Урок Evals — eval suites для regression testing

Чеклист освоения урока


Ключевые выводы

Production — не "запустил и забыл". Production — "запустил и живёшь с этим". 7 failure patterns случатся у всех кто работает с агентами в проде. Вопрос не "если", а "когда" и "готов ли ты".

Превенция дешевле recovery. Iteration cap + budget kill switch + output validation — три копеечных паттерна которые покрывают большую часть типичных incidents. Без них — техдолг с первого дня прода.

Postmortem без обвинений — единственный способ не повторить инцидент. Шаблон 10 минут, защита на годы. Даже если работаешь один — записывай. Future you скажет спасибо.


Следующий урок

→ Backup & Disaster Recovery для AI-стека — что делать когда падает сам провайдер

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