Pour Qui Est Agent Trace ?

Cursor a publié Agent Trace, une spécification ouverte pour suivre quel code dans un dépôt a été écrit par un LLM. Elle enregistre le modèle, l’outil, la conversation et les plages de lignes exactes — le tout ajouté à un fichier JSONL dans votre projet.

Le pitch : “Au fur et à mesure que les agents écrivent plus de code, il est important de comprendre ce qui provient de l’IA par rapport aux humains.”

J’ai passé du temps à lire la spécification et l’implémentation de référence. L’ingénierie est solide — schéma propre, extensibilité réfléchie, bonne liste de partenaires (Amp, Amplitude, Cloudflare, Cognition, Google, Vercel). Mais je revenais sans cesse à une question : que fait-on avec ces données ?

Ce Qu’elle Capture

Chaque fois qu’un LLM édite un fichier, un hook se déclenche et enregistre une trace : quel modèle, quel outil, quelles lignes, quelle conversation. L’implémentation de référence gère les événements de Cursor et de Claude Code :

// Du hook de référence — les événements arrivent via 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 },
}));

La spécification définit quatre types de contributeurs — human, ai, mixed, unknown — et prend en charge l’attribution au niveau de la ligne avec des hachages de contenu pour suivre le code qui se déplace. Elle est neutre vis-à-vis des fournisseurs, agnostique vis-à-vis des VCS et extensible via des métadonnées avec espaces de noms.

En tant que format de données, c’est bien conçu. La question est ce qu’elle permet.

Le Défi de l’Attribution

La spécification modélise la paternité comme une classification. Mais le codage assisté par LLM est une conversation. Vous décrivez ce que vous voulez. Le LLM génère quelque chose. Vous modifiez la moitié, rejetez une fonction, demandez une révision, acceptez la deuxième tentative, puis corrigez manuellement un cas limite. Plus tard, un autre LLM refactorise tout le bloc.

Qui a écrit ce code ? La frontière entre la paternité humaine et LLM est floue, et elle devient de plus en plus floue. La plupart du code réel finira comme mixed, et si presque tout est mixed, la classification ne vous dit pas grand-chose.

L’attribution au niveau de la ligne a aussi un problème de durée de vie. Une trace dit “Claude a écrit les lignes 10-50 au commit abc123.” Deux commits plus tard, quelqu’un reformate ce bloc ou en extrait une fonction. La réponse de la spécification est de chaîner via git blame, et les hachages de contenu peuvent aider à suivre le code qui se déplace. Mais dans les workflows avec des rebases et des squash-merges, la chaîne se casse. Ce sont des problèmes difficiles — le genre qu’un RFC précoce devrait mettre en évidence.

L’Action Manquante

La spécification écarte explicitement les usages évidents : pas pour la propriété du code, pas pour l’évaluation de la qualité, pas pour la provenance des données d’entraînement. Elle dit “transparence”. Mais la transparence est un moyen, pas une fin.

Si le code passe la revue et les tests, qu’est-ce qui change parce qu’un LLM l’a écrit ? S’il est bogué, vous le corrigez de toute façon. La spécification ne relie jamais l’attribution à une action concrète. Les données entrent, mais il n’y a pas de moyen défini d’obtenir des réponses. C’est le fossé — pas le format, mais le cas d’usage.

Là Où Ça Devient Intéressant

Voici ce que je pense qu’Agent Trace vise réellement, même si la spécification ne le dit pas encore.

Derrière chaque fonction générée par LLM, il y a des jetons de raisonnement, des fausses pistes, des nouvelles tentatives, des changements de contexte et des invocations d’outils. Un agent ne produit pas seulement du code — il passe par un processus pour y arriver. Il lit des fichiers, comprend mal une interface, revient en arrière, essaie une approche différente, exécute un test, corrige l’échec et arrive à une solution. Ce processus est invisible dans le diff final.

Le hook capture déjà plus que la simple attribution. Regardez la surface d’entrée :

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;
}

Modèle, session, conversation, outil, commande, durée, si c’est un agent en arrière-plan, le mode compositeur, chaque invocation d’outil avec son entrée. Ce ne sont pas seulement des données d’attribution. Ce sont des données de processus. Et les données de processus sont là où réside la vraie valeur :

La Bonne Question

Agent Trace en est à ses débuts. C’est un RFC avec de vrais défis autour de la modélisation de l’attribution, de la durabilité des plages et de la sémantique des requêtes. Mais l’instinct est bon — à mesure que les LLM écrivent plus de code, nous avons besoin de données structurées sur la façon dont cela se produit.

La version la plus utile de cette spécification pourrait ne pas être “qu’a écrit le LLM ?” mais “comment le LLM y est-il arrivé ?”. Le grand livre au niveau de la ligne est un point de départ. La trace du processus — le raisonnement, les itérations, le coût d’arriver à une solution — c’est là que cela devient quelque chose que les équipes utilisent réellement pour écrire un meilleur code avec les LLM.

C’est la spécification sur laquelle je voudrais construire.