Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Écrire un Skill Bundle

Un paquet de compétences est le seul type de plugin qui ne contient aucun code WebAssembly. Il s’agit d’un répertoire de compétences Markdown, empaqueté et distribué via le mécanisme des plugins : même manifeste, même découverte, même politique de signature, même zeroclaw plugin install. Utilisez-le lorsque la fonctionnalité que vous ajoutez consiste en des instructions, des invites et des workflows plutôt qu’en du code, et que vous préférez les sémantiques de distribution de plugins (signature, installation via le registre, gestion des versions) à des fichiers isolés dans un répertoire de compétences.

Vérifiez d’abord votre binaire. Les bundles de skills reposent sur la machinerie des plugins, et les binaires de release préconstruits fournis par l’installateur sont compilés sans la fonctionnalité plugins-wasm : sur un binaire standard, zeroclaw plugin ... est une sous-commande non reconnue et les skills fournis par les plugins ne se chargent pas. Pour utiliser les bundles de cette page, compilez depuis les sources avec un backend d’exécution de plugins, par exemple cargo build --release --features plugins-wasm-cranelift. Si vous voulez simplement un répertoire partagé de skills sur un binaire standard, utilisez plutôt les bundles natifs décrits dans Skills : zeroclaw skills bundle add <alias> en crée un et zeroclaw skills install <source> --bundle <alias> y installe des skills, vous offrant les mêmes skills sans la sémantique de distribution des plugins.

Ce guide est vérifié par rapport au chemin de validation dans crates/zeroclaw-plugins/src/host.rs (validate_skill_bundle, validate_skill_md_frontmatter) et le chargeur dans crates/zeroclaw-runtime/src/skills/mod.rs.

Pour savoir ce qu’est une compétence et comment les agents les utilisent, lisez d’abord Skills. Cette page ne traite que de l’empaquetage des bundles.

Disposition

Un plugin ne contenant que des compétences omet wasm_path et inclut un répertoire skills/ au format agentskills.io :

my-toolkit/
  manifest.toml           # capabilities = skill only, no wasm_path
  README.md               # optional bundle-level overview
  skills/
    design-review/
      SKILL.md
      scripts/            # optional
      references/         # optional
    code-review/
      SKILL.md
    data-analysis/
      SKILL.md
      references/

Validation : ce que la découverte impose

L’hôte valide la forme du bundle lors de la découverte et de l’installation, et rejette l’ensemble du plugin à la première défaillance (validate_skill_bundle dans host.rs). Les règles exactes :

  1. skills/ doit exister et être un répertoire.
  2. Il doit contenir au moins un sous-répertoire. Un skills/ vide est un manifeste invalide, et non un bundle vide.
  3. Chaque sous-répertoire doit contenir un SKILL.md.
  4. Chaque SKILL.md doit commencer par un frontmatter YAML (un délimiteur --- sur la première ligne, clôturé par un ---), et ce frontmatter doit déclarer les clés name et description non vides.

La vérification du frontmatter s’exécute volontairement au moment de la découverte : un bundle dont les skills omettent name ou description échoue lors du chargement du plugin, et non lorsqu’un agent invoque la skill pour la première fois en cours de conversation.

Un en-tête de compétence valide :

---
name: design-review
description: Structured design review workflow for architecture proposals.
---

# Design Review

...instructions...

Namespacing

Les compétences du bundle chargé sont enregistrées sous des identifiants qualifiés par le plugin : plugin:<plugin-name>/<skill-name>, par exemple plugin:my-toolkit/design-review (namespace_plugin_skill dans skills/mod.rs). Chaque compétence reçoit également un tag plugin:<plugin-name>. Cela évite les conflits avec les compétences créées par les utilisateurs et entre les bundles : deux bundles peuvent à la fois fournir une compétence code-review et coexister.

Le namespacing interagit avec la priorité des skills : dans la résolution des skills effectives de l’agent, les skills de même nom provenant de sources différentes sont dédupliqués par priorité et les perdants sont enregistrés comme masqués. Le qualificatif de plugin maintient votre bundle entièrement hors de ce conflit, sauf si une autre copie du même nom de bundle est en jeu.

Scripts

