Инженерная трасса
Продуктовая телеметрия ядра (/v1/stats, spend, cron_runs) отвечает на
вопрос «как дела вообще». Трасса отвечает на другой: почему сломался вот
этот тур. Какой именно запрос уехал провайдеру, когда он ответил 400; из
какого запроса родился этот вызов инструмента; сколько тур ждал сеть, а
сколько — человека.
Принцип один: сначала записывай факты, толкуй потом. Горячий путь тура только дописывает события и складывает полные тела — он не строит никакой итоговой картины. Толкование — чистая функция над записью: когда понимание отказа меняется, редьюсер переписывается и прогоняется по старым трассам заново.
Включение
Переменная окружения на процессе ядра:
EVA_TRACE_DIR=/var/lib/eva/trace eva-kernel --config config.yaml
Выключено (по умолчанию) — накладных расходов ноль: по горячему пути вместо
контекста трассы лежит None. Записи никуда не выгружаются — это
диагностика на своём диске, не телеметрия.
Что пишется
На каждый корневой тур — свой каталог <started_ms>-<turn_id>:
| Файл | Что в нём |
|---|---|
manifest.json | id трассы (свой, отдельный от id тура), id тура и чата, время старта, ревизия ядра |
trace.jsonl | лента событий, только дописывается: монотонный seq, at_ms, turn, kind |
payloads/*.json | полные тела: запросы к провайдеру, ответы, аргументы и выхлопы инструментов — без потолков |
payloads/*-prompt.txt | человекочитаемый снимок каждого запроса: точный вход модели диффабельным текстом |
События: turn_started, provider_request / provider_response /
provider_error, usage, tool_call / tool_result (с длительностью),
rule_fired, cancelled, turn_finished / turn_failed. Вызов несёт
номер итерации — по нему видно, какой запрос его породил.
Подагенты наследуют контекст трассы от тимлида и пишут в тот же каталог под id своих туров — дерево команды разбирается по одной ленте.
Разбор: eva-trace
Толкование — отдельный бинарь, которому нужен только каталог:
eva-trace /var/lib/eva/trace/1754650000000-<turn_id>
Печатает таймлайн тура: каждый поход к провайдеру с длительностью и ссылкой на тело, вызовы инструментов с итерацией-родителем и временем работы, расход токенов и денег, финал тура. В конце — итоги: сколько ждали провайдера, сколько работали инструменты, полная цена.
Родня
- Снимок промпта из
payloads/*-prompt.txt— тот же текст, что стерегут снимковые тесты сборки промпта (src/snapshots/, insta): регрессия сборки — однострочный дифф снимка. - Мок-провайдер проверяет инварианты каждого запроса (сопряжённость пар
tool_use/tool_result, непустая системная часть, последний ход — за пользователем) паникой — весь тестовый набор стережёт их, ничего о них не зная. - Трасса не подменяет бенчмарк (
benchmark/, крейт eva-bench): бенчмарк меряет качество на сценариях, трасса объясняет один конкретный отказ.