Aller au contenu
astorlm
Langue: Français
← Carte

Niveau 8

Des skills à la demande

Une skill, c'est un manuel pour un type de travail. L'agent voit toujours la liste des manuels, et n'en lit un que quand une requête l'exige.
1/16 Plis du bandonéon :
  • user
  • assistant
  • tool_result
L'assistant de commandes d'une boulangerie. Trois livres de recettes sur l'étagère : ce sont ses skills. Au-dessus du passe pend un ticket par livre, avec son nom et une ligne sur quand l'utiliser. Seuls les tickets vont dans le system prompt.

EventBus

Le problème

L'assistant de commandes d'une boulangerie doit connaître les règles de la maison. Quelle taille de gâteau pour 20 personnes. Que les gâteaux sans fruits à coque ne cuisent que le vendredi matin. Le montant de l'acompte. Comment chiffrer un plateau traiteur. Ce que contient chaque produit déjà en rayon. Le modèle n'en sait rien.

La solution évidente : tout écrire et le coller dans le system prompt. Ça marche le premier jour. Puis les manuels grossissent, et il y en a dix. Chaque requête transporte désormais tous les manuels, à chaque tour, que le client veuille une pièce montée ou seulement les horaires d'ouverture. Vous payez pour tout ça, les requêtes ralentissent, et la seule règle qui compte est enterrée sous celles qui ne comptent pas.

C'est Tomebloat, le system prompt boursouflé. Il nourrit Gulp, du niveau 7 : un prompt déjà plein laisse moins de place à la conversation elle-même.

La solution

Coupez chaque manuel en deux. Une description d'une ou deux lignes dit quand la skill s'applique. Le corps dit comment faire le travail. Seules les descriptions vont dans le system prompt, sous forme de catalogue. Quand une requête correspond à l'une d'elles, le modèle demande son corps, et le corps rejoint la conversation à partir de là.

C'est la progressive disclosure (divulgation progressive) : montrer d'abord l'index, et le détail seulement quand il le faut. Le format habituel est un dossier par skill avec un fichier SKILL.md. Le frontmatter en tête (le bloc entre les lignes ---) contient le nom et la description. Tout ce qui suit est le corps.

---
name: custom-cake-order
description: Cakes made to order. Use when a customer wants a cake baked for them — size by guests, flavors, allergies, lead time, deposit.
---

# Custom cake orders

1. Size by guests: up to 12 → 18 cm, up to 24 → 24 cm, more → two tiers.
2. Flavors: chocolate, vanilla, dulce de leche. Nothing else.
3. Nut allergy → the nut-free line. It only bakes on Friday mornings.
4. Check the calendar before you promise a date. Never less than 72 hours.
5. Quote the 50% deposit, and ask before you book. Never book on your own.

Il y a trois façons courantes de donner des skills au modèle. astorlm prend en charge les trois avec skillMode :

  • all

    Le corps complet de chaque skill va dans le system prompt, dès la première requête.

    Aucun appel en plus, et le modèle ne peut pas sauter un manuel. Très bien pour deux ou trois skills courtes dont presque chaque requête a besoin. Au-delà, c'est Tomebloat.

  • on-demand

    Le system prompt liste le nom et la description de chaque skill. Un outil load_skill renvoie le corps complet quand le modèle le demande.

    Ça passe à l'échelle jusqu'à des dizaines de skills. Ça coûte un appel d'outil par skill chargée, et les petits modèles répondent parfois sans charger la skill dont ils avaient besoin.

  • filesystem

    Le catalogue donne aussi le chemin de chaque SKILL.md, et le modèle l'ouvre avec son outil ordinaire de lecture de fichiers.

    La même idée, sans outil spécial. C'est ainsi que font Claude Code, Codex et Gemini CLI, donc le même dossier de skills fonctionne partout. Il faut un agent capable de lire des fichiers.

Une skill n'est pas un outil. Un outil, c'est quelque chose que la boucle exécute pour le modèle. Une skill, c'est quelque chose que le modèle lit, et elle peut lui dire quels outils appeler et dans quel ordre, comme la recette qui dit « vérifie le calendrier avant de promettre une date ».

Les personnages

Les mêmes personnages que d'habitude, cette fois dans la cuisine d'une boulangerie.