Une compétence peut comporter un répertoire scripts/. Le chargement des compétences contenant des scripts est régi par le paramètre skills.allow_scripts de l’opérateur, que le chargeur de compétences de plugin transmet sans modification (discover_plugin_skills dans skills/mod.rs) : une compétence bundle avec des scripts est soumise aux mêmes règles d’audit et de suppression qu’une compétence workspace. Ne supposez pas que vos scripts s’exécutent simplement parce que le bundle a été installé.

Manifeste

Le manifeste est le fichier nommé manifest.toml dans le répertoire du plugin. Ses champs sont la surface serde de PluginManifest dans crates/zeroclaw-plugins/src/lib.rs, qui est la source de vérité :

ChampObligatoireSignification
nameouiSlug canonique unique du package et composant du package de chaque clé de configuration d’instance dérivée. Il ne constitue pas lui-même une clé de configuration d’opérateur. Utilisez 1–128 caractères ASCII en minuscules ; commencez et terminez par [a-z0-9], avec uniquement [a-z0-9._-] entre les deux. La découverte rejette les noms non valides ou en double.
versionouiChaîne de version, p. ex. 0.1.0.
descriptionnonDescription lisible affichée par zeroclaw plugin list.
authornonNom de l’auteur ou de l’organisation.
wasm_pathpour les capacités WASMNom du fichier du composant, relatif au répertoire du plugin. Obligatoire sauf si la seule capacité est skill. La découverte ignore le plugin si le fichier nommé n’existe pas.
capabilitiesoui, non videCe qu’est le plugin : l’un de tool, channel, memory, observer, skill (PluginCapability, sérialisé en snake_case).
permissionsnonServices de l’hôte auxquels le code peut accéder : http_client, config_read, file_read, file_write, memory_read, memory_write (PluginPermission). Seuls les deux premiers sont appliqués aujourd’hui ; les autres sont acceptés mais inactifs. Déclarer config_read nécessite config_schema, et seuls les adaptateurs d’outils/de canaux le fournissent actuellement.
config_schemaexactement avec config_readRédigez un schéma JSON Draft 2020-12 pour la configuration privée de ce plugin ; il est inclus dans les octets du manifeste canonique et est donc couvert lorsque le manifeste est signé. La racine doit être un objet avec un mappage properties et additionalProperties = false. Chaque propriété de premier niveau doit avoir un type pris en charge explicite, directement ou via un pointeur JSON local : string, boolean, integer, number, array ou object. Les consommateurs d’outils et de canaux peuvent définir x-secret = true directement sur une propriété de type chaîne de premier niveau pour la retirer de la configuration publique et l’exposer via l’import d’hôte à portée limitée secrets.get. Les outils reçoivent la configuration publique sous __config et peuvent lire les secrets pendant execute. Les canaux lisent l’objet public actuel via config.get et les secrets via secrets.get pendant configure et les appels opérationnels ; ces deux imports sont indisponibles lors de l’instanciation et de la découverte des métadonnées statiques. Les marqueurs secrets imbriqués, false ou non booléens, ainsi que les propriétés secrètes qui ne sont pas de type chaîne sont rejetés. Un schéma sans config_read, ou config_read sans schéma, est rejeté.
signaturenonSignature Ed25519 en Base64url sur les octets canoniques du manifest. Défini lors de la signature pour la distribution.
publisher_keynonClé publique Ed25519 encodée en hexadécimal du signataire.

Déclarez uniquement les permissions effectivement utilisées par le code. Une permission non déclarée est une surface d’hôte que le composant ne peut pas atteindre ; une permission déclarée de manière superflue est une surface d’attaque que vous avez sollicitée et une charge d’audit pour quiconque révise votre plugin.

