← LLMOps and agent observability: debugging the black box
07 / 07 · 60 min

Capstone: trace detective

Diagnosing a failing production agent from raw traces: aggregates, reading a sample, root-cause evidence, and an RCA report with eval cases against recurrence.

Lesson content is currently available in Russian.

What you will learn

  • →Вести расследование по сырым трейсам: от агрегатов и таймлайна к чтению деревьев и доказательствам.
  • →Опознавать в сырых данных циклы, распухший контекст, сломанные инструменты и тихую смену модели.
  • →Оформлять RCA-отчёт с trace-id-доказательствами, фиксами первопричин и регрессионными кейсами.

Дано: зелёный uptime, красные отзывы

Сценарий капстоуна. Агент поддержки интернет-магазина работает в проде полгода: инструменты search_orders, get_policy, create_ticket, retrieval по базе знаний, модель за алиасом провайдера. Две недели назад всё было спокойно; сейчас поддержка завалена жалобами «бот отвечает не то и подвисает», доля 👎 выросла втрое. При этом дашборд доступности безмятежно зелёный: 200 OK, error rate у API в норме. Знакомая по уроку 5 картина — значит, копать надо в качество и трейсы.

Вам выдают выгрузку: ~500 трейсов за 14 дней в JSONL — по спану на строку, с trace_id, parent_span_id, таймстемпами, статусами, атрибутами gen_ai.* у генераций, аргументами и результатами tool-спанов, скорами фидбэка на трейсах. Никакого UI — только сырые данные, скрипты и метод. Это намеренно: платформа наблюдаемости может смениться, а навык читать сырые трейсы остаётся.

Задача из трёх частей: найти первопричины деградации (спойлер сценария: их больше одной — в реальных инцидентах дефекты любят накладываться); доказать каждую конкретными trace_id и полями, а не впечатлениями; предложить фиксы и регрессионные кейсы, закрывающие рецидив.

Правила детектива, выстраданные предыдущими уроками: сначала агрегаты, потом чтение отдельных трейсов — иначе утонете; гипотезы записываются до проверки, чтобы данные не подгонялись под первое впечатление; вывод без доказательства — не вывод, а версия.

Шаг 1: агрегаты и таймлайн

Расследование начинается с цифр по дням — они сужают область поиска с 500 трейсов до нескольких подозреваемых сегментов. Минимальный набор: число трейсов, p50/p95 длительности, среднее и максимальное число спанов на трейс, распределение finish_reasons, error rate по каждому имени инструмента, суммарные input_tokens, доля 👎.

import json, collections

by_day = collections.defaultdict(lambda: collections.Counter())
spans_per_trace = collections.Counter()

for line in open("traces.jsonl"):
    s = json.loads(line)
    day = s["start_time"][:10]
    spans_per_trace[s["trace_id"]] += 1
    attrs = s.get("attributes", {})
    for fr in attrs.get("gen_ai.response.finish_reasons", []):
        by_day[day]["finish:" + fr] += 1
    if s.get("kind") == "tool" and s.get("status") == "ERROR":
        by_day[day]["tool_error:" + s["name"]] += 1

Дальше — таймлайн и точки перелома. Ищете день, когда метрика сломала тренд, и синхронные изменения: «с 9-го числа среднее число спанов выросло с 6 до 19, p95 — с 8 до 40 секунд» — гипотеза о циклах; «с 11-го доля finish_reason = length подскочила с 1% до 15%, суммарные input_tokens удвоились» — гипотеза о распухшем контексте; «error rate search_orders с 12-го держится на 30%» — гипотеза о сломанном инструменте.

Итог шага — таблица «дата перелома → аномалия → гипотеза», где гипотез обычно две-четыре. Обратите внимание: разные даты переломов почти наверняка означают разные независимые первопричины — не пытайтесь объяснить всё одной.

Шаг 2: чтение трейсов и сбор доказательств

Из каждого аномального сегмента возьмите 5–10 трейсов и восстановите деревья (сортировка спанов по parent_span_id и таймстемпам). Вот как типовые находки выглядят в сырых данных:

  • Цикл: подряд пять tool-спанов search_orders с одинаковым аргументом {"order_id": "ORD-000000"} — модель выдумала несуществующий номер и долбит поиск; после пятого повтора — капитуляция «не могу найти заказ». Доказательство: trace_id + последовательность идентичных вызовов;
  • Сломанный инструмент: с 12-го числа все спаны search_orders со status = ERROR и одинаковым текстом исключения (смена схемы ответа внешнего API). Коварная часть — трейсы завершаются OK: агент отвечает про заказы «по памяти», из общих соображений. Классическая проглоченная ошибка из урока 4;
  • Распухший контекст: в длинных сессиях input_tokens генераций растут по шагам — 3k, 18k, 60k, 115k — затем finish_reason = length; сопоставив с датой деплоя, находите релиз, где сломали обрезку истории;
  • Тихая смена модели: с 9-го числа gen_ai.response.model отличается от привычного при неизменном gen_ai.request.model — провайдер переключил алиас, и стиль ответов «поплыл», что видно по скорам фидбэка именно на этой модели.

