Les skills que mon agent ne voyait pas
J’avais 84 skills installés et je supposais que les 84 fonctionnaient. Cinq ne fonctionnaient pas. swiftui, testing-philosophy, typeset, web-performance et update-shortcuts-guide parvenaient au modèle réduits à un simple nom, sans aucune description, alors que leurs fichiers sur le disque portaient des descriptions parfaitement valables. Un skill sans description ne peut pas être routé, parce que la description est le signal de routage. Ces cinq-là ne pouvaient jamais s’activer automatiquement, et rien nulle part ne me l’a signalé. Aucune erreur, aucun avertissement, aucune ligne de log. Je les ai découverts par hasard, et la seule raison pour laquelle j’ai pu prouver la cause, c’est que le correctif a inversé le phénomène sous mes yeux.
{.answer-block}
En bref
- Les descriptions de skills sont chargées dans le contexte à chaque tour et partagent un budget fixe de caractères. Dépassez-le et les descriptions sont supprimées silencieusement.12
- J’avais 84 skills installés, dont 82 portaient une description, pour un total de 21,848 caractères. Cinq sont arrivés avec le nom présent et la description absente. Sur le disque, ces cinq-là comptaient de 206 à 336 caractères chacun.
- Aucun attribut de fichier n’expliquait lesquels avaient sauté. Longueur de description, taille du fichier, format YAML, décalage entre
nameet le dossier, date de modification : tout se recoupait entre les supprimés et les conservés. - J’ai réécrit 74 descriptions pour ramener le total de 21,848 à 9,885 caractères. Les cinq skills jusque-là invisibles sont réapparus en pleine session, dans la même conversation, description intacte. Hypothèse, intervention, confirmation.
- Le budget exact n’est pas documenté et fait aujourd’hui débat. Anthropic a des tickets ouverts signalant que la fraction est calculée sur une base fixe de 200K en ignorant l’extension de contexte à 1M.34
- La règle de réécriture qui a permis de tenir dans le budget : la seule mission d’une description est de répondre à quand faut-il l’invoquer. La procédure, la philosophie et les chemins de fichiers appartiennent au corps, qui n’est chargé qu’à l’invocation.
Une panne sans message d’erreur
La plupart des bugs de harness s’annoncent d’eux-mêmes. Un hook sort avec un code non nul, un serveur MCP refuse de démarrer, un appel d’outil renvoie une trace d’exécution. Le budget de descriptions ne fait rien de tout cela. Il sert discrètement au modèle une liste plus courte que celle qui se trouve sur votre disque, et chaque symptôme en aval ressemble à un problème de modèle plutôt qu’à un problème de plomberie.
Je m’en suis aperçu en lisant ma propre fenêtre de contexte plutôt que mon système de fichiers. En parcourant la liste des skills, cinq entrées avaient un nom et rien après. Toutes les autres avaient un nom et une phrase. J’ai récupéré les fichiers :
swiftui HAS 322 chars on disk -> DROPPED in context
testing-philosophy HAS 291 chars on disk -> DROPPED in context
typeset HAS 248 chars on disk -> DROPPED in context
web-performance HAS 206 chars on disk -> DROPPED in context
update-shortcuts-guide HAS 336 chars on disk -> DROPPED in context
La conséquence est pire qu’un skill lent ou incorrect. Un agent décide d’invoquer un skill en lisant sa description. Retirez la description et vous n’avez pas dégradé le routage, vous l’avez supprimé. Le skill est installé, valide et inatteignable. swiftui est mon skill de patterns iOS 26, ce qui veut dire que chaque session Swift que j’ai lancée volait sans lui.
Anthropic a des tickets ouverts qui décrivent la même panne, dont un intitulé « Skill description budget silently truncates routing information, causing skill routing failures ».2 Le comportement est donc un bug connu, pas une mauvaise configuration locale. C’était utile à apprendre, et cela ne m’a pas aidé à trouver lesquels de mes skills étaient touchés.
Écarter les réponses faciles
La tentation était de deviner le mécanisme et de corriger. J’ai d’abord cherché à falsifier les hypothèses, parce que « cinq skills sont cassés » et « cinq skills sont cassés pour telle raison » sont deux affirmations très différentes.
Si une propriété au niveau du fichier désignait un skill pour la suppression, le groupe supprimé devrait se distinguer du groupe conservé quelque part de mesurable. Je les ai comparés :
| Propriété | Supprimés (5) | Conservés (77) |
|—|—|
| Longueur moyenne de description | 280 caractères | 266 caractères |
| Taille moyenne du fichier | 9,106 octets | 7,608 octets |
| Description YAML en scalaire de bloc | 2 sur 5 | 30 sur 77 |
| name différent du dossier | 1 sur 5 | 4 sur 77 |
| Date de modification | de janvier à juillet | de janvier à juillet |
Rien ne les séparait. Les descriptions supprimées n’étaient pas les plus longues, les fichiers n’étaient pas particulièrement volumineux, le style YAML était mélangé dans les deux groupes et les dates de modification couvraient la même période. La position alphabétique échouait elle aussi : les skills classés après swiftui gardaient leur description.
À ce stade, la position honnête était que j’avais un symptôme reproductible et aucun mécanisme. Je l’ai donc écrit ainsi et je suis parti chercher un test plutôt qu’une théorie.
Le test
Si c’est le total qui compte, alors réduire ce total devrait restaurer les descriptions supprimées, quels que soient les fichiers que je coupe. La prédiction est falsifiable et peu coûteuse.
J’ai réécrit 74 descriptions, faisant passer le total de 21,848 caractères à 9,885. Les cinq skills jusque-là invisibles sont revenus avec leur description, dans la même session, sans redémarrage.
C’est toute l’expérience. Une prédiction, une intervention, une confirmation. La suppression dépend de la taille agrégée, pas d’une propriété du fichier individuel, ce qui explique précisément pourquoi aucun attribut par fichier ne pouvait distinguer les deux groupes.
Un bug qui ne laisse aucune trace laisse tout de même un contrefactuel. Si vous ne trouvez pas la cause en inspectant la panne, changez une variable et regardez si la panne suit.
Je tiens à être précis sur ce que je n’ai pas établi. Je ne connais pas le budget exact, et je ne vais pas publier un chiffre que je ne peux pas sourcer. La documentation officielle omet la limite.5 Les mesures de la communauté situent le plafond pratique autour de 15,500 à 16,000 caractères et relèvent environ 109 caractères de surcoût par entrée, dus aux balises XML, au nom du skill et au champ d’emplacement, dont rien n’est capturé par un simple décompte des caractères de description.6 Avec 84 skills, ce seul surcoût représente environ 9,156 caractères. Parallèlement, des contributeurs d’Anthropic rapportent que la fraction du budget est calculée sur une base fixe de 200K et ignore l’extension de contexte à 1M, de sorte que deux sessions sur la même machine peuvent obtenir des budgets différents.34
Ma première rédaction de cette découverte affirmait que ma configuration dépassait le budget de 119%. J’avais multiplié une hypothèse non vérifiée (1% d’une fenêtre de 1M) par une mesure réelle, et produit un chiffre assuré qui ne reposait sur rien. Les faits observés tiennent : 21,848 caractères ont fait sauter cinq descriptions, 9,885 n’en ont fait sauter aucune. Le pourcentage, lui, n’a pas tenu, et il n’aurait jamais dû être écrit.
La seule mission d’une description, c’est le routage
Couper 12,000 caractères semble destructeur. Ça ne l’était pas, parce que l’essentiel de ce qui vivait dans ces descriptions ne faisait aucun travail de routage.
Voici ce qu’annonçait mon skill jiro, en 686 caractères :
Philosophie d’artisanat shokunin pour la qualité du code et la fierté professionnelle. S’active lors de l’implémentation de fonctionnalités, du refactoring, de l’écriture de tests, de la relecture de travaux, ou de tout changement non trivial sur FastAPI/Python, Swift/SwiftUI, les frontends HTMX et le code d’infrastructure. Intègre trois philosophies fondamentales : Shokunin (l’excellence dans les détails invisibles), Omotenashi (le service par le métier), Rick Rubin (canalisation et distillation créatives). Point de décision central : l’Evidence Gate (produire la preuve de la qualité, pas un sentiment à son sujet). À utiliser quand : construire des fonctionnalités, refactorer, tester, relire du code, corriger des bugs, ou tout travail où une preuve de qualité est exigée avant d’annoncer l’achèvement.
Environ 500 de ces caractères expliquent ce que le skill contient. Rien là-dedans n’aide à décider s’il faut l’ouvrir. Le remplacement fait 126 caractères :
Standards d’artisanat et de preuve pour la qualité du code. À utiliser lors de l’implémentation, du refactoring, des tests, des relectures ou de la correction de bugs.
Mêmes mots déclencheurs, même comportement de routage, un cinquième du coût. La philosophie n’a pas disparu ; elle vit dans le corps, qui n’est chargé que lorsque le skill s’exécute vraiment. La payer à chaque tour n’apportait rien.
Le schéma s’est répété sur l’ensemble. Neuf skills update-*-guide portaient 3,024 caractères de boilerplate quasi identique sur le balayage des sources, la synchronisation des copies et l’exécution des traductions. Ramenés à environ 115 caractères chacun, ils routent toujours correctement, parce que ce qui les distingue, c’est le guide qu’ils mettent à jour, pas le pipeline qu’ils partagent.
Trois règles ont fait le travail :
- Gardez le déclencheur, coupez l’explication. Les noms, les commandes slash et les mots qu’un utilisateur taperait réellement restent. Les descriptions de procédure interne partent.
- Les chemins de fichiers appartiennent au corps. Un chemin ne peut pas aider le modèle à décider quand invoquer quelque chose.
- Le boilerplate partagé est du surcoût pur. Si neuf skills disent la même phrase, cette phrase n’en distingue aucun.
La seconde taxe : des descriptions qui agissent sans être appelées
L’élagage a mis au jour un coût plus subtil. Onze de mes descriptions, 3,808 caractères au total, portaient un langage impératif : ALWAYS, NEVER, MUST, PROACTIVELY, BEFORE. distribute disait NEVER. no-shortcuts disait ALWAYS. git-custody disait BEFORE.
Ces mots siègent dans le contexte à chaque tour, que le skill s’exécute ou non. Ils se lisent comme des instructions parce qu’ils sont écrits comme des instructions, et le modèle n’a aucun moyen fiable de traiter une description comme un texte de catalogue inerte tout en traitant une instruction système formulée de façon identique comme contraignante.
Des travaux récents nomment l’effet. « The Regression Tax », mesuré sur environ 6,000 exécutions, deux benchmarks d’automatisation bureautique et trois piles de harness, identifie l’osmose des descriptions de skills : un skill qui modifie le comportement de l’agent par sa seule présence dans le contexte, même sans jamais être invoqué.1 Sa conclusion principale : les meilleurs skills l’emportent en régressant moins plutôt qu’en apportant davantage, et les skills surinvestissent dans les consignes procédurales tout en sous-investissant dans l’ancrage et la vérification.
La preuve en production est arrivée avant la théorie. Anthropic a fait marche arrière sur l’auto-activation des skills intégrés /verify et /code-review en v2.1.215, en les réservant à une invocation explicite.7 Deux versions plus tard, /deep-research a cessé lui aussi de s’auto-invoquer.8 Ce sont des skills lourds dont les exécutions non sollicitées coûtaient plus qu’elles ne rapportaient : de l’osmose observée en conditions réelles par l’éditeur, et corrigée en supprimant l’activation plutôt qu’en réécrivant la description.
Une description surdimensionnée coûte donc deux fois. Elle consomme le budget dont d’autres skills ont besoin pour leur routage, et elle exerce une pression comportementale que personne n’a demandée. Les deux coûts tombent sur des tours où le skill n’apporte rien.
La partie inconfortable : le corps ne gouverne peut-être pas davantage
« Déplacez-le dans le corps » est le conseil que je viens de donner, et il porte une hypothèse qu’il vaut mieux énoncer à voix haute : qu’une procédure chargée par l’agent au moment de l’invocation gouverne réellement ce que fait l’agent. De nouveaux travaux de benchmark suggèrent que cette hypothèse est plus fragile qu’il n’y paraît.
HANDBOOK.md a testé exactement cela. Soixante-cinq tâches, des documents de politique de 20 à 124 pages, des agents travaillant sur l’e-mail, la messagerie, les agendas et le commerce dans des entreprises simulées, avec 824 critères d’évaluation programmatiques. La meilleure de trente configurations de modèles a réussi 36.2% des essais, et la plupart des configurations de pointe sont restées sous les 25%.9
Les modes d’échec nommés sont ceux qui comptent ici. Les agents laissent une requête plausible venue de l’environnement l’emporter sur la politique en vigueur. Ils effectuent une vérification requise, puis agissent contre son résultat. Ils perdent le détail des règles sur de longs horizons. Aucun de ces échecs n’est un échec de récupération ; le document était disponible du début à la fin.
La version honnête de ma règle est donc plus étroite que « les descriptions routent, les corps expliquent ». Sortir la procédure de la description reste juste, parce que cela récupère le budget dont d’autres skills ont besoin pour leur routage et empêche un texte jamais invoqué d’orienter le comportement. Ce sont deux gains réels, et aucun ne dépend de la bonne gouvernance du corps. Ce que cela ne vous achète pas, c’est la certitude que la procédure déplacée sera suivie. Un manuel de 124 pages et un corps de SKILL.md de 3,000 mots se situent sur la même courbe.
La lecture pratique : traitez la longueur du corps comme un coût, pas comme une place de stationnement gratuite. Si une règle doit vraiment tenir, une description est le mauvais endroit pour elle, et un corps long n’est qu’à peine meilleur. L’application relève d’un dispositif déterministe (un hook, une règle de permission, un test), pas d’une prose qu’on demande à un modèle de retenir pendant qu’il fait autre chose.
Auditer les vôtres
Commencez à l’intérieur d’une session. Lancez /context, qui indique si des skills ont été exclus.5 S’il signale des exclusions, vous avez le problème et votre diagnostic est terminé.
La raison pour laquelle je n’ai pas commencé là est instructive : mes cinq skills n’étaient pas exclus, ils arrivaient avec le nom intact et la description retirée, une panne plus discrète qu’une entrée manquante, qui ne remonte peut-être pas de la même façon. Vérifiez donc quand même contre votre système de fichiers. Le contrôle ne demande aucun outillage au-delà d’un shell :
python3 - <<'PY'
import os, re, glob
rows = []
for f in glob.glob(os.path.expanduser('~/.claude/skills/*/SKILL.md')):
name = os.path.basename(os.path.dirname(f))
fm = re.match(r'^---\s*\n(.*?)\n---\s*\n', open(f, encoding='utf-8', errors='replace').read(), re.S)
if not fm:
continue
d = re.search(r'^description:\s*(.*?)(?=\n[a-zA-Z_-]+:|\Z)', fm.group(1), re.S | re.M)
if not d:
continue
desc = ' '.join(d.group(1).split()).strip('"\'').lstrip('|').strip()
rows.append((len(desc), name))
rows.sort(reverse=True)
print(f'{len(rows)} skills, {sum(r[0] for r in rows)} description chars')
for length, name in rows[:15]:
print(f' {length:4d} {name}')
PY
Comparez ensuite la sortie à ce que votre modèle a réellement reçu. L’écart entre les deux, c’est toute la découverte. Si un skill apparaît dans votre contexte avec un nom et aucune phrase après, ce skill est installé et inatteignable.
Trois habitudes découlent de cet audit :
Budgétez chaque nouveau skill, pas seulement les longs. Le surcoût par entrée accompagne chaque skill quelle que soit la longueur de sa description, si bien que le dixième skill de 90 caractères coûte plus que 90 caractères.
Recomptez après chaque ajout de skills. Je ne peux pas vous donner de marge de sécurité, parce que le plafond n’est pas documenté et varierait selon la façon dont la fraction est calculée.34 Une vérification empirique vaut mieux qu’une marge calculée qui repose sur une hypothèse, ce qui est exactement l’erreur que j’ai commise.
Faites un instantané avant d’élaguer. La plupart de mes dossiers de skills n’étaient pas suivis par git, et sept étaient des liens symboliques vers un dossier qui n’était pas un dépôt du tout, si bien que git add les a refusés avec « beyond a symbolic link ». J’ai commencé par écrire chaque description d’origine dans un fichier JSON. Un contrôle de version que vous n’avez pas vérifié n’est pas une sauvegarde.
Points clés
- Un skill sans description n’est pas dégradé, il est inatteignable. La description porte à elle seule toute la décision de routage.
- La panne est silencieuse par construction. Aucune erreur, aucun avertissement, aucun log. Lancez
/contextpour les avertissements d’exclusion, puis comparez la liste de votre contexte à votre système de fichiers, car une description retirée est plus discrète qu’une entrée manquante. - C’est la taille agrégée qui provoque la suppression, pas les propriétés de chaque fichier. Aucun attribut du fichier individuel ne prédisait quels skills perdraient leur description.
- Quand l’inspection échoue, intervenez. Je ne pouvais pas trouver le mécanisme en examinant la panne. Changer le total et regarder la panne s’inverser l’a prouvé en une seule étape.
- Les descriptions routent ; les corps expliquent. Tout ce qui, dans une description, n’aide pas à décider quand invoquer est payé à chaque tour et ne rapporte rien.
- Les impératifs dans une description agissent sur vous sans être invoqués. ALWAYS et NEVER orientent le comportement depuis le catalogue : c’est l’effet d’osmose mesuré.1
- Ne publiez pas un pourcentage que vous ne pouvez pas sourcer. Ma propre première rédaction a multiplié une mesure réelle par un budget deviné et a produit un chiffre assuré et faux.
Questions fréquentes
Pourquoi mon skill Claude Code ne s’active-t-il pas ?
Vérifiez si le modèle voit vraiment sa description. Les descriptions de skills sont chargées dans le contexte à chaque tour et partagent un budget fixe de caractères ; le dépasser supprime des descriptions silencieusement, sans erreur, sans avertissement et sans ligne de log. Cinq de mes 84 skills parvenaient au modèle réduits à un simple nom alors que leurs fichiers sur le disque portaient des descriptions parfaitement valables. Un skill sans description ne peut pas être routé.12
Quel est le budget de description des skills dans Claude Code ?
Le budget exact n’est pas documenté et fait aujourd’hui débat, et je ne vais pas publier un chiffre que je ne peux pas sourcer. Ce que j’ai mesuré : 21,848 caractères de descriptions ont fait sauter cinq descriptions, et 9,885 caractères n’en ont fait sauter aucune. Les mesures de la communauté situent le plafond pratique autour de 15,500 à 16,000 caractères, avec environ 109 caractères de surcoût par entrée, et des contributeurs d’Anthropic rapportent que la fraction du budget est calculée sur une base fixe de 200K.346
Comment savoir lesquels de mes skills ont perdu leur description ?
Commencez à l’intérieur d’une session avec /context, qui indique si des skills ont été exclus. Vérifiez ensuite quand même contre votre système de fichiers, car mes cinq skills n’étaient pas exclus : ils arrivaient avec le nom intact et la description retirée, une panne plus discrète qu’une entrée manquante. Additionnez les caractères de description dans le frontmatter de vos fichiers SKILL.md et comparez cette liste à ce que votre contexte affiche réellement.5
Qu’est-ce qui relève de la description d’un skill plutôt que de son corps ?
La seule mission d’une description est de répondre à la question de savoir quand le skill doit être invoqué. Gardez les mots déclencheurs, les noms et les commandes slash qu’un utilisateur taperait réellement, et déplacez la procédure, la philosophie et les chemins de fichiers dans le corps, qui n’est chargé qu’à l’invocation. Ma description jiro est passée de 686 à 126 caractères avec le même comportement de routage, parce qu’environ 500 de ces caractères ne faisaient qu’expliquer ce que le skill contient.
Les descriptions de skills influencent-elles le comportement même quand le skill ne s’exécute jamais ?
Oui, et c’est la seconde taxe. Onze de mes descriptions contenaient ALWAYS, NEVER, MUST, PROACTIVELY et BEFORE, des mots qui siègent dans le contexte à chaque tour et se lisent comme des instructions parce qu’ils sont écrits comme des instructions. « The Regression Tax » nomme cet effet l’osmose des descriptions de skills : un skill qui modifie le comportement de l’agent par sa seule présence dans le contexte, même sans jamais être invoqué.1
Références
-
« The Regression Tax », arXiv:2607.22520, 24 juillet 2026. Environ 6,000 exécutions sur deux benchmarks d’automatisation bureautique et trois piles de harness. L’article nomme trois modes de régression : l’osmose des descriptions de skills (changement de comportement dû à la présence dans le contexte, sans invocation), le déplacement de l’ancrage et le déplacement de la vérification. Conclusion principale : les skills les plus performants dépassent les autres surtout en régressant moins plutôt qu’en apportant davantage. ↩↩↩↩↩
-
Skill description budget silently truncates routing information, causing skill routing failures, ticket anthropics/claude-code #64606. Voir aussi Skill descriptions truncated due to context budget constraints, ticket #56710. ↩↩↩
-
skillListingBudgetFraction is calculated against a fixed ~200K baseline, not the model’s actual context window, ticket anthropics/claude-code #57941. ↩↩↩↩
-
Skill description budget uses base context, ignores [1m] extension, ticket anthropics/claude-code #57168. ↩↩↩↩
-
Extend Claude with skills, documentation Claude Code. La documentation publiée n’indique aucun budget total de caractères pour les descriptions de skills. Voir aussi Skills docs omit the 250-character cap for /skills descriptions, ticket #40121. ↩↩↩
-
Claude Code skill budget research. Mesure communautaire situant le plafond pratique autour de 15,500 à 16,000 caractères de métadonnées de skills au total, avec environ 109 caractères de surcoût par entrée (balises XML ~85, nom du skill ~20, champ d’emplacement ~4), et observant que des entrées entières sont masquées plutôt que tronquées individuellement dans les cas mesurés. ↩↩
-
Claude Code CHANGELOG, v2.1.215, juillet 2026 : les skills intégrés
/verifyet/code-reviewne s’auto-invoquent plus et exigent une invocation explicite. ↩ -
Claude Code CHANGELOG, v2.1.218, 22 juillet 2026 :
/code-reviews’exécute comme sous-agent en arrière-plan et/deep-researchne s’auto-invoque plus. ↩ -
Liudas Panavas, Sebastian Minus, Bradley Monton, Derek Ray, Suhaas Garre, Sushant Mehta et Edwin Chen, « HANDBOOK.md: A Benchmark for Long-Context Agentic Instruction Following », arXiv:2607.25398, soumis le 28 juillet 2026. Soixante-cinq tâches réparties sur cinq domaines (finance, facturation médicale, assurance, logistique, ressources humaines) dans dix entreprises fictives, avec des procédures opérationnelles rédigées par des experts, de 20 à 124 pages, et 824 critères d’évaluation programmatiques. La meilleure des trente configurations de modèles évaluées a réussi 36.2% des essais ; la plupart des configurations de pointe sont restées sous les 25%. Schémas d’échec nommés : laisser une requête plausible venue de l’environnement l’emporter sur la politique en vigueur, effectuer une vérification requise puis agir contre son résultat, et perdre le détail des règles sur de longs horizons. ↩