Les valeurs des opérateurs restent des chaînes dans plugins.entries et sont chiffrées lors de leur persistance, avec pour clé une chaîne zpi1_… versionnée dérivée de l’identité du package détenu par l’hôte, de la capacité et de la liaison (l’installation affiche et initialise la clé d’instance complète de la liaison d’outil par défaut) : les chaînes sont stockées telles quelles, les booléens et les nombres sont représentés par du texte scalaire JSON, et les tableaux et les objets par du texte JSON. Avant l’exécution de tout code invité, l’hôte matérialise ces chaînes selon les types du schéma du package et valide l’objet complet pour les adaptateurs d’outils et de canaux. Les propriétés non secrètes de l’outil constituent __config ; un canal obtient l’objet non secret via config.get. Une propriété marquée x-secret = true est exclue des deux surfaces publiques et n’est accessible que via secrets.get("property") dans un cadre de service autorisé. Les lectures publiques et secrètes d’un canal au cours d’un même appel partagent une révision canonique unique, et l’hôte supprime cette vue matérialisée à la fin de l’appel. Un plugin de canal conforme doit résoudre les deux à chaque point d’utilisation et ne doit pas conserver les valeurs de configuration ou d’identifiants dans l’état invité conservé à chaud ; renvoyer du texte en clair à l’invité signifie que l’hôte ne peut pas imposer la non-rétention face à du code malveillant. Si config_read a été demandé mais n’a pas été effectivement accordé, l’hôte valide un objet vide ; par conséquent, un schéma comportant des propriétés obligatoires échoue en mode sécurisé au lieu de démarrer sans la configuration requise. Si l’objet vide est valide, un outil omet __config lorsqu’il est vide et les imports config/secret du canal renvoient access-denied ; les appels effectués hors d’un cadre autorisé, les échecs de résolution et l’épuisement du budget d’appels à l’hôte renvoient unavailable.

Pour un bundle de compétences : capabilities contenant exactement skill, aucun wasm_path, et généralement aucun permissions ; le bundle est une donnée, et l’ensemble des permissions contrôle l’accès aux fonctions hôtes que markdown n’appelle jamais.

Un plugin aux capacités mixtes (par exemple tool + skill) est autorisé : il doit alors contenir un wasm_path valide pour le monde des outils et un bundle skills/ valide, et les deux validations sont exécutées.

Installer et vérifier

Ces commandes nécessitent un binaire dans lequel l’hôte de plugins a été compilé. Les binaires de publication précompilés fournis par le programme d’installation sont compilés sans la fonctionnalité plugins-wasm, donc zeroclaw plugin ... y est une sous-commande non reconnue et les plugins installés ne sont jamais découverts. Compilez depuis les sources avec un backend d’exécution de plugins, par ex. cargo build --release --features plugins-wasm-cranelift.

Chaque plugin réside dans son propre sous-répertoire du répertoire des plugins (par défaut ~/.zeroclaw/plugins/, résolu via plugins.plugins_dir), contenant le manifeste et le composant dont le nom correspond au wasm_path du manifeste :

~/.zeroclaw/plugins/
└── my-plugin/
    ├── manifest.toml
    └── my-plugin.wasm

Installer à partir d’un répertoire local (cela valide la structure du manifeste et applique la politique de signature avant de copier quoi que ce soit) :

zeroclaw plugin install ./my-plugin/

Activer le système de plugins et confirmer la découverte :

zeroclaw config set plugins.enabled true
zeroclaw plugin list
zeroclaw plugin info my-plugin

zeroclaw plugin list et zeroclaw plugin info confirment qu’un package est installé et détectable, mais la découverte n’équivaut pas à l’activation. plugins.enabled = true active l’hôte de plugins ; les fonctionnalités d’outils et de compétences découvertes automatiquement sont chargées à l’exécution uniquement lorsque plugins.auto_discover = true l’est également, et cet indicateur vaut false par défaut (refus en cas d’échec) :

zeroclaw config set plugins.auto_discover true

Ainsi, plugins.enabled = true à lui seul vous fournit les canaux que vous déclarez sous [channels.plugin.<alias>], mais aucun outil ni aucune compétence de plugin : un paquet d’outils ou de compétences peut apparaître dans zeroclaw plugin list tout en n’apportant rien à l’exécution. Les liaisons de canaux explicites sont nommées par l’opérateur plutôt que découvertes automatiquement ; elles n’ont donc pas besoin de auto_discover ; cet indicateur contrôle uniquement les outils et compétences découverts automatiquement.

Un plugin absent de zeroclaw plugin list a été ignoré lors de la découverte : consultez le journal de démarrage pour l’avertissement d’ignorance (manifeste corrompu, fichier wasm_path manquant ou rejet par la politique de signature).

Après leur découverte, les compétences apparaissent avec un espace de noms sur les interfaces de compétences (la liste des compétences, le tableau de bord) sous la forme plugin:<your-bundle>/<skill>. Demandez à l’agent d’en utiliser un pour valider le fonctionnement de bout en bout.

Suivant

  • Distribution de plugins : un skill bundle est la chose la plus simple à publier, et le processus de signature est identique à celui des plugins WASM.