Демо работает, продакшен плачет
Вы создали AI-агента. В демо он гениален: анализирует данные, пишет код, отвечает на вопросы. Выкатываете в продакшен. Через неделю получаете панику: агент отправил 500 одинаковых писем клиентам, зациклился на обновлении одной записи в базе, а его логи напоминают поток сознания шизофреника.
Знакомо? Добро пожаловать в реальный мир production-ready AI систем.
Разница между демо и продакшеном для агентов - как между детским садом и спецназом. В демо все контролируемо: один запрос, один ответ, чистый контекст. В продакшене агент живет в дикой среде: сетевые таймауты, падающие API, грязные данные, конкурентные запросы, необходимость помнить историю на 50 шагов назад.
Главная ошибка: думать, что агент - это просто обертка вокруг LLM. На самом деле агент - это распределенная stateful система с непредсказуемым поведением. И проектировать его нужно соответственно.
Проблема №1: Состояние, которое теряется (или не теряется, когда нужно)
Stateful vs stateless - старый спор, но для агентов он приобретает новые грани. Агент по определению stateful: он должен помнить, что уже сделал, какие инструменты вызывал, какие результаты получил.
Но где хранить это состояние? Вариантов три, и все плохие по-своему.
1 В памяти процесса (самоубийственный подход)
Храним состояние в переменных Python. Агент запускается, работает час, падает. Все состояние потеряно. Пользователь начинает заново. Или хуже: агент работает в Kubernetes, pod перезапускается при деплое. Состояние испаряется.
# КАК НЕ НАДО ДЕЛАТЬ
class NaiveAgent:
def __init__(self):
self.conversation_history = [] # Умрет при рестарте
self.executed_steps = [] # Потеряется при падении
def process(self, query):
self.conversation_history.append(query)
# ... логика агента
return response
Этот код работает в демо. В продакшене он гарантирует потерю данных при первой же проблеме.
2 В базе данных (медленно и сложно)
Сохраняем каждый шаг в PostgreSQL/Redis. Теперь состояние переживает рестарты. Но появляются новые проблемы:
- Латентность: каждый шаг агента = запись в БД. Агент, который делает 20 шагов, превращается в 20 network round-trips
- Консистентность: что если агент умер между записью состояния и вызовом инструмента?
- Очистка: старые сессии агентов накапливаются, база раздувается
3 Векторная база для контекста (иллюзия решения)
Модный подход: храним эмбеддинги разговоров, при необходимости достаем релевантные куски. Работает для чатов, но ломается для многошаговых workflow.
Проблема: агент, который анализирует финансовый отчет за 5 шагов, на шаге 6 может "забыть" выводы с шага 2, потому что семантически они не похожи на текущий запрос. А выводы эти критичны.
Проблема №2: Сайд-эффекты, которые накапливаются
Сайд-эффект в программировании - когда функция меняет что-то во внешнем мире. Для агентов сайд-эффекты - это их хлеб. Отправить email, создать запись в БД, запустить деплой.
Но в отличие от обычного кода, агент не понимает идиоматичности сайд-эффектов. Он видит инструмент "send_email" и использует его. Много раз. Подряд.
Реальные случаи из практики:
- Агент для обработки поддержки: получил 100 тикетов, отправил 100 ответов, но 95 из них были одинаковыми (потому что тикеты были похожими)
- Research агент: делал 20 запросов к Google Search API за минуту, получил бан за превышение лимита
- Агент-разработчик: создал 10 одинаковых функций в коде, потому "на каждом шаге думал, что это новая задача"
Корень проблемы: агенты не имеют built-in механизмов для:
- Дедупликации действий
- Отката изменений при ошибке
- Балансировки нагрузки на внешние API
- Проверки "а нужно ли вообще это делать?"
| Тип сайд-эффекта | Риск | Защита |
|---|---|---|
| Изменение данных (БД) | Потеря данных, corruption | Транзакции, dry-run режим |
| Внешние вызовы (API) | Баны, лимиты, costs | Rate limiting, кэширование |
| Коммуникация (email, messages) | Спам, дублирование | Дедупликация, задержки |
| Длительные операции (деплой) | Блокировка системы | Подтверждение, timeout |
4 Как добавить защиту от сайд-эффектов
Не надейтесь, что LLM сама поймет последствия. Добавляйте механическую защиту:
class SafeAgent:
def __init__(self):
self.executed_actions = set() # Хэши выполненных действий
self.rate_limiter = RateLimiter(requests_per_minute=10)
def execute_tool(self, tool_name, params):
# 1. Дедупликация
action_hash = hash(f"{tool_name}:{json.dumps(params)}")
if action_hash in self.executed_actions:
return {"error": "Это действие уже выполнено"}
# 2. Rate limiting для внешних вызовов
if not self.rate_limiter.can_proceed(tool_name):
return {"error": "Превышен лимит вызовов"}
# 3. Для опасных действий - требовать подтверждение
if tool_name in ["delete_database", "send_email_to_all"]:
if not self.get_human_approval(params):
return {"error": "Требуется подтверждение человека"}
# 4. Выполняем с таймаутом
try:
result = execute_with_timeout(tool_name, params, timeout=30)
self.executed_actions.add(action_hash)
return result
except TimeoutError:
return {"error": "Таймаут выполнения"}
Это базовый каркас. В реальной системе нужно больше: транзакции для БД, откат при ошибках, кэширование результатов дорогих операций.
Проблема №3: Аудит, которого нет
Представьте: агент принял решение отказать клиенту в кредите. Клиент спрашивает "почему?". Что отвечаете?
С обычным ML pipeline есть feature importance, логи правил. С агентом - только промпт, который был в контексте, и ответ LLM. Который может быть разным при каждом запуске.
Аудит агентов нужен для:
- Комплаенс: доказать, что решение не дискриминационное
- Дебаггинг: понять, почему агент сделал глупость
- Обучение: найти паттерны ошибок для улучшения промптов
- Биллинг: посчитать, сколько стоила каждая сессия
Но стандартное логирование не работает. Потому что лог агента - это не просто "вызвал функцию X". Это:
- Полный промпт со всем контекстом
- Ответ LLM (который может быть 1000 токенов)
- Парсинг ответа (который мог сломаться)
- Решение о выборе инструмента
- Результат инструмента
- Новый промпт для следующего шага
Записать это в текстовый файл - получите терабайты мусора за день.
Ключевая мысль: аудит агента должен быть структурированным и семантическим. Не просто "что делал", а "почему решил это сделать" и "какие альтернативы рассматривал".
5 Архитектура системы аудита
Нужно три уровня логирования:
# 1. Structured logging - в машиночитаемом формате
log_entry = {
"session_id": "sess_123",
"step": 5,
"timestamp": "2024-01-15T10:30:00Z",
"agent_thoughts": {
"reasoning": "Клиент запросил анализ отчета...",
"considered_tools": ["analyze_financials", "fetch_historical_data"],
"chosen_tool": "analyze_financials",
"confidence": 0.8 # Можно выцепить из LLM ответа
},
"tool_execution": {
"name": "analyze_financials",
"params": {"report_id": 456},
"result": {"profit_margin": 0.15, "risk_score": 0.3},
"duration_ms": 1200
},
"cost": {
"input_tokens": 1250,
"output_tokens": 340,
"estimated_cost": 0.012
}
}
# Пишем не в файл, а в Elasticsearch/ClickHouse
# Для поиска по сессиям, агрегации по стоимости, анализа паттернов
Второй уровень: семантическое индексирование. Берем ключевые решения агента, эмбеддим, кладем в векторную БД. Теперь можно искать "похожие случаи, где агент ошибся".
Третий уровень: воспроизводимость. Сохраняем seed для генерации, версию модели, температуру. Чтобы можно было воспроизвести сессию и понять, была ли ошибка детерминистической или случайной.
Проблема №4: Многошаговость, которая превращается в лабиринт
Одношаговый агент - это просто чат с инструментами. Настоящие агенты делают десятки шагов. И здесь начинается ад.
Каждый шаг - это:
- Накопление контекста (токены дорожают)
- Риск дрейфа цели (агент забывает, зачем начал)
- Возможность зацикливания
- Каскадные ошибки (ошибка на шаге 3 ломает шаги 4-10)
В нашей статье "Когда команды ИИ-агентов вредят вместо помощи" мы разбирали, как мультиагентные системы создают хаос. Но даже один агент с многошаговым workflow может навредить не меньше.
Решение: явное управление workflow. Не надеяться, что LLM сама решит, когда остановиться.
class OrchestratedAgent:
def __init__(self):
self.max_steps = 20
self.step_count = 0
self.original_goal = ""
def execute_workflow(self, goal):
self.original_goal = goal
while self.step_count < self.max_steps:
# 1. Проверяем, не достигли ли цели
if self.is_goal_achieved():
return self.compile_results()
# 2. Проверяем, не ушли ли от темы
if self.has_goal_drift():
self.realign_with_goal()
# 3. Выполняем шаг
result = self.execute_step()
# 4. Проверяем зацикливание
if self.is_looping():
raise AgentLoopError("Обнаружено зацикливание")
self.step_count += 1
raise MaxStepsExceeded(f"Превышено {self.max_steps} шагов")
def has_goal_drift(self):
# Анализируем последние шаги: не ушли ли от original_goal
# Можно использовать эмбеддинги или простую эвристику
recent_actions = self.get_recent_actions(5)
# Проверяем семантическую близость к цели
return calculate_drift(self.original_goal, recent_actions) > 0.7
Это упрощенный пример. В реальности нужно больше эвристик: timeout на общее выполнение, проверка прогресса (делаем ли мы движение к цели), fallback стратегии при зацикливании.
Собираем все вместе: production-ready агент
Итак, что отличает продакшен-агента от демо-версии?
- Состояние: сохраняется вне процесса, с checkpoint'ами и возможностью восстановления
- Сайд-эффекты: защищены дедупликацией, rate limiting, подтверждениями
- Аудит: структурированный, семантический, с возможностью воспроизведения
- Workflow: управляется оркестратором с проверками на дрейф цели и зацикливание
- Мониторинг: метрики стоимости, latency, успешности шагов, качества ответов
Самая частая ошибка - начать с реализации логики агента, а потом "прикрутить" надежность. Так не работает. Надежность должна быть вшита в архитектуру с первого дня.
Если вы проектируете агента с нуля, посмотрите нашу статью "Production-ready AI-агент с нуля" - там разбирается архитектура, которая не сломается в первую неделю.
Что будет дальше? (Спойлер: станет сложнее)
Тренды, которые усугубят проблемы:
- Более длинные контексты: 1M токенов - это не только больше знаний, но и больше мусора в состоянии
- Мультимодальность: агенты с vision - это новые сайд-эффекты (анализ изображений стоит дорого)
- Автономность: агенты, которые работают днями - нуждаются в механизмах сна, приоритизации, resource management
- Интеграция с реальным миром: IoT, robotics - здесь ошибки агента имеют физические последствия
Мой прогноз: через год появятся специализированные frameworks для production агентов. Не LangChain (который решает проблему композиции), а frameworks, которые решают проблемы состояния, сайд-эффектов, аудита. Что-то вроде "Kubernetes для агентов".
А пока - готовьтесь к боли. Или начните строить надежность в своих агентах сегодня, пока они не сломали что-то важное.
Последний совет: прежде чем выпускать агента в продакшен, дайте ему "побеситься" в изолированной среде. Создайте sandbox с копией production данных, но без реальных сайд-эффектов. Запустите 1000 сессий. Посмотрите, сколько раз он сломается, зациклится или натворит дел. Только после этого думайте о реальных пользователях.