Поставь телеметрию для агентов в {{stack}}. Без неё ты слепой: жалоба пользователя приходит — а что произошло, не знаешь.
1. Что логировать (must-have)
Для каждой агентской сессии:
| Поле | Зачем |
|---|---|
session_id | Связать всё одной сессии |
agent_id / model | Какой агент и какая модель |
prompt_version | Связать с версией промта (см. версионирование) |
user_id (если есть) | Сегментация |
started_at / ended_at | Latency |
status | ok / failed / timeout / cancelled |
turn_count | Сколько шагов сделал |
input_tokens / output_tokens / cached_tokens | Cost и кэш-эффективность |
cost_usd | Прямой денежный сигнал |
Для каждого tool call:
tool_name,args(отсанированные),duration_ms,status,error_classresult_size_tokens(большой ответ = риск контекстного флуда)
Для каждой ошибки:
error_class(timeout / quota / validation / model_refusal / loop_detected)turn_index(на каком шаге упало)last_tool
2. Что НЕ логировать
- Полный user input без редакции (PII, секреты)
- Полные body запросов с API-ключами
- Содержимое файлов которые читал агент
- Bearer tokens, cookies, env vars
Что делать вместо: храни хэши или метаданные (длина, тип), и опциональный full payload в защищённом хранилище с retention 7-30 дней.
3. Формат
Структурированный JSON, одна строка на событие:
{"ts":"2026-05-17T10:23:01Z","session_id":"s_1","event":"tool_call","tool":"Read","duration_ms":42,"status":"ok"}
{"ts":"2026-05-17T10:23:01Z","session_id":"s_1","event":"tool_call","tool":"Bash","duration_ms":3800,"status":"timeout","error_class":"timeout"}
Никаких многострочных pretty JSON, никаких free-text логов — будет невозможно агрегировать.
4. Куда складывать
| Объём | Решение |
|---|---|
| Прототип | Локальный JSONL файл + jq |
| До 10М событий/мес | ClickHouse / DuckDB / BigQuery |
| Production | Datadog / Honeycomb / Grafana Loki |
| Trace-ориентированно | OpenTelemetry → любой бэкенд |
OpenTelemetry semantic conventions для GenAI уже есть — используй их, не изобретай свои названия полей.
5. Дашборды (минимум 4)
- Health: success rate, p50/p95/p99 latency, error mix по
error_class - Cost: $ по дню / по агенту / по prompt_version
- Tool usage: топ-tools, % ошибок per tool, latency per tool
- Loop & timeout: сессии с turn_count > N или статусом timeout
На каждой диаграмме — последняя релизная отметка (вертикальная линия) чтобы видеть регрессии.
6. Алерты
Не больше 5-7, иначе игнор:
- Error rate > X% за 15 мин
- p95 latency > Y сек за 15 мин
- Cost-per-session > Z (drift промта)
- Loop detection: turn_count > N в > M% сессий
- Tool timeout rate > X%
7. Trace-ы для дебага
Для одной проблемной сессии должно быть видно:
- Все turns с input/output (с редакцией)
- Все tool calls, в каком порядке, с какими args
- Все ошибки с stack traces
Это самое ценное при разборе жалобы. Без traces ты гадаешь.
8. Privacy и retention
- PII в логах хранится не дольше N дней (юр.требования)
- Доступ к full payload — по запросу, с аудитом
- В дашбордах — агрегаты, не сырое
- Если регион требует — pin storage в нужный регион
9. Workflow при инциденте
- Алерт стрелял → открыть Health
- Найти timestamps скачка
- Глянуть Cost / Tool usage — что изменилось
- Сравнить с предыдущим
prompt_version— релиз был? - Открыть 5 traces проблемных сессий → найти паттерн
- Зафиксировать в incident-doc, прикрутить regression-test
Анти-паттерны
console.logв проде без агрегатора- Полные prompt+response в логи (PII, токены)
- Нет
prompt_version— невозможно связать релиз и регрессию - 30 алертов — никто не читает
- Trace без correlation ID — невозможно собрать сессию
На выходе
- Список полей с примером JSONL
- Конфиг логгера / OTel exporter
- 4 дашборда (Health / Cost / Tools / Loops)
- 5-7 алертов
- Документ "что делать при инциденте"
Мониторинг и алёрты
Что мерить, какие алёрты ставить, как не превратить on-call в ад.
Eval-фреймворк для LLM
Как мерить качество промтов и агентов: test set, метрики, автоматизация.
A/B-тест промтов
Сравнить две версии промта статистически, не на глаз.