L'Oracle le modèle
Le chef derrière le passe. Il lit ce qu'il a devant lui, à chaque tour, et ne cuisine rien lui-même.
Les tickets le catalogue
Un par skill, sur le rail au-dessus du passe : un nom et une ligne sur quand l'utiliser. Ils font partie du system prompt, donc ils partent avec chaque requête.
L'étagère les corps des skills
Un livre de recettes par skill, fermé. Plus le livre est épais, plus il pèse de tokens. Rien de tout ça n'atteint le modèle tant que personne ne va le chercher.
Le livre ouvert une skill chargée
load_skill renvoie le corps comme résultat d'outil (le marque-page vert). Il entre dans le bandonéon comme n'importe quel résultat, donc il reste ouvert sur le passe pour le reste de l'exécution.
Le four check_calendar
Un outil ordinaire. C'est la recette qui dit au modèle de s'en servir.
La barre taille de la requête
Combien de tokens transporte la prochaine requête. Sa longueur totale correspond à ce qu'elle transporterait avec les trois livres collés dans le system prompt.

Dans le panneau EventBus, load_skill apparaît comme un tool_execution_start et un tool_execution_end ordinaires. La boucle n'a aucune idée que les skills existent : pour elle, charger un manuel n'est qu'un appel d'outil de plus.

Le code

Avec astorlm : Pointez skillSources vers un dossier de skills. La valeur par défaut skillMode: 'on-demand' met le catalogue dans le system prompt et ajoute l'outil load_skill pour vous.

À partir de zéro : Lisez chaque SKILL.md, mettez une ligne par skill dans le system prompt, et ajoutez un outil load_skill qui renvoie un corps. La boucle du niveau 2 ne change pas du tout.

import { OpenAIProvider, createFileSystemSkillSource, createLocalAgent, tool } from 'astorlm'
import { z } from 'zod'

const checkCalendar = tool({
  name: 'check_calendar',
  description: 'Free baking slots and pickup times for a day, per production line.',
  schema: z.object({ day: z.string(), line: z.enum(['regular', 'nut-free']) }),
  execute: async ({ day, line }) => bakerySlots(day, line), // your code
})

const agent = await createLocalAgent({
  // Any OpenAI-compatible endpoint: OpenAI, Ollama, LM Studio, vLLM, a proxy…
  provider: new OpenAIProvider({
    baseURL: 'http://localhost:11434/v1', // e.g. Ollama's default address
    model: 'your-model', // e.g. 'llama3.1', 'gpt-4o-mini'
    apiKey: 'YOUR_API_KEY', // local servers usually ignore it
  }),
  tools: [checkCalendar],
  // Every folder in ./skills with a SKILL.md is one skill:
  //   skills/custom-cake-order/SKILL.md, skills/catering-quote/SKILL.md, …
  skillSources: [createFileSystemSkillSource({ dir: './skills' })],
  // The default. Only each skill's name and description go in the system prompt,
  // and the agent gets a load_skill tool to fetch a full body when it needs one.
  skillMode: 'on-demand',
  maxTurns: 10,
})

agent.on('tool-end', ({ name, output }) => {
  if (name === 'load_skill') console.log('loaded:', output.slice(0, 60))
})

const last = await agent.run('I need a cake for 20 people this Saturday. Chocolate, and one guest can’t have nuts.')
console.log(last.content)

Points de vigilance

  • La description est le déclencheur. Le modèle choisit une skill sur sa seule description, comme il choisit un outil (niveau 3). Dites quand l'utiliser, pas ce qu'elle contient : « À utiliser quand un client veut un gâteau fait sur commande » vaut mieux que « Informations sur les gâteaux ». Dans l'animation, allergen-info mentionne aussi les allergies ; seules les descriptions évitent au modèle de charger le mauvais livre.
  • Les petits modèles sautent l'étape. Certains répondent tout de suite sans charger la skill dont ils avaient besoin. Dites-le clairement dans le system prompt (« charge la skill correspondante avant de répondre »), essayez le mode filesystem ou, pour une skill dont chaque requête a besoin, gardez-la en all.
  • Une skill chargée reste chargée. Son corps est dans l'historique, donc chaque tour suivant le paie, et la compaction (niveau 7) peut le tronquer plus tard. Gardez des corps courts et coupez les grosses skills en deux.
  • Les skills sont des instructions, donc du code. Quiconque écrit un SKILL.md pilote votre agent. Ne chargez pas de skills depuis des dossiers ou des registres que vous ne contrôlez pas (niveau 14).