Для Кого Предназначен Agent Trace?
Cursor выпустил Agent Trace — открытую спецификацию для отслеживания того, какой код в репозитории был написан LLM. Она записывает модель, инструмент, диалог и точные диапазоны строк — всё это добавляется в JSONL-файл в вашем проекте.
Презентация: “Поскольку агенты пишут всё больше кода, важно понимать, что пришло от ИИ, а что от людей.”
Я потратил время на чтение спецификации и эталонной реализации. Инженерная работа солидная — чистая схема, продуманная расширяемость, хороший список партнёров (Amp, Amplitude, Cloudflare, Cognition, Google, Vercel). Но я постоянно возвращался к одному вопросу: что вы делаете с этими данными?
Что Она Фиксирует
Каждый раз, когда LLM редактирует файл, срабатывает хук и записывается трассировка: какая модель, какой инструмент, какие строки, какой диалог. Эталонная реализация обрабатывает события как от Cursor, так и от Claude Code:
// Из эталонного хука — события поступают через stdin
appendTrace(createTrace("ai", input.file_path!, {
model: input.model,
rangePositions,
transcript: input.transcript_path,
metadata: { conversation_id: input.conversation_id, generation_id: input.generation_id },
}));
Спецификация определяет четыре типа участников — human, ai, mixed, unknown — и поддерживает атрибуцию на уровне строк с хешами содержимого для отслеживания перемещающегося кода. Она нейтральна к поставщикам, агностична к VCS и расширяема через метаданные с пространствами имён.
Как формат данных, это хорошо спроектировано. Вопрос в том, что это позволяет.
Проблема Атрибуции
Спецификация моделирует авторство как классификацию. Но кодирование с помощью LLM — это диалог. Вы описываете, что хотите. LLM генерирует что-то. Вы редактируете половину, отклоняете функцию, просите доработку, принимаете вторую попытку, а затем вручную исправляете крайний случай. Позже другая LLM рефакторит весь блок.
Кто написал этот код? Граница между человеческим и LLM-авторством размыта, и становится всё более размытой. Большая часть реального кода окажется mixed, и если почти всё mixed, классификация не говорит вам многого.
Атрибуция на уровне строк также имеет проблему срока годности. Трассировка говорит: “Claude написал строки 10-50 в коммите abc123.” Через два коммита кто-то переформатирует этот блок или извлечёт из него функцию. Ответ спецификации — цепочка через git blame, и хеши содержимого могут помочь отследить перемещающийся код. Но в рабочих процессах с rebase и squash-merge цепочка разрывается. Это сложные проблемы — те, которые должен поднимать ранний RFC.
Отсутствующее Действие
Спецификация явно отказывается от очевидных применений: не для владения кодом, не для оценки качества, не для происхождения обучающих данных. Она говорит “прозрачность”. Но прозрачность — это средство, а не цель.
Если код проходит проверку и тесты, что меняется из-за того, что его написала LLM? Если в нём есть ошибки, вы всё равно их исправляете. Спецификация никогда не связывает атрибуцию с конкретным действием. Данные поступают, но нет определённого способа получить ответы. Вот в чём разрыв — не формат, а вариант использования.
Где Становится Интересно
Вот на что, по моему мнению, на самом деле указывает Agent Trace, даже если спецификация этого пока не говорит.
За каждой функцией, сгенерированной LLM, стоят токены рассуждений, ложные повороты, повторные попытки, переключения контекста и вызовы инструментов. Агент не просто производит код — он проходит процесс, чтобы до него добраться. Он читает файлы, неправильно понимает интерфейс, откатывается назад, пробует другой подход, запускает тест, исправляет ошибку и приходит к решению. Этот процесс невидим в финальном diff.
Хук уже захватывает больше, чем просто атрибуцию. Посмотрите на входную поверхность:
interface HookInput {
hook_event_name: string;
model?: string;
transcript_path?: string | null;
conversation_id?: string;
generation_id?: string;
session_id?: string;
file_path?: string;
edits?: FileEdit[];
command?: string;
duration?: number;
is_background_agent?: boolean;
composer_mode?: string;
tool_name?: string;
tool_input?: { file_path?: string; new_string?: string; old_string?: string; command?: string };
tool_use_id?: string;
}
Модель, сессия, диалог, инструмент, команда, продолжительность, фоновый ли это агент, режим композитора, каждый вызов инструмента с его входом. Это не просто данные об атрибуции. Это данные о процессе. А данные о процессе — это то, где находится настоящая ценность:
- Оценки. Какие модели испытывают трудности с какими паттернами? Функция, которая заняла одну попытку, отличается от той, которая заняла двенадцать попыток — даже если результат идентичен. Не “кто написал”, а “насколько сложно было произвести”.
- Кодовые базы, нативные для агентов. Если агенты постоянно испытывают трудности с модулем — много ложных поворотов, высокий процент повторных попыток, повторяющаяся путаница с контекстом — это сигнал о том, что код не структурирован под то, как работают агенты. Вы можете рефакторить для ясности, лучших интерфейсов, более явных контрактов. Данные трассировки становятся картой того, где ваша кодовая база враждебна к сотрудничеству с LLM.
- Оптимизация процесса. Какие конфигурации инструментов производят лучший код с первой попытки? Какие паттерны промптов уменьшают откат назад? На эти вопросы нельзя ответить на основе атрибуции строк. Вам нужен путь, а не пункт назначения.
Правильный Вопрос
Agent Trace находится на ранней стадии. Это RFC с реальными проблемами в области моделирования атрибуции, устойчивости диапазонов и семантики запросов. Но интуиция правильная — по мере того как LLM пишут больше кода, нам нужны структурированные данные о том, как это происходит.
Самая полезная версия этой спецификации может быть не “что написала LLM?”, а “как LLM до этого добралась?”. Реестр на уровне строк — это отправная точка. Трассировка процесса — рассуждение, итерации, стоимость достижения решения — вот где это становится тем, что команды действительно используют для написания лучшего кода с LLM.
Вот спецификация, на которой я хотел бы строить.