Разница между демо и ИИ-агентом в продакшене — не в модели. Модель одна и та же. Демо пишется за вечер: подключил API, объявил три инструмента, вызвал agent.run(), посмотрел, как оно красиво работает. Продакшен от этого отличается количеством скучного кода вокруг модели, и этого кода примерно вчетверо больше, чем самого агента.
IDC в исследовании для Lenovo посчитала конверсию: из 33 запущенных ИИ-пилотов до широкого развёртывания доходят четыре. Остальные 88% умирают между демо и релизом. Оговорка важная — считали пилоты вообще, не агентов отдельно, так что растиражированное «88% агентов не доходят до продакшена» строго говоря неточно. Но порядок величины показательный, и причины IDC называет прямо: незрелость данных, процессов и инфраструктуры. Не «модель недостаточно умная».
Ниже — шесть слоёв, из которых собирается работающий агент, и что конкретно ломается, если слой пропустить.
Откуда взялась разбивка на слои
Честная оговорка: единой утверждённой схемы «шесть слоёв продакшен-агента» не публиковала ни Anthropic, ни Microsoft, ни OpenAI. Это обобщение, которое сложилось у практиков. Но части его подтверждаются независимо.
Anthropic в разборе «Building effective agents» описывает агента предельно скупо: это LLM, которая в цикле вызывает инструменты, опираясь на обратную связь от среды. И тут же добавляет, что автономность означает более высокую стоимость и накопление ошибок, поэтому нужны условия остановки — например, максимальное число итераций — плюс тестирование в песочнице и guardrails.
С другой стороны заходит OWASP: в проекте GenAI Security вышел Top 10 for Agentic Applications 2026, собранный при участии более сотни исследователей и практиков. Отдельный список рисков именно для агентных систем существует не потому, что кому-то захотелось нового документа, а потому что агент, получивший инструменты, ломается иначе, чем чат-бот.
Слой 1. Модель: клиент должен вырываться без боли
Задача слоя — общаться с API, ретраить сбои, парсить ответ. Всё. Никакой бизнес-логики.
Критерий здоровья здесь один: сможете ли вы поменять модель, тронув одну строку. Сегодня у вас Claude, через месяц дообученная open-source модель на своём железе, ещё через месяц роутинг дешёвых запросов на маленькую модель, а сложных — на большую. Anthropic, кстати, приводит такой роутинг как штатный паттерн, а не как экзотику.
Технически это решается контрактом. В Python — Protocol, структурная типизация: любой класс с нужными методами подходит, наследоваться не надо.
class LLMClient(Protocol):
async def chat(self, messages: list[dict], max_tokens: int = 1024) -> str: ...
Что ломается без этого: привязка к вендору, тихие поломки при изменении API и невозможность прогнать тесты, не заплатив за запросы. Про последнее у нас есть отдельный разбор о тестах агента без API-ключей — там этот же протокол делает всю работу.
Слой 2. Оркестрация: у цикла нет естественного конца
Без оркестрации у вас чат-бот: запрос, ответ, конец. Агентным его делает цикл — подумать, вызвать инструмент, посмотреть на результат, решить, всё ли готово. Паттерн ReAct, reason plus act, стал здесь стандартом просто потому, что он самый простой из работающих.
Проблема цикла в том, что он не знает, когда остановиться. Агент, который не смог получить внятный ответ от инструмента, будет вызывать его снова. И снова. Пятьдесят раз, пока кто-нибудь не посмотрит на счёт за API.
Поэтому жёсткий лимит итераций — не оптимизация, а условие запуска. Пять-семь шагов на задачу, дальше принудительный выход с человекочитаемым сообщением. Плюс circuit breaker: если внешний сервис отвечает ошибкой три раза подряд, перестаём в него долбиться на минуту, а не пытаемся бесконечно.
Слой 3. Инструменты: каждый вызов проходит через шлюз
Инструменты дают агенту руки. Агент без них — дорогой генератор текста, агент с ними и без ограничений — источник инцидентов.
Правило простое: ни один инструмент не выполняется в обход пайплайна. На каждый вызов — проверка прав, валидация входных данных по схеме, принудительный таймаут через asyncio.wait_for() и запись в аудит. Таймаут именно принудительный: без него зависший HTTP-запрос держит весь цикл, и агент выглядит просто «медленным», хотя он мёртвый.
Валидация входа тут не формальность. Модель генерирует аргументы инструмента текстом, и этот текст приходит из диалога с пользователем. Всё, что вы знаете про непроверенный пользовательский ввод, применимо здесь один в один.
Слой 4. Память: границы диалога и границы токенов
Без памяти каждая реплика начинается с нуля: агент не помнит, что сказали два сообщения назад, и не учитывает результаты своих же вызовов инструментов.
Наивное решение — складывать всё в промпт — упирается в лимит контекста примерно на десятой реплике. Дальше нужен либо sliding window, либо сжатие: старые сообщения свернуть в резюме, свежие оставить как есть.
Второй вопрос — что вообще можно хранить. История переписки в поддержке — это персональные данные, номера заказов, иногда фрагменты платёжных реквизитов. Продакшен-вариант: шифрование на уровне отдельного диалога с деривацией ключа через PBKDF2, детекция PII на входе, разделение хранилищ по идентификатору диалога. Чтобы утечка одного ключа не открывала всю базу.
Слой 5. Guardrails: слой, который стоит денег ровно один раз
Это проверки прав, ограничения частоты, валидация путей, фильтрация контента и лимиты по стоимости. Всё, что отвечает на вопрос «что агенту вообще разрешено».
Показательный пример — защита от выхода за пределы рабочей директории. Агенту разрешено писать в /tmp/workspace, и наивная проверка сравнивает начало пути с этой строкой. Но /tmp/workspace-evil тоже начинается с /tmp/workspace, и проверка его пропустит. Лечится двумя движениями: сначала Path.resolve(), чтобы развернуть символические ссылки и .., потом сравнение с префиксом, к которому дописан слеш.
base_prefix = str(self.base_dir) + "/"
Ограничение частоты в распределённой системе делается через sliding window на sorted sets в Redis — счётчик в памяти процесса бесполезен, когда у вас три реплики за балансировщиком. И отдельно — потолок расходов на диалог, после которого агент вежливо отказывается продолжать. Плавная деградация вместо падения: лучше ответить «не могу выполнить сейчас», чем уронить процесс.
Тут же живёт то, что с недавних пор стало главной практической угрозой для агентов, — доверие к содержимому, которое агент читает сам. README из репозитория, описание MCP-сервера, страница из выдачи: всё это попадает в контекст и влияет на решения. Как это эксплуатируют на практике, мы разбирали на кампании с поддельными MCP-серверами.
Слой 6. Наблюдаемость: чтобы понять, что было в три ночи
Структурированные логи, аудиторский след, метрики, трейсинг. Ключевая деталь — correlation ID, единый идентификатор, который проходит через всю цепочку: ввод пользователя, вызов модели, выполнение инструмента, проверку прав, ответ. Без него у вас россыпь строк, из которой невозможно собрать один инцидент.
Минимальный рабочий вариант не требует стека на миллион: SQLite с таблицей событий, где есть время, correlation ID, тип действия и уровень значимости, уже даёт восстановимую картину. Дальше можно переезжать на OpenTelemetry, когда объём вырастет.
Отдельно про расходы: отслеживание токенов по диалогам — часть этого слоя, а не бухгалтерии. Аномальный рост расхода на одного пользователя — самый ранний сигнал, что агент зацикливается или что его используют не по назначению.
Как понять, чего не хватает вашему агенту
Пройдите по списку и отвечайте только «да, вот код» или «нет». «Планируем» считается за «нет».
- Смена LLM-провайдера — это правка одного адаптера или переписывание половины проекта?
- Есть жёсткий максимум итераций в цикле, и что происходит при его достижении?
- Есть circuit breaker на внешние вызовы, или агент долбится в упавший сервис бесконечно?
- Каждый вызов инструмента проходит проверку прав, или права проверяются только на входе в диалог?
- У инструментов есть принудительный таймаут, а не надежда на таймаут библиотеки?
- Аргументы инструментов валидируются по схеме до выполнения?
- Пути к файлам разворачиваются через
Path.resolve()и сравниваются с префиксом со слешем? - Ограничение частоты работает поверх всех реплик, а не в памяти одного процесса?
- Есть потолок расходов на диалог и что-то происходит при его достижении?
- История диалога шифруется, и ключ выводится на диалог, а не один на всю базу?
- Что происходит при переполнении контекста — сжатие, окно или падение?
- Логи связаны correlation ID, и можно поднять полную цепочку одного запроса?
- Тесты прогоняются в CI без обращения к платному API?
Меньше восьми «да» — до продакшена рано, и дело не в промптах.
Про инцидент, с которого обычно начинают такие статьи. В исходном материале, откуда взята разбивка на слои, приводится случай: финтех выкатил агента поддержки в пятницу, к трём ночи в субботу тот оформил 47 000 долларов неавторизованных возвратов пользователю, подобравшему нужные формулировки. История правдоподобная и хорошо иллюстрирует, что бывает без слоёв 3 и 5. Подтверждения ей мы не нашли: ни компании, ни даты, ни отчёта, ни публикации. Считайте это иллюстрацией, а не кейсом, и не ссылайтесь на неё в разговоре с руководством — спросят источник.
Источники
- Anthropic, Building effective agents — цикл агента, условия остановки, песочница и guardrails
- OWASP GenAI Security Project, Top 10 for Agentic Applications 2026
- CIO, разбор исследования IDC: 88% пилотов не доходят до развёртывания
- Lenovo CIO Playbook 2025 — первичный отчёт IDC с цифрой 33 к 4
- Репозиторий production-ai-agents — рабочий код слоёв, запускается локально без API-ключей

