Créateur de compétences
Guide du cycle de vie des compétences d'agent pour la définition, la structuration et l'empaquetage des compétences réutilisables, avec des scripts, des références et des ressources.
Source: Contenu adapté de anthropics/skills (MIT).
Une compétence permettant de créer de nouvelles compétences et de les améliorer de manière itérative.
À un niveau élevé, le processus de création d'une compétence se déroule comme suit:
- Décidez de ce que vous voulez que la compétence fasse et approximativement comment elle doit le faire
- Rédiger une ébauche de la compétence
- Créez quelques invites de test et exécutez Claude-with-access-to-the-skill dessus
- Aider l'utilisateur à évaluer les résultats qualitativement et quantitativement
- Pendant que les exécutions se déroulent en arrière-plan, rédigez quelques évaluations quantitatives s'il n'y en a pas (s'il y en a, vous pouvez les utiliser telles quelles ou les modifier si vous pensez que quelque chose doit changer à leur sujet). Expliquez-les ensuite à l'utilisateur (ou s'ils existaient déjà, expliquez ceux qui existent déjà)
- Utilisez le script
eval-viewer/generate_review.pypour montrer à l'utilisateur les résultats à consulter, et laissez-le également consulter les mesures quantitatives.
- Réécrivez la compétence en fonction des commentaires de l'évaluation des résultats par l'utilisateur (et également s'il existe des défauts flagrants qui ressortent des critères quantitatifs)
- Répétez jusqu'à ce que vous soyez satisfait
- Développez l'ensemble de tests et réessayez à plus grande échelle
Votre travail lorsque vous utilisez cette compétence consiste à déterminer où se trouve l'utilisateur dans ce processus, puis à intervenir et à l'aider à progresser à travers ces étapes. Ainsi, par exemple, ils disent peut-être "Je veux créer une compétence pour X". Vous pouvez aider à affiner ce qu'ils signifient, rédiger un brouillon, rédiger les cas de test, déterminer comment ils souhaitent évaluer, exécuter toutes les invites et répéter.
D’un autre côté, ils ont peut-être déjà une ébauche de la compétence. Dans ce cas, vous pouvez accéder directement à la partie eval/iterate de la boucle.
Bien sûr, vous devez toujours être flexible et si l'utilisateur dit "Je n'ai pas besoin de lancer un tas d'évaluations, vibrez simplement avec moi", vous pouvez le faire à la place.
Ensuite, une fois la compétence terminée (mais encore une fois, l'ordre est flexible), vous pouvez également exécuter l'améliorateur de description de compétence, pour lequel nous avons un script entièrement séparé, afin d'optimiser le déclenchement de la compétence.
Cool? Cool.
Communiquer avec l'utilisateur
Le créateur de compétences est susceptible d’être utilisé par des personnes très familiarisées avec le jargon du codage. Si vous ne l'avez pas entendu (et comment pourriez-vous, cela n'a commencé que très récemment), il existe maintenant une tendance où le pouvoir de Claude incite les plombiers à ouvrir leurs terminaux, les parents et les grands-parents à Google "comment installer npm". D’un autre côté, la majorité des utilisateurs sont probablement assez familiarisés avec l’informatique.
Alors faites attention aux indices contextuels pour comprendre comment formuler votre communication! Dans le cas par défaut, juste pour vous donner une idée:
- "évaluation" et "benchmark" sont à la limite, mais OK
- pour "JSON" et "assertion", vous souhaitez voir des indices sérieux de la part de l'utilisateur indiquant qu'il sait ce que sont ces éléments avant de les utiliser sans les expliquer
Vous pouvez expliquer brièvement les termes en cas de doute, et n'hésitez pas à clarifier les termes avec une courte définition si vous ne savez pas si l'utilisateur comprendra.
Créer une compétence
Capturer l'intention
Commencez par comprendre l’intention de l’utilisateur. La conversation en cours peut déjà contenir un flux de travail que l'utilisateur souhaite capturer (par exemple, il dit « transformez-le en compétence »). Si tel est le cas, extrayez d'abord les réponses de l'historique de la conversation: les outils utilisés, la séquence d'étapes, les corrections apportées par l'utilisateur, les formats d'entrée/sortie observés. L'utilisateur devra peut-être combler les lacunes et devra confirmer avant de passer à l'étape suivante.
- Que doit permettre cette compétence à Claude?
- Quand cette compétence doit-elle se déclencher? (quelles expressions/contextes utilisateur)
- Quel est le format de sortie attendu?
- Faut-il mettre en place des cas de tests pour vérifier que la compétence fonctionne? Les compétences avec des résultats objectivement vérifiables (transformations de fichiers, extraction de données, génération de code, étapes de flux de travail fixes) bénéficient des cas de test. Les compétences ayant des résultats subjectifs (style d’écriture, art) n’en ont souvent pas besoin. Suggérez la valeur par défaut appropriée en fonction du type de compétence, mais laissez l'utilisateur décider.
Entretien et recherche
Posez de manière proactive des questions sur les cas extrêmes, les formats d'entrée/sortie, les exemples de fichiers, les critères de réussite et les dépendances. Attendez d'écrire des invites de test jusqu'à ce que cette partie soit réglée.
Vérifiez les MCP disponibles - s'ils sont utiles pour la recherche (recherche de documents, recherche de compétences similaires, recherche de meilleures pratiques), recherche en parallèle via des sous-agents si disponibles, sinon en ligne. Préparez-vous avec le contexte pour réduire le fardeau de l'utilisateur.
Écrivez le SKILL.md
Sur la base de l'entretien avec l'utilisateur, remplissez ces éléments:
- nom: identifiant de compétence
- description: Quand déclencher, ce qu'il fait. Il s'agit du principal mécanisme de déclenchement: il inclut à la fois ce que fait la compétence ET les contextes spécifiques indiquant quand l'utiliser. Toutes les informations « quand utiliser » se trouvent ici, pas dans le corps. Remarque: actuellement, Claude a tendance à « sous-déclencher » les compétences, à ne pas les utiliser lorsqu'elles seraient utiles. Pour lutter contre cela, veuillez rendre les descriptions de compétences un peu « insistantes ». Ainsi, par exemple, au lieu de « Comment créer un tableau de bord simple et rapide pour afficher les données anthropiques internes. », vous pourriez écrire « Comment créer un tableau de bord simple et rapide pour afficher les données anthropiques internes. Assurez-vous d'utiliser cette compétence chaque fois que l'utilisateur mentionne des tableaux de bord, la visualisation de données, des métriques internes ou souhaite afficher tout type de données d'entreprise, même s'il ne demande pas explicitement un « tableau de bord ».
- compatibilité: outils requis, dépendances (facultatif, rarement nécessaire)
- le reste de la compétence:)
Guide de rédaction des compétences
Anatomie d'une compétence
skill-name/
SKILL.md (required)
YAML frontmatter (name, description required)
Markdown instructions
Bundled Resources (optional)
scripts/ - Executable code for deterministic/repetitive tasks
references/ - Docs loaded into context as needed
assets/ - Files used in output (templates, icons, fonts)Divulgation progressive
Les compétences utilisent un système de chargement à trois niveaux:
- Métadonnées (nom + description) - Toujours en contexte (~100 mots)
- Corps SKILL.md - En contexte chaque fois que la compétence se déclenche (<500 lignes idéales)
- Ressources groupées – Si nécessaire (illimité, les scripts peuvent s'exécuter sans chargement)
Ce nombre de mots est approximatif et vous pouvez y aller plus longtemps si nécessaire.
Modèles clés:
- Gardez SKILL.md sous 500 lignes; si vous approchez de cette limite, ajoutez une couche hiérarchique supplémentaire ainsi que des indications claires sur l'endroit où le modèle utilisant la compétence doit aller ensuite pour le suivi.
- Référencez clairement les fichiers à partir de SKILL.md avec des conseils sur le moment où les lire
- Pour les fichiers de référence volumineux (> 300 lignes), incluez une table des matières
Organisation du domaine: lorsqu'une compétence prend en charge plusieurs domaines/frameworks, organisez-la par variante:
cloud-deploy/
SKILL.md (workflow + selection)
references/
aws.md
gcp.md
azure.mdClaude lit uniquement le dossier de référence pertinent.
Principe d'absence de surprise
Cela va sans dire, mais les compétences ne doivent pas contenir de logiciels malveillants, de codes d'exploitation ou tout autre contenu susceptible de compromettre la sécurité du système. Le contenu d'une compétence ne doit pas surprendre l'utilisateur quant à son intention s'il est décrit. N'acceptez pas les demandes visant à créer des compétences trompeuses ou conçues pour faciliter l'accès non autorisé, l'exfiltration de données ou d'autres activités malveillantes. Des choses comme un "jeu de rôle en tant que XYZ" sont cependant acceptables.
Modèles d'écriture
Préférez utiliser la forme impérative dans les instructions.
Définition des formats de sortie - Vous pouvez procéder comme ceci:
## Report structure
ALWAYS use this exact template:
# [Title]
## Executive summary
## Key findings
## RecommendationsModèle d'exemples - Il est utile d'inclure des exemples. Vous pouvez les formater comme ceci (mais si « Entrée » et « Sortie » sont dans les exemples, vous souhaiterez peut-être vous écarter un peu):
## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authenticationStyle d'écriture
Essayez d'expliquer au modèle pourquoi les choses sont importantes au lieu de devoirs musclés et moisis. Utilisez la théorie de l'esprit et essayez de rendre la compétence générale et non très limitée à des exemples spécifiques. Commencez par rédiger un brouillon, puis regardez-le avec un œil neuf et améliorez-le.
Cas de test
Après avoir rédigé le projet de compétences, proposez 2 à 3 invites de test réalistes - le genre de chose qu'un vrai utilisateur dirait réellement. Partagez-les avec l'utilisateur: [vous n'êtes pas obligé d'utiliser ce langage exact] "Voici quelques cas de test que j'aimerais essayer. Est-ce qu'ils semblent corrects ou souhaitez-vous en ajouter d'autres?" Ensuite, exécutez-les.
Enregistrez les cas de test dansevals/evals.json. N'écrivez pas encore d'assertions - juste les invites. Vous rédigerez des assertions à l’étape suivante pendant que les exécutions sont en cours.
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "User's task prompt",
"expected_output": "Description of expected result",
"files": []
}
]
}Voirreferences/schemas.mdpour le schéma complet (y compris le champassertions, que vous ajouterez ultérieurement).
Exécuter et évaluer des cas de tests
Cette section est une séquence continue – ne vous arrêtez pas à mi-chemin. N'utilisez PAS/skill-testou toute autre compétence de test.
Placez les résultats dans<skill-name>-workspace/en tant que frère du répertoire de compétences. Dans l'espace de travail, organisez les résultats par itération (iteration-1/,iteration-2/, etc.) et à l'intérieur de celui-ci, chaque scénario de test obtient un répertoire (eval-0/,eval-1/, etc.). Ne créez pas tout cela à l’avance – créez simplement des répertoires au fur et à mesure.
Étape 1: Générez toutes les courses (avec compétence ET ligne de base) dans le même tour
Pour chaque cas de test, générez deux sous-agents au cours du même tour – un avec la compétence, un sans. C'est important: ne lancez pas d'abord les exécutions avec compétences, puis revenez plus tard pour les références. Lancez tout en même temps pour que tout se termine à peu près en même temps.
Course avec compétences:
Execute this task:
- Skill path: <path-to-skill>
- Task: <eval prompt>
- Input files: <eval files if any, or "none">
- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- Outputs to save: <what the user cares about - e.g., "the .docx file", "the final CSV">Exécution de référence (même invite, mais la référence dépend du contexte):
- Créer une nouvelle compétence: aucune compétence du tout. Même invite, pas de chemin de compétences, enregistrez dans
without_skill/outputs/. - Améliorer une compétence existante: l'ancienne version. Avant de procéder à la modification, prenez un instantané de la compétence (
cp -r <skill-path> <workspace>/skill-snapshot/), puis pointez le sous-agent de base vers l'instantané. Enregistrez dansold_skill/outputs/.
Écrivez uneval_metadata.jsonpour chaque scénario de test (les assertions peuvent être vides pour l'instant). Donnez à chaque évaluation un nom descriptif basé sur ce qu'elle teste - pas seulement "eval-0". Utilisez également ce nom pour le répertoire. Si cette itération utilise des invites eval nouvelles ou modifiées, créez ces fichiers pour chaque nouveau répertoire eval - ne présumez pas qu'ils sont repris des itérations précédentes.
{
"eval_id": 0,
"eval_name": "descriptive-name-here",
"prompt": "The user's task prompt",
"assertions": []
}Étape 2: Pendant que les exécutions sont en cours, rédigez des assertions
N'attendez pas simplement la fin des courses: vous pouvez utiliser ce temps de manière productive. Rédiger des assertions quantitatives pour chaque cas de test et les expliquer à l'utilisateur. Si des assertions existent déjà dansevals/evals.json, examinez-les et expliquez ce qu'elles vérifient.
Les bonnes assertions sont objectivement vérifiables et ont des noms descriptifs - elles doivent être lues clairement dans le visualiseur de référence afin que quelqu'un qui jette un coup d'œil aux résultats comprenne immédiatement ce que chacune vérifie. Les compétences subjectives (style d'écriture, qualité de la conception) sont mieux évaluées qualitativement: n'imposez pas d'affirmations sur des choses qui nécessitent un jugement humain.
Mettez à jour les fichierseval_metadata.jsonetevals/evals.jsonavec les assertions une fois rédigées. Expliquez également à l'utilisateur ce qu'il verra dans le visualiseur: à la fois les résultats qualitatifs et le point de référence quantitatif.
Étape 3: Une fois les exécutions terminées, capturez les données de synchronisation
Une fois chaque tâche de sous-agent terminée, vous recevez une notification contenanttotal_tokensetduration_ms. Enregistrez ces données immédiatement danstiming.jsondans le répertoire d'exécution:
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}C'est la seule opportunité de capturer ces données: elles proviennent de la notification de tâche et ne sont pas conservées ailleurs. Traitez chaque notification au fur et à mesure qu’elle arrive plutôt que d’essayer de les regrouper.
Étape 4: Noter, regrouper et lancer la visionneuse
Une fois toutes les analyses terminées:
-
Notez chaque exécution: génère un sous-agent de notation (ou note en ligne) qui lit
agents/grader.mdet évalue chaque assertion par rapport aux résultats. Enregistrez les résultats dansgrading.jsondans chaque répertoire d'exécution. Le tableau d'attentes grading.json doit utiliser les champstext,passedetevidence(et nonname/met/detailsou d'autres variantes) - le visualiseur dépend de ces noms de champs exacts. Pour les assertions qui peuvent être vérifiées par programme, écrivez et exécutez un script plutôt que de le surveiller: les scripts sont plus rapides, plus fiables et peuvent être réutilisés au fil des itérations. -
Agréger dans un benchmark - exécutez le script d'agrégation à partir du répertoire du créateur de compétences:
python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>Cela produit
benchmark.jsonetbenchmark.mdavec pass_rate, time et tokens pour chaque configuration, avec la moyenne stddev et le delta. Si vous générez manuellement benchmark.json, consultezreferences/schemas.mdpour connaître le schéma exact attendu par le spectateur. Placez chaque version with_skill avant son homologue de base. -
Faites passer un analyste - lisez les données de référence et les modèles de surface que les statistiques globales pourraient cacher. Voir
agents/analyzer.md(la section « Analyse des résultats de référence ») pour savoir ce qu'il faut rechercher: des éléments tels que des assertions qui réussissent toujours quelle que soit la compétence (non discriminante), des évaluations à forte variance (éventuellement instables) et des compromis temps/jeton. -
Lancez le visualiseur avec des résultats qualitatifs et des données quantitatives:
nohup python <skill-creator-path>/eval-viewer/generate_review.py \ <workspace>/iteration-N \ --skill-name "my-skill" \ --benchmark <workspace>/iteration-N/benchmark.json \ > /dev/null 2>&1 & VIEWER_PID=$!Pour l'itération 2+, transmettez également
--previous-workspace <workspace>/iteration-<N-1>.Environnements de travail collaboratif/sans tête: Si
webbrowser.open()n'est pas disponible ou si l'environnement n'a pas d'affichage, utilisez--static <output_path>pour écrire un fichier HTML autonome au lieu de démarrer un serveur. Les commentaires seront téléchargés sous forme de fichierfeedback.jsonlorsque l'utilisateur clique sur « Soumettre tous les avis ». Après le téléchargement, copiezfeedback.jsondans le répertoire de l'espace de travail pour la prochaine itération à récupérer.
Remarque: veuillez utiliser generate_review.py pour créer la visionneuse; il n'est pas nécessaire d'écrire du HTML personnalisé.
- Dites à l'utilisateur quelque chose comme: "J'ai ouvert les résultats dans votre navigateur. Il y a deux onglets: "Sorties" vous permet de cliquer sur chaque cas de test et de laisser des commentaires, "Benchmark" affiche la comparaison quantitative. Lorsque vous avez terminé, revenez ici et faites-le moi savoir. "
Ce que l'utilisateur voit dans le visualiseur
L'onglet "Sorties" affiche un scénario de test à la fois:
- Invite: la tâche qui a été confiée
- Sortie: les fichiers produits par la compétence, rendus en ligne si possible
- Sortie précédente (itération 2+): section réduite affichant la sortie de la dernière itération
- Notes formelles (si une notation a été effectuée): section réduite montrant la réussite/l'échec de l'assertion
- Commentaires: une zone de texte qui s'enregistre automatiquement au fur et à mesure de la saisie
- Commentaires précédents (itération 2+): leurs commentaires de la dernière fois, affichés sous la zone de texte
L'onglet « Benchmark » affiche le résumé des statistiques: taux de réussite, timing et utilisation des jetons pour chaque configuration, avec des répartitions par évaluation et des observations d'analystes.
La navigation se fait via les boutons précédent/suivant ou les touches fléchées. Une fois terminé, ils cliquent sur « Soumettre tous les avis », ce qui enregistre tous les commentaires dansfeedback.json.
Étape 5: Lire les commentaires
Lorsque l'utilisateur vous dit qu'il a terminé, lisezfeedback.json:
{
"reviews": [
{"run_id": "eval-0-with_skill", "feedback": "the chart is missing axis labels", "timestamp": "..."},
{"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
{"run_id": "eval-2-with_skill", "feedback": "perfect, love this", "timestamp": "..."}
],
"status": "complete"
}Un retour vide signifie que l’utilisateur pensait que tout allait bien. Concentrez vos améliorations sur les cas de test pour lesquels l'utilisateur a eu des plaintes spécifiques.
Tuez le serveur de visualisation lorsque vous en avez terminé:
kill $VIEWER_PID 2>/dev/nullAméliorer la compétence
C'est le cœur de la boucle. Vous avez exécuté les cas de test, l'utilisateur a examiné les résultats et vous devez maintenant améliorer la compétence en fonction de ses commentaires.
Comment penser aux améliorations
-
Généralisez à partir des commentaires. Ce qui se passe ici, c'est que nous essayons de créer des compétences qui peuvent être utilisées un million de fois (peut-être littéralement, peut-être même plus, qui sait) à travers de nombreuses invites différentes. Ici, vous et l'utilisateur répétez encore et encore quelques exemples seulement, car cela permet d'avancer plus rapidement. L'utilisateur connaît parfaitement ces exemples et peut rapidement évaluer de nouveaux résultats. Mais si la compétence que vous et l'utilisateur développez conjointement ne fonctionne que pour ces exemples, elle est inutile. Plutôt que d'introduire des changements fastidieux et excessifs, ou des MUST trop restrictifs, s'il y a un problème persistant, vous pouvez essayer de vous diversifier et d'utiliser différentes métaphores, ou de recommander différents modèles de travail. C'est relativement bon marché à essayer et peut-être que vous tomberez sur quelque chose de génial.
-
Gardez l'invite légère. Supprimez les éléments qui ne pèsent pas sur eux. Assurez-vous de lire les transcriptions, pas seulement les résultats finaux - s'il semble que la compétence fait perdre beaucoup de temps au modèle à faire des choses improductives, vous pouvez essayer de vous débarrasser des parties de la compétence qui le font faire cela et voir ce qui se passe.
-
Expliquez le pourquoi. Essayez d'expliquer le pourquoi derrière tout ce que vous demandez au modèle de faire. Les LLM d'aujourd'hui sont intelligents. Ils ont une bonne théorie de l'esprit et, lorsqu'on leur donne un bon harnais, ils peuvent aller au-delà des instructions par cœur et vraiment faire bouger les choses. Même si les commentaires de l'utilisateur sont laconiques ou frustrés, essayez de réellement comprendre la tâche et pourquoi l'utilisateur écrit ce qu'il a écrit et ce qu'il a réellement écrit, puis transmettez cette compréhension dans les instructions. Si vous vous retrouvez à écrire TOUJOURS ou JAMAIS en majuscules, ou à utiliser des structures super rigides, c'est un signal d'alarme - si possible, recadrez et expliquez le raisonnement afin que le modèle comprenne pourquoi la chose que vous demandez est importante. C'est une approche plus humaine, plus puissante et plus efficace.
-
Recherchez le travail répété dans les cas de test. Lisez les transcriptions des exécutions de tests et remarquez si les sous-agents ont tous écrit indépendamment des scripts d'assistance similaires ou ont adopté la même approche en plusieurs étapes pour quelque chose. Si les 3 scénarios de test ont abouti à ce que le sous-agent écrive un
create_docx.pyou unbuild_chart.py, c'est un signal fort que la compétence doit regrouper ce script. Écrivez-le une fois, mettez-le dansscripts/et dites à la compétence de l'utiliser. Cela évite à chaque invocation future de réinventer la roue.
Cette tâche est assez importante (nous essayons ici de créer des milliards de valeur économique par an!) et votre temps de réflexion n’est pas un bloqueur; prenez votre temps et réfléchissez bien. Je suggérerais de rédiger un projet de révision, puis de le réexaminer et d'apporter des améliorations. Faites vraiment de votre mieux pour entrer dans la tête de l’utilisateur et comprendre ce qu’il veut et ce dont il a besoin.
La boucle d'itération
Après avoir amélioré la compétence:
- Appliquez vos améliorations à la compétence
- Réexécutez tous les scénarios de test dans un nouveau répertoire
iteration-<N+1>/, y compris les exécutions de référence. Si vous créez une nouvelle compétence, la référence est toujourswithout_skill(aucune compétence) – qui reste la même au fil des itérations. Si vous améliorez une compétence existante, utilisez votre jugement sur ce qui a du sens comme référence: la version originale avec laquelle l'utilisateur est entré ou l'itération précédente. - Lancez le réviseur avec
--previous-workspacepointant sur l'itération précédente - Attendez que l'utilisateur examine et vous dise qu'il a terminé
- Lisez les nouveaux commentaires, améliorez-vous encore, répétez
Continuez jusqu'à:
- L'utilisateur se dit content
- Les commentaires sont tous vides (tout semble bon)
- Vous ne faites pas de progrès significatifs
Avancé: comparaison aveugle
Pour les situations où vous souhaitez une comparaison plus rigoureuse entre deux versions d'une compétence (par exemple, l'utilisateur demande « la nouvelle version est-elle réellement meilleure? »), il existe un système de comparaison aveugle. Lisezagents/comparator.mdetagents/analyzer.mdpour plus de détails. L'idée de base est la suivante: donner deux résultats à un agent indépendant sans lui dire lequel est lequel, et le laisser juger de la qualité. Analysez ensuite pourquoi le gagnant a gagné.
Ceci est facultatif, nécessite des sous-agents et la plupart des utilisateurs n'en auront pas besoin. La boucle d’examen humain est généralement suffisante.
Description Optimisation
Le champ de description dans le frontmatter SKILL.md est le principal mécanisme qui détermine si Claude invoque une compétence. Après avoir créé ou amélioré une compétence, proposez d'optimiser la description pour une meilleure précision de déclenchement.
Étape 1: Générer des requêtes d'évaluation de déclencheur
Créez 20 requêtes d'évaluation - un mélange de requêtes à déclencher et à ne pas déclencher. Enregistrer au format JSON:
[
{"query": "the user prompt", "should_trigger": true},
{"query": "another prompt", "should_trigger": false}
]Les requêtes doivent être réalistes et quelque chose qu'un utilisateur de Claude Code ou Claude.ai saisirait réellement. Pas de demandes abstraites, mais des demandes concrètes et spécifiques et contenant beaucoup de détails. Par exemple, les chemins de fichiers, le contexte personnel concernant le travail ou la situation de l'utilisateur, les noms et valeurs des colonnes, les noms d'entreprise, les URL. Un peu de trame de fond. Certains peuvent être en minuscules ou contenir des abréviations, des fautes de frappe ou un discours informel. Utilisez un mélange de différentes longueurs et concentrez-vous sur les cas extrêmes plutôt que de les rendre clairs (l'utilisateur aura la possibilité de les approuver).
Mauvais:"Format this data","Extract text from PDF","Create a chart"
Bon:"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think"
Pour les requêtes devraient déclencher (8-10), pensez à la couverture. Vous voulez des formulations différentes ayant la même intention – certaines formelles, d’autres informelles. Incluez les cas où l'utilisateur ne nomme pas explicitement la compétence ou le type de fichier mais en a clairement besoin. Ajoutez à cela des cas d'utilisation inhabituels et des cas où cette compétence est en concurrence avec une autre mais devrait gagner.
Pour les requêtes ne devraient pas déclencher (8 à 10), les plus précieuses sont les quasi-accidents: des requêtes qui partagent des mots-clés ou des concepts avec la compétence mais qui nécessitent en réalité quelque chose de différent. Pensez aux domaines adjacents, aux formulations ambiguës où une correspondance de mot clé naïve se déclencherait mais ne devrait pas se déclencher, et aux cas où la requête touche à quelque chose que fait la compétence mais dans un contexte où un autre outil est plus approprié.
La chose clé à éviter: ne faites pas en sorte que les requêtes qui ne doivent pas déclencher soient manifestement non pertinentes. "Écrire une fonction de Fibonacci" comme test négatif pour une compétence PDF est trop simple - cela ne teste rien. Les cas négatifs devraient être vraiment délicats.
Étape 2: Réviser avec l'utilisateur
Présentez l'ensemble d'évaluation à l'utilisateur pour examen à l'aide du modèle HTML:
- Lire le modèle de
assets/eval_review.html - Remplacez les espaces réservés:
__EVAL_DATA_PLACEHOLDER__-> le tableau JSON d'éléments d'évaluation (pas de guillemets autour - c'est une affectation de variable JS)__SKILL_NAME_PLACEHOLDER__-> le nom de la compétence__SKILL_DESCRIPTION_PLACEHOLDER__-> la description actuelle de la compétence
- Écrivez dans un fichier temporaire (par exemple,
/tmp/eval_review_<skill-name>.html) et ouvrez-le:open /tmp/eval_review_<skill-name>.html - L'utilisateur peut modifier les requêtes, activer le déclencheur, ajouter/supprimer des entrées, puis cliquer sur "Exporter l'ensemble d'évaluation".
- Le fichier est téléchargé sur
~/Downloads/eval_set.json- vérifiez le dossier Téléchargements pour connaître la version la plus récente au cas où il y en aurait plusieurs (par exemple,eval_set (1).json).
Cette étape est importante: les mauvaises requêtes d'évaluation conduisent à de mauvaises descriptions.
Étape 3: Exécutez la boucle d'optimisation
Dites à l'utilisateur: "Cela prendra un certain temps - je vais exécuter la boucle d'optimisation en arrière-plan et la vérifier périodiquement."
Enregistrez l'ensemble d'évaluation dans l'espace de travail, puis exécutez-le en arrière-plan:
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <model-id-powering-this-session> \
--max-iterations 5 \
--verboseUtilisez l'ID de modèle de l'invite de votre système (celui qui alimente la session en cours) afin que le test de déclenchement corresponde à ce que l'utilisateur expérimente réellement.
Pendant son exécution, suivez périodiquement la sortie pour donner à l'utilisateur des mises à jour sur l'itération en cours et à quoi ressemblent les scores.
Cela gère automatiquement la boucle d’optimisation complète. Il divise l'ensemble d'évaluation en 60 % d'entraînement et 40 % de tests retenus, évalue la description actuelle (en exécutant chaque requête 3 fois pour obtenir un taux de déclenchement fiable), puis appelle Claude pour proposer des améliorations en fonction de ce qui a échoué. Il réévalue chaque nouvelle description à la fois lors du train et du test, en itérant jusqu'à 5 fois. Une fois terminé, il ouvre un rapport HTML dans le navigateur affichant les résultats par itération et renvoie JSON avecbest_description- sélectionné par score de test plutôt que par score d'entraînement pour éviter le surajustement.
Comment fonctionne le déclenchement des compétences
Comprendre le mécanisme de déclenchement permet de concevoir de meilleures requêtes d'évaluation. Les compétences apparaissent dans la listeavailable_skillsde Claude avec leur nom + description, et Claude décide de consulter ou non une compétence en fonction de cette description. La chose importante à savoir est que Claude ne consulte les compétences que pour les tâches qu'il ne peut pas gérer facilement seul - des requêtes simples en une seule étape comme « lire ce PDF » peuvent ne pas déclencher une compétence même si la description correspond parfaitement, car Claude peut les gérer directement avec des outils de base. Les requêtes complexes, en plusieurs étapes ou spécialisées déclenchent de manière fiable des compétences lorsque la description correspond.
Cela signifie que vos requêtes d'évaluation doivent être suffisamment approfondies pour que Claude puisse réellement bénéficier de la consultation d'une compétence. Les requêtes simples telles que « lire le fichier X » sont de mauvais cas de test: elles ne déclencheront pas de compétences, quelle que soit la qualité de la description.
Étape 4: Appliquer le résultat
Prenezbest_descriptionà partir de la sortie JSON et mettez à jour le frontmatter SKILL.md de la compétence. Montrez à l'utilisateur avant/après et rapportez les scores.
Package et présent (uniquement si l'outilpresent_filesest disponible)
Vérifiez si vous avez accès à l'outilpresent_files. Si ce n'est pas le cas, ignorez cette étape. Si vous le faites, emballez la compétence et présentez le fichier.skill à l'utilisateur:
python -m scripts.package_skill <path/to/skill-folder>Après l'empaquetage, dirigez l'utilisateur vers le chemin du fichier.skillrésultant afin qu'il puisse l'installer.
Instructions spécifiques à Claude.ai
Dans Claude.ai, le flux de travail de base est le même (brouillon -> test -> révision -> améliorer -> répéter), mais comme Claude.ai n'a pas de sous-agents, certains mécanismes changent. Voici ce qu'il faut adapter:
Exécution de cas de test: aucun sous-agent ne signifie pas d'exécution parallèle. Pour chaque cas de test, lisez le fichier SKILL.md de la compétence, puis suivez ses instructions pour exécuter vous-même l'invite de test. Faites-les un à la fois. C'est moins rigoureux que les sous-agents indépendants (vous avez écrit la compétence et vous l'exécutez également, vous disposez donc d'un contexte complet), mais c'est un contrôle de cohérence utile - et l'étape de révision humaine compense. Ignorez les exécutions de base - utilisez simplement la compétence pour terminer la tâche comme demandé.
Vérification des résultats: si vous ne parvenez pas à ouvrir un navigateur (par exemple, la VM de Claude.ai n'a pas d'affichage ou si vous êtes sur un serveur distant), ignorez complètement le réviseur du navigateur. Présentez plutôt les résultats directement dans la conversation. Pour chaque scénario de test, affichez l'invite et le résultat. Si le résultat est un fichier que l'utilisateur doit voir (comme un.docx ou un.xlsx), enregistrez-le dans le système de fichiers et indiquez-lui où il se trouve afin qu'il puisse le télécharger et l'inspecter. Demandez des commentaires en ligne: « À quoi cela ressemble? Quelque chose que vous changeriez? »
Analyse comparative: ignorez l'analyse comparative quantitative: elle repose sur des comparaisons de base qui ne sont pas significatives sans sous-agents. Concentrez-vous sur les retours qualitatifs de l’utilisateur.
La boucle d'itération: comme avant: améliorez les compétences, réexécutez les cas de test, demandez des commentaires - juste sans le réviseur du navigateur au milieu. Vous pouvez toujours organiser les résultats dans des répertoires d'itération sur le système de fichiers si vous en avez un.
Optimisation de la description: Cette section nécessite l'outil CLIclaude(en particulierclaude -p) qui n'est disponible que dans Claude Code. Sautez-le si vous êtes sur Claude.ai.
Comparaison aveugle: nécessite des sous-agents. Sautez-le.
Packaging: Le scriptpackage_skill.pyfonctionne n'importe où avec Python et un système de fichiers. Sur Claude.ai, vous pouvez l'exécuter et l'utilisateur peut télécharger le fichier.skillrésultant.
Mise à jour d'une compétence existante: l'utilisateur peut vous demander de mettre à jour une compétence existante, et non d'en créer une nouvelle. Dans ce cas:
- Conservez le nom d'origine. Notez le nom du répertoire de la compétence et le champ principal
name- utilisez-les tels quels. Par exemple, si la compétence installée estresearch-helper, affichezresearch-helper.skill(et nonresearch-helper-v2). - Copier dans un emplacement accessible en écriture avant de modifier. Le chemin de compétence installé peut être en lecture seule. Copiez dans
/tmp/skill-name/, modifiez-y et emballez à partir de la copie. - En cas d'empaquetage manuel, effectuez d'abord une étape dans
/tmp/, puis copiez-le dans le répertoire de sortie: les écritures directes peuvent échouer en raison des autorisations.
Instructions spécifiques au cowork
Si vous êtes en Cowork, les principales choses à savoir sont:
- Vous avez des sous-agents, donc le flux de travail principal (créer des cas de test en parallèle, exécuter des lignes de base, noter, etc.) fonctionne tous. (Cependant, si vous rencontrez de graves problèmes de délais d'attente, vous pouvez exécuter les invites de test en série plutôt qu'en parallèle.)
- Vous n'avez ni navigateur ni écran, donc lors de la génération de la visionneuse d'évaluation, utilisez
--static <output_path>pour écrire un fichier HTML autonome au lieu de démarrer un serveur. Proposez ensuite un lien sur lequel l'utilisateur peut cliquer pour ouvrir le code HTML dans son navigateur. - Pour une raison quelconque, la configuration de Cowork semble dissuader Claude de générer la visionneuse d'évaluation après avoir exécuté les tests, donc juste pour réitérer: que vous soyez dans Cowork ou dans Claude Code, après avoir exécuté des tests, vous devez toujours générer la visionneuse d'évaluation pour que l'humain puisse examiner des exemples avant de réviser la compétence vous-même et d'essayer d'apporter des corrections, en utilisant
generate_review.py(sans écrire votre propre code HTML de boutique). Désolé d'avance mais je vais mettre ici toutes les majuscules: GÉNÉREZ LA VISIONNEUR D'ÉVAL AVANT d'évaluer vous-même les entrées. Vous voulez les présenter à l’humain dès que possible! - Les commentaires fonctionnent différemment: comme il n'y a pas de serveur en cours d'exécution, le bouton "Soumettre tous les avis" du spectateur téléchargera
feedback.jsonsous forme de fichier. Vous pourrez ensuite le lire à partir de là (vous devrez peut-être d'abord demander l'accès). - L'empaquetage fonctionne -
package_skill.pya juste besoin de Python et d'un système de fichiers. - L'optimisation de la description (
run_loop.py/run_eval.py) devrait très bien fonctionner dans Cowork car elle utiliseclaude -pvia un sous-processus, pas un navigateur, mais veuillez la sauvegarder jusqu'à ce que vous ayez complètement terminé de créer la compétence et que l'utilisateur accepte qu'elle soit en bon état. - Mise à jour d'une compétence existante: l'utilisateur peut vous demander de mettre à jour une compétence existante, et non d'en créer une nouvelle. Suivez les instructions de mise à jour dans la section claude.ai ci-dessus.
Fichiers de référence
Le répertoire agents/ contient des instructions pour les sous-agents spécialisés. Lisez-les lorsque vous devez générer le sous-agent concerné.
agents/grader.md- Comment évaluer les assertions par rapport aux sortiesagents/comparator.md- Comment faire une comparaison A/B aveugle entre deux sortiesagents/analyzer.md- Comment analyser pourquoi une version en bat une autre
Le répertoire references/ contient une documentation supplémentaire:
references/schemas.md- Structures JSON pour evals.json, grading.json, etc.
Répéter une fois de plus la boucle principale ici pour mettre l'accent:
- Déterminez en quoi consiste la compétence
- Rédiger ou modifier la compétence
- Exécutez Claude-with-access-to-the-skill sur les invites de test
- Avec l'utilisateur, évaluez les résultats:
- Créez benchmark.json et exécutez
eval-viewer/generate_review.pypour aider l'utilisateur à les réviser - Exécuter des évaluations quantitatives
- Créez benchmark.json et exécutez
- Répétez jusqu'à ce que vous et l'utilisateur soyez satisfaits
- Emballez la compétence finale et renvoyez-la à l'utilisateur.
Veuillez ajouter des étapes à votre TodoList, si vous en avez, pour vous assurer de ne pas l'oublier. Si vous êtes dans Cowork, veuillez spécifiquement mettre « Créer des évaluations JSON et exécutereval-viewer/generate_review.pyafin que l'humain puisse examiner les cas de test » dans votre TodoList pour vous assurer que cela se produit.
Bonne chance!
Fichiers de ressources
LICENCE.txt
Ressource binaire
agents/analyseur.md
Télécharger agents/analyzer.md
Ressource binaire
agents/comparateur.md
Télécharger agents/comparator.md
Ressource binaire
agents/niveleur.md
Ressource binaire
actifs/eval_review.html
Télécharger actifs/eval_review.html
Ressource binaire
eval-viewer/generate_review.py
Télécharger eval-viewer/generate_review.py
Ressource binaire
eval-viewer/viewer.html
Télécharger eval-viewer/viewer.html
Ressource binaire
références/schémas.md
Télécharger références/schemas.md
Ressource binaire
scripts/init.py
Télécharger les scripts/init.py
Ressource binaire
scripts/aggregate_benchmark.py
Télécharger scripts/aggregate_benchmark.py
Ressource binaire
scripts/generate_report.py
Télécharger scripts/generate_report.py
Ressource binaire
scripts/improve_description.py
Télécharger scripts/improve_description.py
Ressource binaire
scripts/package_skill.py
Télécharger scripts/package_skill.py
#!/usr/bin/env python3
"""
Skill Packager - Creates a distributable .skill file of a skill folder
Usage:
python utils/package_skill.py <path/to/skill-folder> [output-directory]
Example:
python utils/package_skill.py skills/public/my-skill
python utils/package_skill.py skills/public/my-skill ./dist
"""
import fnmatch
import sys
import zipfile
from pathlib import Path
from scripts.quick_validate import validate_skill
# Patterns to exclude when packaging skills.
EXCLUDE_DIRS = {"__pycache__", "node_modules"}
EXCLUDE_GLOBS = {"*.pyc"}
EXCLUDE_FILES = {".DS_Store"}
# Directories excluded only at the skill root (not when nested deeper).
ROOT_EXCLUDE_DIRS = {"evals"}
def should_exclude(rel_path: Path) -> bool:
"""Check if a path should be excluded from packaging."""
parts = rel_path.parts
if any(part in EXCLUDE_DIRS for part in parts):
return True
# rel_path is relative to skill_path.parent, so parts[0] is the skill
# folder name and parts[1] (if present) is the first subdir.
if len(parts) > 1 and parts[1] in ROOT_EXCLUDE_DIRS:
return True
name = rel_path.name
if name in EXCLUDE_FILES:
return True
return any(fnmatch.fnmatch(name, pat) for pat in EXCLUDE_GLOBS)
def package_skill(skill_path, output_dir=None):
"""
Package a skill folder into a .skill file.
Args:
skill_path: Path to the skill folder
output_dir: Optional output directory for the .skill file (defaults to current directory)
Returns:
Path to the created .skill file, or None if error
"""
skill_path = Path(skill_path).resolve()
# Validate skill folder exists
if not skill_path.exists():
print(f"❌ Error: Skill folder not found: {skill_path}")
return None
if not skill_path.is_dir():
print(f"❌ Error: Path is not a directory: {skill_path}")
return None
# Validate SKILL.md exists
skill_md = skill_path / "SKILL.md"
if not skill_md.exists():
print(f"❌ Error: SKILL.md not found in {skill_path}")
return None
# Run validation before packaging
print("🔍 Validating skill...")
valid, message = validate_skill(skill_path)
if not valid:
print(f"❌ Validation failed: {message}")
print(" Please fix the validation errors before packaging.")
return None
print(f"✅ {message}\n")
# Determine output location
skill_name = skill_path.name
if output_dir:
output_path = Path(output_dir).resolve()
output_path.mkdir(parents=True, exist_ok=True)
else:
output_path = Path.cwd()
skill_filename = output_path / f"{skill_name}.skill"
# Create the .skill file (zip format)
try:
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Walk through the skill directory, excluding build artifacts
for file_path in skill_path.rglob('*'):
if not file_path.is_file():
continue
arcname = file_path.relative_to(skill_path.parent)
if should_exclude(arcname):
print(f" Skipped: {arcname}")
continue
zipf.write(file_path, arcname)
print(f" Added: {arcname}")
print(f"\n✅ Successfully packaged skill to: {skill_filename}")
return skill_filename
except Exception as e:
print(f"❌ Error creating .skill file: {e}")
return None
def main():
if len(sys.argv) < 2:
print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
print("\nExample:")
print(" python utils/package_skill.py skills/public/my-skill")
print(" python utils/package_skill.py skills/public/my-skill ./dist")
sys.exit(1)
skill_path = sys.argv[1]
output_dir = sys.argv[2] if len(sys.argv) > 2 else None
print(f"📦 Packaging skill: {skill_path}")
if output_dir:
print(f" Output directory: {output_dir}")
print()
result = package_skill(skill_path, output_dir)
if result:
sys.exit(0)
else:
sys.exit(1)
if __name__ == "__main__":
main()scripts/quick_validate.py
Télécharger scripts/quick_validate.py
#!/usr/bin/env python3
"""
Quick validation script for skills - minimal version
"""
import sys
import os
import re
import yaml
from pathlib import Path
def validate_skill(skill_path):
"""Basic validation of a skill"""
skill_path = Path(skill_path)
# Check SKILL.md exists
skill_md = skill_path / 'SKILL.md'
if not skill_md.exists():
return False, "SKILL.md not found"
# Read and validate frontmatter
content = skill_md.read_text()
if not content.startswith('---'):
return False, "No YAML frontmatter found"
# Extract frontmatter
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not match:
return False, "Invalid frontmatter format"
frontmatter_text = match.group(1)
# Parse YAML frontmatter
try:
frontmatter = yaml.safe_load(frontmatter_text)
if not isinstance(frontmatter, dict):
return False, "Frontmatter must be a YAML dictionary"
except yaml.YAMLError as e:
return False, f"Invalid YAML in frontmatter: {e}"
# Define allowed properties
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata', 'compatibility'}
# Check for unexpected properties (excluding nested keys under metadata)
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
if unexpected_keys:
return False, (
f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
)
# Check required fields
if 'name' not in frontmatter:
return False, "Missing 'name' in frontmatter"
if 'description' not in frontmatter:
return False, "Missing 'description' in frontmatter"
# Extract name for validation
name = frontmatter.get('name', '')
if not isinstance(name, str):
return False, f"Name must be a string, got {type(name).__name__}"
name = name.strip()
if name:
# Check naming convention (kebab-case: lowercase with hyphens)
if not re.match(r'^[a-z0-9-]+$', name):
return False, f"Name '{name}' should be kebab-case (lowercase letters, digits, and hyphens only)"
if name.startswith('-') or name.endswith('-') or '--' in name:
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
# Check name length (max 64 characters per spec)
if len(name) > 64:
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
# Extract and validate description
description = frontmatter.get('description', '')
if not isinstance(description, str):
return False, f"Description must be a string, got {type(description).__name__}"
description = description.strip()
if description:
# Check for angle brackets
if '<' in description or '>' in description:
return False, "Description cannot contain angle brackets (< or >)"
# Check description length (max 1024 characters per spec)
if len(description) > 1024:
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
# Validate compatibility field if present (optional)
compatibility = frontmatter.get('compatibility', '')
if compatibility:
if not isinstance(compatibility, str):
return False, f"Compatibility must be a string, got {type(compatibility).__name__}"
if len(compatibility) > 500:
return False, f"Compatibility is too long ({len(compatibility)} characters). Maximum is 500 characters."
return True, "Skill is valid!"
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python quick_validate.py <skill_directory>")
sys.exit(1)
valid, message = validate_skill(sys.argv[1])
print(message)
sys.exit(0 if valid else 1)scripts/run_eval.py
Télécharger scripts/run_eval.py
Ressource binaire
scripts/run_loop.py
Télécharger scripts/run_loop.py
Ressource binaire
scripts/utils.py
"""Shared utilities for skill-creator scripts."""
from pathlib import Path
def parse_skill_md(skill_path: Path) -> tuple[str, str, str]:
"""Parse a SKILL.md file, returning (name, description, full_content)."""
content = (skill_path / "SKILL.md").read_text()
lines = content.split("\n")
if lines[0].strip() != "---":
raise ValueError("SKILL.md missing frontmatter (no opening ---)")
end_idx = None
for i, line in enumerate(lines[1:], start=1):
if line.strip() == "---":
end_idx = i
break
if end_idx is None:
raise ValueError("SKILL.md missing frontmatter (no closing ---)")
name = ""
description = ""
frontmatter_lines = lines[1:end_idx]
i = 0
while i < len(frontmatter_lines):
line = frontmatter_lines[i]
if line.startswith("name:"):
name = line[len("name:"):].strip().strip('"').strip("'")
elif line.startswith("description:"):
value = line[len("description:"):].strip()
# Handle YAML multiline indicators (>, |, >-, |-)
if value in (">", "|", ">-", "|-"):
continuation_lines: list[str] = []
i += 1
while i < len(frontmatter_lines) and (frontmatter_lines[i].startswith(" ") or frontmatter_lines[i].startswith("\t")):
continuation_lines.append(frontmatter_lines[i].strip())
i += 1
description = " ".join(continuation_lines)
continue
else:
description = value.strip('"').strip("'")
i += 1
return name, description, contentVoir dans GitHub
Usine à thème
Instructions de compétences d'agent pour créer des thèmes de marque Claude avec des palettes, une typographie et des kits de mise en page prêts à être réutilisés.
Compétence de modèle
Squelette minimal de compétences d'agent présentant les fichiers, métadonnées et légendes requis pour démarrer rapidement les nouvelles compétences Claude.
claudeskills Docs