В этой статье я структурировал весь опыт и подходы к тому, как мониторить и трейсить LLM и AI-агентов на их основе. Это очень большая и тяжелая статья, но мне хотелось полностью закрыть всю тему за раз и создать крепкий бейзлайн для погружения в тему observability и трейсинга агентов.
Поговорим про то, почему все LLM-based решения требуют новых подходов, обсудим ключевые проблемы агентов, посмотрим пару самых популярных решений и обзор всех опенсорсных и зафиналим трендами и направлением, куда все это движется.
Про оценку (evaluations или evals) здесь не будет, но обязательно скоро будет отдельная статья и про это. Но будет про Langfuse, Phoenix, OpenLIT, Langtrace, LangWatch и Lunary.
Поехали!
Почему все изменилось для LLM-based систем
Когда у нас были просто LLM, то все было просто: один вызов LLM -> один ответ. Легко отследить промпт, ответ, токены, задержку. Как только LLM научились решать атомарные сложные задачи, мы перешли к концепции агентов и изменилось вообще все: типичная задача агента может потребовать составления плана, его критики и переоценки, десятка шагов выполнения, каскадного вызова множества инструментов, обращения и записи в память, саморефлексии и не только.
В этом очень легко потеряться и это создает новые проблемы. Пути выполнения недетерминированные даже для не очень сложных задач, цепочки причинностей вложенные, оркестрация непрозрачна, есть взрывной рост стоимости ризонинга и многое другое. У нас появились уникальные режимы отказа: галлюцинации вызова инструментов, бесконечные смысловые циклы, переполнение и дрифт контекста — все это требует вообще переопределения самого понятия ошибки.
AI-агенты не падают в классическом смысле, ошибка скрыта и классические инструменты не умеют это легко отлавливать. Но современные проблемы требуют современных решений и новых современных инструментов. И они есть.
Что критично отслеживать
Современная observability для агентов должна понимать не просто «что вызвали», а «почему», «каким путём», «что агент знал», «что он решил», «где потерялся контекст», «где денежки и почему сгорел весь бюджет».
И все требования можно разбить как бы на три большие группы.
1. Визуализация
Агенты создают очень сложный цифровой след в своей работе. Это могут быть линейные цепочки в базовом ReAct, циклические workflow в plan-execute-revise петлях, иерархические структуры с Agent/Subagents или параллельное выполнение асинхронных инструментов.
Фактически это можно свести к почти классическому привычному DAG, но с критичным дополнением — поддержкой циклов. Потому что агент может по 5 раз заходить в одну и ту же ноду пока не получит нужный результат. Визуализация должна показывать не просто граф, а как именно агент двигался по нему, сколько раз проходил через каждую ноду и где застревал.
2. Семантические типы спанов
Спан (span) — это термин из OpenTelemetry, который фактически является журналом выполнения одной операции с контекстом для её отслеживания в распределённой системе (trace_id, метки времени, имя операции и так далее)
Классические спаны описывают технические операции, не семантику рассуждений. В традиционном микросервисе спан это http.request, db.query, cache.get — операции с однозначными входами и выходами. Атрибуты тоже технические: http.status_code, db.statement, response.size_bytes. Это отвечает на вопросы «что выполнилось» и «сколько времени заняло». Все это нужно, но не отвечает на вопрос «почему».
А нам нужно понимать не просто что LLM вызвался, а почему агент принял конкретное решение, какую стратегию выбрал, насколько был уверен, что наблюдал и как это повлияло на следующий шаг.
Примеры классического спана и LLM-style:
### Классика
span: llm.completion
duration: 1.2s
tokens: 450
status: success
### LLM-style
span: agent.reasoning
thought: "Клиент описывает отклонённый платёж на 45,000₽.
Сумма превышает дневной лимит по карте (30,000₽).
Нужно проверить лимиты перед эскалацией в fraud."
confidence_score: 0.85
alternative_paths_considered: ["fraud_check", "block_card", "check_limits"]
chosen_strategy: "check_limits_first"
span: agent.tool_call
tool_name: get_card_limits
parameters: {"card_id": "4276****1234", "client_id": "C789012"}
validation_status: "passed"
reasoning: "Превышение лимита — самая частая причина отклонённых
платежей в нашей статистике (67% случаев)"
Другое дело!
Пример спана с ошибками:
### Классика
span: error
exception.type: "ValidationError"
exception.message: "Invalid parameter type"
stack_trace: [...]
### LLM-style
span: agent.tool_call[initiate_card_block]
tool_name: "block_card"
parameters: {"card_number": "4276 3822 1234 5678", "reason": "fraud"}
validation_status: "failed"
validation_error: "Parameter 'card_number' должен быть без пробелов,
получен '4276 3822 1234 5678'"
parent_span: agent.reasoning
thought: "Клиент сообщил о подозрительной транзакции.
Нужно немедленно заблокировать карту."
context_used: "Номер карты из предыдущего сообщения: '4276 3822 1234 5678'"
mistake: "Скопировал номер карты из текста с пробелами,
не нормализовал формат"
Все это можно по��ытаться свести в таблицу:
Тип span |
Критические атрибуты |
Зачем нужно |
llm.reasoning |
thought, confidence_score |
Понимание принятия решений |
agent.tool_call |
tool_name, parameters, validation_status |
Отлов неправильного использования инструментов |
agent.planning |
plan_steps[], strategy |
Отладка плохих стратегий |
agent.observation |
result, parsed_output, error |
Трейсинг потока информации |
agent.memory |
memory_type, retrieval_query, context_window |
Проблемы с памятью |
workflow.state_transition |
from_state, to_state, trigger |
Отладка LangGraph/StateGraph |
3. Экономика запросов
Технически это тот же пункт 2, только он настолько критичный, что его нужно вынести отдельно. Очень важно понимать, что любой и каждый запрос к LLM стоит токенов/денег и для сложных агентов это очень важно считать.
Пример:
### Классика
total_tokens: 8500
total_cost: $0.12
### LLM-style
agent.planning
tokens: 1400 (16% от total)
cost: $0.021
agent.tool_call[get_transaction_history]
tokens: 2900 (34% от total)
cost: $0.043
agent.reasoning[retry_with_different_approach]
tokens: 3100 (36% от total)
cost: $0.046
explanation: "Первая гипотеза о лимитах не подтвердилась,
проверяю историю транзакций на suspicious activity"
В первом случае мы не понимаем, на что именно были потрачены токены и чтобы не потратить бюджет маленькой страны, нам это важно знать и контролировать.
Переходим к инструментам! И да, обзор только про опенсурсные и которые можно самостоятельно развернуть у себя.
Open-source инструменты для Agent Observability
Сначала стоит два слова сказать про OpenLLMetry — попытку стандартизации этого процесса — чтобы каждый инструмент смог принимать один формат данных, накручивая свою логику уже вокруг него.
Семантические типы спанов которые я описал выше (llm.reasoning, agent.tool_call, agent.planning и другие) — это не моё изобретение. Они взяты из OpenLLMetry, развивающегося стандарта для трассировки LLM и агентных систем.
OpenLLMetry это не продукт и не отдельная платформа. Это спецификация — попытка сообщества привести индустрию к единому языку описания того, что делают агенты. Текущее состояние (на момент написания статьи) — это формирующийся стандарт, ещё не принятый повсеместно: большинство инструментов частично совместимы — они поглядывают на OpenLLMetry как на референс, делая неполную совместимость и часто расширяют стандарт собственными полями под свои нужды.
И теперь приступаем непосредственно к самим инструментам.
Langfuse — production-телеметрия
Философия: вырос из экосистемы LangChain как специализированный инструмент для трейсинга сложных LLM-пайплайнов. Фокус на детализацию стоимости токенов и визуализацию графов рассуждений. Стал де-факто стандартом для production-агентов на LangChain/LangGraph, но если очень нужно, то интегрируется с чем угодно.
Архитектура: PostgreSQL-based с SDK для Python/Go и TypeScript/JS. Опционально ClickHouse для тяжелой аналитики.
Что умеет: практически всё что нужно для production-агентов — иерархические трейсы, визуализация графов, версионирование промптов, экономика токенов, обратная связь с пользователями, фильтрация и поиск. А лучше всех сделано: нативная интеграция с LangGraph (переходы состояний, воспроизведение из любой ноды), детальный подсчет стоимости на уровне каждого спана, и управление датасетами для непрерывного улучшения через успешные трейсы.
Оверхед: сбор трейсов добавляет ~5-15мс на каждый LLM-вызов. На нагрузке требует умения правильно готовить PostgreSQL — правильные индексы, баунсеры и вот это все. Но главная проблема — объём хранимых данных. Langfuse сохраняет полные промпты и ответы в каждом спане, а типичный агент с 10 шагами создаёт ~50-150KB данных на один запуск (сильно зависит от длины промптов и ответов). При 100K запусков в день это 5-15GB новых данных ежедневно.
Минусы: батчинг с задержкой до 30 секунд — нет визуализации прям в реальном времени (впринципе, для большинства систем — вполне терпимо). Подключение других фреймворков требует копания ручками, а развертывание требует экспертизы в PostgreSQL под нагрузку и объемы, и нет метрик GPU если инференс локальный.
Langfuse хорош и заслуживает отдельной статьи (я постараюсь ее подготовить).
Phoenix от Arize AI — отладка по требованию и ресерч
Философия: изначально создавался для ML observability и детекта дрифта, а затем к нему добавили фокус на LLM и агенты. Позиционируется как research-friendly инструмент с акцентом на эксперименты и поиск первопричин, не на долгосрочное хранение. Для прода годится!
Архитектура: построен на OpenTelemetry с Python-бэкендом. SQLite для локальной работы, опционально PostgreSQL для прода. Неплохо поддерживает OpenLLMetry — reasoning нужно маппить вручную, но активно развивается совместимость со стандартом.
Что умеет: большинство базовых функций для трейсинга агентов — визуализация трейсов с DAG и циклами, автоинструментация для популярных фреймворков (LangChain/LlamaIndex и тд), встроенные проверки качества (точность, галлюцинации, токсичность), экспорт данных в parquet. А лучше всех сделано воспроизведение спанов (можно переиграть упавший вызов с измененными параметрами и сравнить результаты side-by-side), детект дрифта через кластеризацию эмбеддингов шагов рассуждений, и глубокий анализ качества RAG с оценкой релевантности и использования контекста.
Оверхед: локально минимальный latency overhead благодаря локальной архитектуре — трейсы пишутся в SQLite без сетевых вызовов, добавляя <1-3мс на запрос. Но на проде быстрота SQLite становится проблемой: типичная база быстро вырастает и на объеме начинается деградация, а миграция на PostgreSQL уже требует умения его готовить. Phoenix по своему дизайну не спроектирован для долгосрочного хранения — рекомендуют периодически экспортировать данные в parquet и очищать базу.
Минусы: SQLite не подходит для production-нагрузок, миграция на PostgreSQL требует ручной настройки. Интерфейс менее отполирован чем у Langfuse. Архитектура не заточена под долгосрочное хранение, но вывозит несколько месяцев хранения. Недостаточно детально отображает вызовы интструментов по сравнению с Langfuse — здесь больше фокуса на ML-метрики чем на агентную семантику.
OpenLIT
Философия: объединение наблюдаемости с замером инференса и его трейсинга. Создавался для команд с локальным инференсом LLM, где критично видеть корреляцию между загрузкой GPU и поведением агента.
Архитектура: python с OpenTelemetry SDK, интегрирован с NVIDIA DCGM/ROCm для GPU-метрик. Хранение: Prometheus для метрик + Tempo/Jaeger для трейсов и визуал через Grafana.
Что умеет: стандартный набор для трейсинга агентов через OpenTelemetry плюс метрики инфраструктуры — трейсинг application layer, дашборды Grafana для LLM-нагрузок, алертинг на аномалии. Лучше всего сделан подсчет метрики GPU, увязанных с шагами рассуждений (видно что планирование медленное из-за очереди на GPU, а не из-за сложности ризонинга), детальная аналитика инференса в виде эффективности батчинга, использования KV-кеша, пропускная способность памяти и так далее. Есть интеграция из коробки с vLLM/TensorRT и интересные штуки типа дашборда сравнения стоимости облачных API с собственным развертыванием с учетом амортизации железа.
Оверхед: двухслойная архитектура создаёт больший оверхед чем у конкурентов. Трейсинг приложений добавляет стандартные ~5-10мс, но сбор GPU-метрик через DCGM добавляет ещё ~2-5мс из-за поллинга. Объем данных значительный: метрики GPU компкатно пишутся в Prometheus (time-series), но трейсы в Tempo могут занимать ~100-200KB на запуск агента при детальном профилировании. При 10K запусков в день с GPU-профилированием это ~1-2GB трейсов + ~500MB метрик ежедневно.
Минусы: тяжелый сетап — нужен весь Prometheus stack (Prometheus, Tempo/Jaeger, Grafana) плюс DCGM для GPU-метрик, что требует хорошей экспертизы для прод-развертывания. Сложная начальная конфигурация для корректной корреляции GPU-метрик с трейсами агентов. Документация построена больше про model ops, чем про агентное применение. Меньше агентоспецифичных функций по сравнению с Langfuse (нет версионирования промптов, feedback loops, dataset management).
Langtrace
Архитектура: TypeScript/JavaScript с PostgreSQL и поверх OpenTelemetry.
Философия: специально для JS/TS экосистемы где доминирует бэкендовый LangChain.js. Решает проблему что большинство инструментов наблюдаемости Python-центричны.
Что умеет: базовый трейсинг для JS-агентов — автоматическое подключение к популярным библиотекам, отслеживание токенов и стоимости, разбивка задержки по фазам, инструменты для экспериментов с промптами. Лучше всего сделано подключение в одну строку для всей JS-экосистемы (LangChain.js, OpenAI SDK, Anthropic SDK) и React-компоненты для встраивания трейсов в UI — можно показывать рассуждения агента конечным пользователям в своих интерфейсах.
Оверхед: асинхронная отправка трейсов добавляет ~3-8мс latency. Объём данных зависит от детализации — типичный Next.js агент генерирует ~30-80KB на запуск. При 50K запусков в день это ~1.5-4GB в PostgreSQL ежедневно. Self-hosted версия требует Redis для кеширования и очереди.
Минусы: собственно, JS/TS, так как python-экосистема богаче во всем для агентов и LLM. Менее зрелый чем Langfuse для сложных многошаговых процессов. Меньшее комьюнити и меньшая интеграция с фреймворками агентов, а документация иногда отстает от функций. Нужна ручная настройка PostgreSQL и Redis. Нет продвинутых функций вроде повтора спана или детекции дрифта.
LangWatch
Архитектура: Python/TypeScript, PostgreSQL, OpenTelemetry бэкенд.
Философия: качество. Наблюдаемость через призму качества — не просто собрать трейсы, а автоматически оценивать качество каждого вывода и отлавливать любые проблемы до того как они поедут к пользователям.
Что умеет: стандартный набор трейсинга плюс QA — интеграция с OpenTelemetry, управление тестовыми наборами для регрессионного тестирования, аналитика по типам отказов, уведомления. Лучше всего сделано: все виды защит (guardrails) с детектом токсичности, персональных данных, галлюцинаций и ответов не по теме в реальном времени. Это фреймворк автоматической оценки с встроенными метриками (точность, релевантность, связность) и поддержкой кастомных оценщиков, есть дашборды качества и многое интересное по теме.
Оверхедх: самый высокий среди всех инструментов из-за оценок в реальном времени. Базовый трейсинг добавляет стандартные ~5-10мс, но каждая guardrail-проверка это дополнительный LLM-вызов: токсичность ~50-100мс, галлюцинации ~100-200мс, релевантность ~80-150мс. Если включены все проверки, добавка может достигать 200-400мс на один вызов. НО! Сейчас они активно работают над чекпоинтами, которое потенциально избавит от части вызовов. Объём данных также больше: ~80-150KB на запуск агента (оригинал��ные трейсы + результаты всех оценок + эмбеддинги для некоторых проверок). При 10K запусков в день это ~800MB-1.5GB ежедневно.
Минусы: защита дает ложные срабатывания в 5-10% случаев — требуется ручная подстройка порогов. Менее зрелая экосистема плагинов по сравнению с Langfuse или Phoenix. Меньший фокус на метриках оптимизации стоимости и экономики токенов. Сложная настройка кастомных оценщиков требует понимания ML. Стоковая версия требует более глубокой донастройки на почти каждом этапе.
Lunary
Архитектура: Node.js бэкенд, PostgreSQL, React фронтенд. Фокус на легкое развертывание. Не поддерживает OpenLLMetry нативно — работает на более низком уровне абстракции.
Философия: простая альтернатива Langfuse с дополнительным акцентом на управление промптами. Для команд которым не нужна вся мощь сложных решений и важен быстрый старт без сложной инфраструктуры.
Что умеет: базовый набор для небольших проектов — автотрейсинг через обертки, метрики токенов и стоимости, сбор обратной связи от пользователей, реестр промптов с версионированием, командная работа. Лучше всего сделано: версионирование промптов с A/B-тестированием и автоматическим откатом при деградации метрик, централизованное управление шаблонами для всех агентов, встроенные инструменты для экспериментов прямо в UI, и действительно легкое развертывание.
Оверхед: минимальный благодаря простой архитектуре — ~3-7мс на запрос. Объем данных меньше чем у конкурентов потому что Lunary не сохраняет столь детальные трейсы: ~15-40KB на запуск агента против 50-150KB у Langfuse. При 20K запусков в день это всего ~300MB-800MB ежедневно. Но эта экономия данных оборачивается меньшей детализацией — нет глубокой иерархии спанов, упрощенное отображение вызова инструментов. На таких объемах из коробки почти не нужно тюнить PostgreSQL.
А что по мультиагентности?
По инструментам для одиночных агентов прошлись, а вот с мультиагентностью все не очень хорошо практически у всех и это стоит прокомментировать отдельно.
Langfuse — относительно лучшая поддержка через интеграцию с LangGraph. Отображает иерархию главный → подчинённые агенты через вложенные трейсы, но нет специализированных визуализаций для межагентной коммуникации.
Phoenix — построен на OpenTelemetry, позволяет строить граф зависимостей между агентами, но без семантики мультиагентных паттернов (делегирование, консенсус).
OpenLIT — фокус на GPU и инфраструктуру, для мультиагентов практически бесполезен.
Langtrace — базовый трейсинг, нет поддержки управления взаимодействием между агентами.
LangWatch — фокус на качество отдельных ответов, слабая поддержка мультиагентных паттернов.
Lunary — нет поддержки сложных мультиагентных систем.
Вывод: это слабое место ВСЕХ инструментов. Никто не имеет родной поддержки для коммуникации агент-агент, механизмов консенсуса, распределения работы. Относительно лучше Langfuse и Phoenix, но через костыли обычных спанов.
Как выбрать правильный инструмент
Если попытаться подбить все сказанное, то получится вот что:
Ваш кейс |
Подходит |
Почему |
|---|---|---|
Стартап/MVP |
Lunary |
Поднимается за 15 минут, минимальные требования |
Прод на LangChain/LangGraph |
Langfuse |
Глубочайшая интеграция, проверенная масштабируемость |
TypeScript/JavaScript стек |
Langtrace |
Родная поддержка JS-экосистемы, React-компоненты |
Self-hosted модели |
OpenLIT |
Единственный с корреляцией GPU и reasoning |
Агентный ресерч и эксперименты |
Phoenix |
Воспроизведение спанов, детект дрифта |
Критичность качества |
LangWatch |
Автоматические проверки токсичности/галлюцинаций |
Важно: трейсинг часто генерирует очень много объемных данных и объем БД может взлетать очень быстро — лучше сразу заручиться поддержкой DBA для тюнинга PostgreSQL под такое.
Тренды и куда все движется
Описанные инструменты сейчас становятся неким базовым минимумом прод-систем на LLM и агентах, но помимо своего существования они же и формируют запрос на расширение функциональности или появление новых отдельных инструментов.
Мультиагентность
Про это мы уже поговорили отдельно, просто фиксируем. Сейчас нет хорошего инструмента, который решил бы все вопросы из коробки и который не зависел бы от фреймворка.
Но здесь интересно добавить, что возможно правила трейсинга придут из протоколов межагентного взаимодействия, например, MCP. Вполне возможно, что мы увидим какие-то MCP-центричные инструменты.
Безопасность
По мере закидывания в LLM персональных данных (и прочего чувствительного) будет формироваться запрос на специфичные функции именно про содержимое данных, детекцию, маскирование (именно нативно и внутренними инструментами) и многое другое. Здесь тоже возможно появление специализированных трейсинг-инструментов.
Непрерывное обучение
Трейсинг — это не просто логи, это фактически цепочка действий, которая после соответствующей фильтрации вполне может стать новым топливом для обучения агентов. Переиспользование в обучении уже отработанных успешных трейсов — это хороший и уже существующий тренд.
Важные напоминания про архитектуру и зачем нужен трейсинг/observability
И зафиналить хочется сначала простыми, но крайне ценными подходами к архитектуре LLM-решений. С одной стороны, «это все и так понятно», а с другой — в реальной жизни многое из этого почему-то забывается и не делается.
Ретроспектива важнее реального времени
Для большинства продуктов критична способность сделать посмертный разбор неудачных запусков: построить точную историю выполнения, понять зависимости между спанами, увидеть где началась каскадная ошибка. Такое вполне себе можно делать офлайн. Исключение — высоконагруженные системы с безумным RPS на агентах и где нужен живой алертинг на аномалии, но, мне кажется, такое на момент написания статьи живет только в громких презентациях, а в жизни ни у кого пока нет.
Валидация инструментов критична
Примерно 40% багов production-агентов связаны с неправильными параметрами вызовов инструментов — неправильными параметрами вызова, выдуманные инструменты, не правильно подобранные инструменты. И это еще раз подводит нас к идее, что правильно спроектировать систему и нарезать инструменты — очень важно. Валидация схемы ПЕРЕД выполнением инструмента должна быть отдельным спаном с чётким success/failure статусом. Это спасает от дорогих ошибок вроде DELETE без условий.
Стоимость рассуждений — главный сюрприз
Команды регулярно недооценивают взлет цены при переходе от простых вызов LLM к агентам. Типичный множитель: 20-50x из-за множественных шагов рассуждений, вызовов инструментов, рефлексий и ошибок в любом из этих этапов. Оптимизация начинается как раз-таки с прозрачности — мы можем контролировать только то, что видим.
Простота побеждает сложность
Большое количество задач решаются решаются правильный архитектурой, монотонной работой над данными и простым ReAct-loop с 3-5 инструментами. Сложная Multi-Agent Orchestration с Supervisor-Subagent-Worker часто бывает вообще не нужна. И observability как раз часто помогает понять в какой момент начинает оверинжириниг. Сложность без необходимости — это технический долг.
Типичные проблемы агентов в проде
И финалим статью списком типичных ошибок, которыми наиболее часто встречаются в проде и которые правильные инструменты (и работа с ними!) призваны найти и починить.
Context Drift
В процессе своей работы контекст раздувается, и агент постепенно уплывает от исходной цели, фокусируясь на деталях последних сообщений и забывая о главном. Проблема случается гораздо чаще, чем о ней принято говорить, потому что происходит еще до того, как случается переполнение контекста. Проблеме переполнения посвящено много, дрифту — нет, но это не менее важно.
Галлюцинации
Агенты выдумывают то, чего нет. ВСЕ, что угодно. Думаю, сталкивались вообще все и в дополнительных комментариях пункт не нуждается.
Цепная/каскадная деградация в RAG
RAG — это в первую очередь про поиск и R сильно важнее G. Если на первых шагах нашлись не те документы, то все последующее не имеет смысла какие бы модели там ни были.
SQL-инъекции и неправильная генерация запроса
Неправильная подстановка параметров в запрос (UPDATE без условий), обращение к таблицам, которых нет.
Злоупотребление/непонимание инструментов
Если инструменты напилены неправильно, то агент может вызывать их по 10 раз за сессию, чтобы получить что-то простое. И важно не забывать и про кэш.
Провал в кроличью нору
Агенты умные и кажется, что чем больше мы им кинем, тем лучше им будет. Но это не так, наоборот, чем лучше мы проделаем работу БЕЗ агентов, тем лучше заработает с ними.
Выводы
С какими бы архитектурами, проблемами и задачами мы бы не сталкивались, трейсинг и наблюдаемость — это супер важно. И такие инструменты важно знать, использовать и — важно — использовать их ХОРОШО.
Спасибо!
Мой крафтовый тг-канальчик про агентов и все-все с ними связанно: Agentic World и просто другие статьи: