Saltar al contenido
astorlm
Idioma: Español
← Mapa

Nivel 8

Skills bajo demanda

Una skill es un manual para un tipo de trabajo. El agente siempre ve la lista de manuales, y lee uno solo cuando un pedido lo requiere.
1/16 Pliegues del bandoneón:
  • user
  • assistant
  • tool_result
El asistente de pedidos de una panadería. Tres libros de recetas en el estante: esas son sus skills. Sobre el pase cuelga una comanda por libro, con su nombre y una línea sobre cuándo usarlo. Solo las comandas van en el system prompt.

EventBus

El problema

El asistente de pedidos de una panadería necesita conocer las reglas de la casa. Qué tamaño de pastel alcanza para 20 personas. Que los pasteles sin frutos secos solo se hornean los viernes por la mañana. Cuánto es el anticipo. Cómo cotizar una bandeja de catering. Qué lleva cada producto que ya está en los estantes. El modelo no sabe nada de eso.

El arreglo obvio es escribirlo todo y pegarlo en el system prompt. Funciona el primer día. Después los manuales crecen, y ya son diez. Cada pedido carga ahora todos los manuales, en cada turno, ya sea que el cliente quiera un pastel de bodas o solo el horario de atención. Pagas por todo eso, los pedidos se vuelven más lentos, y la única regla que importa queda enterrada entre las que no.

Ese es Tomebloat, el system prompt inflado. Alimenta a Gulp, del nivel 7: un prompt que ya está lleno deja menos lugar para la conversación en sí.

La solución

Divide cada manual en dos. Una descripción de una o dos líneas dice cuándo se aplica la skill. El cuerpo dice cómo hacer el trabajo. Solo las descripciones van en el system prompt, como un catálogo. Cuando un pedido coincide con una, el modelo pide su cuerpo, y el cuerpo se suma a la conversación de ahí en adelante.

Eso es progressive disclosure (revelación progresiva): primero mostrar el índice, y el detalle solo cuando hace falta. El formato habitual es una carpeta por skill con un archivo SKILL.md. El frontmatter del principio (el bloque entre las líneas ---) tiene el nombre y la descripción. Todo lo que está debajo es el cuerpo.

---
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.

Hay tres formas comunes de entregarle skills al modelo. astorlm soporta las tres con skillMode:

  • all

    El cuerpo completo de cada skill va en el system prompt, desde el primer pedido.

    Sin llamadas extra, y el modelo no puede saltarse un manual. Sirve para dos o tres skills cortas que casi todos los pedidos necesitan. Más allá de eso, es Tomebloat.

  • on-demand

    El system prompt lista el nombre y la descripción de cada skill. Una herramienta load_skill devuelve el cuerpo completo cuando el modelo lo pide.

    Escala a docenas de skills. Cuesta una llamada a herramienta por cada skill cargada, y a veces los modelos chicos responden sin cargar la skill que necesitaban.

  • filesystem

    El catálogo también da la ruta de cada SKILL.md, y el modelo lo abre con su herramienta común de lectura de archivos.

    La misma idea sin una herramienta especial. Así lo hacen Claude Code, Codex y Gemini CLI, por eso la misma carpeta de skills funciona en todos. Necesita un agente que pueda leer archivos.

Una skill no es una herramienta. Una herramienta es algo que el bucle ejecuta para el modelo. Una skill es algo que el modelo lee, y puede decirle qué herramientas llamar y en qué orden, como la receta que dice “revisa el calendario antes de prometer una fecha”.

El elenco

El mismo elenco de siempre, esta vez en la cocina de una panadería.

El Oráculo el modelo
El chef detrás del pase. Lee lo que tenga enfrente, en cada turno, y no cocina nada él mismo.
Las comandas el catálogo
Una por skill, en el riel sobre el pase: un nombre y una línea sobre cuándo usarla. Son parte del system prompt, así que van en cada pedido.
El estante los cuerpos de las skills
Un libro de recetas por skill, cerrado. Cuanto más grueso el libro, más tokens pesa. Nada de eso le llega al modelo hasta que alguien lo busca.
El libro abierto una skill cargada
load_skill devuelve el cuerpo como resultado de herramienta (el señalador verde). Entra en el bandoneón como cualquier resultado, así que queda abierto sobre el pase por el resto de la ejecución.
El horno check_calendar
Una herramienta común. Es la receta la que le dice al modelo que la use.
La barra tamaño del pedido
Cuántos tokens lleva el próximo pedido. Su largo completo es lo que llevaría con los tres libros pegados en el system prompt.

En el panel EventBus, load_skill aparece como un tool_execution_start y un tool_execution_end comunes. El bucle no tiene idea de que existen las skills: para él, cargar un manual es una llamada a herramienta más.

El código

Con astorlm: Apunta skillSources a una carpeta de skills. El valor por defecto skillMode: 'on-demand' pone el catálogo en el system prompt y agrega la herramienta load_skill por ti.

Desde cero: Lee cada SKILL.md, pon una línea por skill en el system prompt y agrega una herramienta load_skill que devuelva un cuerpo. El bucle del nivel 2 no cambia en absoluto.

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)

Qué vigilar

  • La descripción es el disparador. El modelo elige una skill solo por su descripción, igual que elige una herramienta (nivel 3). Di cuándo usarla, no qué contiene: “Úsala cuando un cliente quiere que le horneen un pastel” es mejor que “Información sobre pasteles”. En la animación, allergen-info también menciona alergias; solo las descripciones evitan que el modelo cargue el libro equivocado.
  • Los modelos chicos se saltan el paso. Algunos responden directo sin cargar la skill que necesitaban. Dilo claramente en el system prompt (“carga la skill correspondiente antes de responder”), prueba el modo filesystem o, para una skill que todos los pedidos necesitan, déjala en all.
  • Una skill cargada queda cargada. Su cuerpo está en el historial, así que cada turno posterior lo paga, y la compactación (nivel 7) puede truncarlo más adelante. Mantén los cuerpos cortos y divide las skills grandes en dos.
  • Las skills son instrucciones, así que son código. Quien escribe un SKILL.md dirige a tu agente. No cargues skills desde carpetas o registros que no controlas (nivel 14).