Форма доказательства всегда одна: конкретные trace_id, конкретные поля, конкретные числа. «Кажется, агент зацикливается» — версия; «в 41 трейсе после 9-го числа ≥4 идентичных вызова search_orders подряд, примеры: trace abc123, def456» — доказательство. Держите для каждой гипотезы и контрпример: если контекст распухал и до 11-го числа, гипотеза о дате деплоя неверна.

Шаг 3: RCA-отчёт и закрытие петли

Финальный артефакт — RCA-отчёт (root cause analysis), по которому команда чинит систему, а не спорит о впечатлениях. Структура:

Формат отчёта

  • Симптом — что видел бизнес: метрика фидбэка, график с датой перелома;
  • Находки — по одной на первопричину: механизм (как именно дефект приводит к плохим ответам), масштаб (доля затронутых трейсов), доказательства (trace_id, поля, числа), дата и триггер (деплой, смена алиаса, изменение внешнего API);
  • Фиксы — на каждую находку короткий (остановить кровь: откат, лимит итераций) и системный (устранить класс: детект повторов, проброс ошибок инструментов в контекст, бюджет контекста, пиннинг версии модели);
  • Регрессионные кейсы — какие кейсы уходят в eval-сет по каждой находке;
  • Алёрты — какие сигналы из урока 5 поймали бы это на сутки раньше (расхождение response/request model, доля length, error rate инструмента, рост спанов на трейс).

Критерии качества: каждый вывод воспроизводим — читатель с той же выгрузкой приходит к тем же числам; фиксы адресуют первопричины, а не симптомы («увеличить таймаут» не лечит цикл); последние два раздела превращают разовое расследование в постоянную защиту — это и есть петля из урока 6, замкнутая на реальном инциденте.

Если отчёт написан хорошо, следующий такой инцидент не потребует детектива: его поймает алёрт, объяснит сегментированный дашборд, а регрессию заблокирует CI-гейт. В этом и есть смысл курса — превратить отладку чёрного ящика из искусства в конвейер.

Practice

Расследование от начала до конца

Соберите датасет для расследования: либо экспортируйте 200+ трейсов своего агента, подложив в него два дефекта (например, сломайте обрезку истории и «уроните» один инструмент), либо сгенерируйте синтетическую выгрузку скриптом. Передайте выгрузку напарнику (или пройдите сами «вслепую» через неделю): агрегаты по дням, таймлайн переломов, чтение выборки, доказательства, RCA-отчёт по формату урока.

Deliverable

RCA-отчёт: все заложенные первопричины найдены и доказаны trace_id и полями, по каждой — короткий и системный фикс, минимум 8 регрессионных eval-кейсов и 3 алёрта, которые поймали бы инцидент раньше.

Checkpoint

Защитите свой RCA-отчёт: проведите слушателя от симптома через доказательства к фиксам и покажите, почему инцидент не повторится молча.

  • ✓ Порядок расследования соблюдён: агрегаты и таймлайн до чтения отдельных трейсов, гипотезы зафиксированы до проверки.
  • ✓ Каждая первопричина доказана конкретными trace_id и полями (finish_reasons, статусы tool-спанов, response.model, input_tokens), найдены все независимые дефекты.
  • ✓ Отчёт закрывает петлю: фиксы первопричин, регрессионные кейсы в eval-сете и алёрты на раннее обнаружение.

Check yourself

Почему расследование начинают с агрегатов по дням, а не с чтения трейсов?

01Почему расследование начинают с агрегатов по дням, а не с чтения трейсов?

Два перелома метрик в разные даты. О чём это почти наверняка говорит?

02Два перелома метрик в разные даты. О чём это почти наверняка говорит?

Все спаны инструмента после даты X падают с ошибкой, но трейсы завершаются OK и агент уверенно отвечает. Что это?

03Все спаны инструмента после даты X падают с ошибкой, но трейсы завершаются OK и агент уверенно отвечает. Что это?

Что отличает доказательство от версии в RCA-отчёте?

04Что отличает доказательство от версии в RCA-отчёте?

Зачем в RCA-отчёте разделы «регрессионные кейсы» и «алёрты», если первопричины уже найдены?

05Зачем в RCA-отчёте разделы «регрессионные кейсы» и «алёрты», если первопричины уже найдены?

Sources

Capstone: trace detective · LLMOps and agent observability: debugging the black box · VORCL