Наблюдаемость AI-агентов: что логировать, что мерить и когда бить тревогу
Агент отличается от обычного сервиса тем, что сам решает, какой шаг сделать следующим. Поэтому обычных логов и метрик запросов мало: они показывают, что произошло, но не почему. Разбираем, какие данные нужно собирать с первого дня, какие четыре сигнала требуют алертов, где сейчас стандарт OpenTelemetry для GenAI и как мы выбираем инструмент под проект.
9 мин чтения
Почему логов недостаточно
Обычный сервис выполняет один и тот же код на каждый запрос, и лог с временем ответа и кодом ошибки описывает его почти полностью. Агент на один и тот же вопрос может сделать два вызова инструментов или семь, выбрать другой маршрут, зациклиться или остановиться раньше времени. Запись «ответил за 4 секунды, код 200» про такой запрос не говорит ничего.
Нужна трасса: дерево шагов одного запуска, где каждый вызов модели, инструмента и поиска по базе знаний является отдельным узлом со своим входом, выходом, временем и стоимостью. Без неё любая жалоба пользователя превращается в «не воспроизводится», а любая смена модели в лотерею.
Что записывать с первого дня
Минимальный набор небольшой, и собирать его дешевле на старте, чем прикручивать после первого инцидента.
- На уровне запуска: идентификатор трассы, пользователь или арендатор, версия промпта, модель и её версия, итоговые токены, стоимость, длительность, результат: успех, отказ, ошибка, остановка по лимиту.
- На уровне шага: тип узла (вызов модели, инструмент, поиск, проверка человеком), входные аргументы и результат инструмента, число входящих и исходящих токенов, время, ошибка, если была. Содержимое промптов и ответов сохраняется отдельно, с возможностью отключить запись для чувствительных данных.
- На уровне решения: какой маршрут выбрал агент и почему. Если в системе есть роутер «лёгкая модель или старшая», его решение должно быть в трассе, иначе вы не объясните ни счёт, ни качество.
- Связь с внешним миром: идентификатор запроса в вашем бэкенде и в системе провайдера модели. Когда провайдер вернул ошибку, нужен его идентификатор, чтобы писать в поддержку не «иногда падает».
Четыре сигнала, которые требуют алертов
Дашборд с сорока графиками никто не смотрит. Алерты нужны на четыре величины, и для каждой порог задаётся на старте, а не после инцидента.
- Стоимость на задачу. Не общий счёт за день, а p95 стоимости одного запуска. Рост p95 при той же нагрузке означает, что агент стал делать больше шагов, и это видно за часы, а не в конце месяца.
- Время ответа по p95. Среднее скрывает хвост: десять процентов запросов, которые ждут по полминуты, и есть те, о которых напишут.
- Доля ошибок инструментов. Пустой ответ от CRM или тайм-аут поиска по базе знаний, после которого агент продолжил рассуждать, будто данные получил. Пустой результат должен быть явной ошибкой в трассе, а рост их доли сигналом.
- Число шагов и остановки по лимиту. У каждой задачи есть лимит шагов, времени и стоимости. Сработавший лимит означает цикл или деградацию инструмента, и его нужно видеть отдельно от обычных ошибок.
Качество измеряется отдельно
Трассы и метрики отвечают на вопрос «что агент сделал». На вопрос «правильно ли» они не отвечают, и ни один инструмент наблюдаемости сам по себе не отвечает. Для этого нужен набор примеров с известным правильным исходом, который прогоняется при каждой смене промпта, модели или инструмента.
Как это устроено у нас. Для safety-слоя одного из наших продуктов набор состоит из 30 сценариев: 12, где модель обязана сработать, 8, где обязана промолчать, и 10 пограничных. Каждый сценарий прогоняется пять раз, итого 150 вызовов на модель. Критерии зафиксированы заранее: ноль пропусков, точность не ниже 0,92, валидный JSON 150 из 150, p50 до 2 секунд, p95 до 3,5 секунд, цена не выше доллара за тысячу вызовов. Порядок компромисса тоже зафиксирован: полнота, валидность схемы, точность, p95, цена.
Трассы из production кормят этот набор. Каждый инцидент, который разобрали по трассе, становится новым сценарием. Так набор растёт из реальных отказов, а не из догадок.
Где сейчас стандарт: OpenTelemetry GenAI
У OpenTelemetry есть семантические соглашения для GenAI: единые имена атрибутов для вызовов модели, токенов, шагов агента, вызовов инструментов и MCP, событий с содержимым и результатов оценки. Они нужны, чтобы один и тот же код инструментирования можно было отправлять в Langfuse, Phoenix или свою базу без переписывания.
Важная оговорка на октябрь 2026: соглашения не стабилизированы. В июне 2026 их вынесли из основного репозитория в отдельный, open-telemetry/semantic-conventions-genai, и на дату проверки документы спецификации помечены статусом Development, а релизов у репозитория нет. На практике это значит: фиксируйте версию соглашений в коде, ожидайте переименования атрибутов и не стройте дашборды на именах из блогов прошлого года.
Инструменты: что выбрать под проект
Инструментов в этой категории больше десятка. Для проектов нашего масштаба выбор обычно сводится к трём вариантам плюс «свой бэкенд поверх OpenTelemetry». Данные о лицензиях проверены 29 октября 2026 по страницам репозиториев.
| Вариант | Где работает | Когда подходит |
|---|---|---|
| Langfuse | Open source, лицензия MIT за исключением папок ee. Self-host через Docker Compose, Helm, шаблоны Terraform. Есть облако | Данные нельзя выпускать из контура; стек не привязан к одному фреймворку; нужны трассы, оценки и промпты в одном месте |
| LangSmith | Коммерческий сервис LangChain, облако; self-host только на платном плане. Глубокая интеграция с LangGraph | Агент собран на LangGraph и команда готова отправлять трассы наружу; нужна самая подробная картина шагов графа |
| Arize Phoenix | Код открыт под Elastic License 2.0, self-host бесплатно, запускается одним контейнером; читает трассы OpenTelemetry и OpenInference | Основная боль в RAG: какие фрагменты нашлись и почему ответ собран не из тех; нужен инструмент без привязки к вендору |
| OpenTelemetry + свой бэкенд | Инструментирование по соглашениям GenAI, хранение в том, что уже есть: ClickHouse, Grafana, Elastic | В компании уже есть наблюдаемость для сервисов и команда, которая её держит; AI-часть должна жить там же |
Минимальная схема на первую неделю
Если агент уже в проде, а наблюдаемости нет, порядок такой.
- Обернуть каждый вызов модели и каждый инструмент в span с токенами, временем и результатом. Один день работы, если инструменты уже описаны как функции.
- Ввести лимиты на задачу: шаги, время, стоимость. Сработавший лимит пишется в трассу как отдельный исход.
- Поднять Langfuse или Phoenix рядом с приложением и отправить туда трассы. На этом этапе достаточно одного инстанса без отказоустойчивости.
- Поставить четыре алерта из раздела выше с порогами по текущим значениям p95 плюс запас.
- Собрать первые 30 сценариев для оценки из трасс последней недели: по десять успешных, спорных и ошибочных.