Files
agents_and_robots/dev/issues/016-skills-system.md
T
egutierrez f561f686c4 refactor: migrar tasks/ a dev/issues/ con estructura de desarrollo
Se mueve la documentación de issues/tasks de .claude/tasks/ a dev/issues/
para separar la planificación de desarrollo de la configuración de Claude.
Se añade dev/README.md como índice de la carpeta de desarrollo. Los issues
completados se mueven a dev/issues/completed/. Esto permite que dev/ sea
el punto central de documentación interna del proyecto.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:41:16 +00:00

11 KiB

016 — Sistema de Skills para agentes

Objetivo

Crear un sistema de skills reutilizables que los agentes puedan cargar y ejecutar. Las skills son paquetes de instrucciones, scripts y recursos que amplian las capacidades de un agente mas alla de las tools de function calling. Mientras las tools son funciones atomicas (clock, http_get, ssh_command), las skills son flujos completos de trabajo (deploy a produccion, analizar logs, generar reportes).

Contexto

  • Las tools (tools/) son funciones atomicas: reciben args, ejecutan, devuelven resultado. El LLM las invoca via function calling.
  • Las skills son paquetes de instrucciones + recursos que guian al agente para completar tareas complejas multi-paso. Son como "recetas" que el agente sigue.
  • Ejemplo: una tool es ssh_command. Una skill es "deploy-service" que usa ssh_command, http_get, y logica condicional para hacer un deploy completo.

Prerequisitos

  • Ninguno estricto. El sistema de tools existente sigue funcionando igual.

Estructura de una skill

skills/<categoria>/<skill-name>/
├── SKILL.md              ← obligatorio (frontmatter YAML + instrucciones markdown)
├── LICENSE.txt            ← opcional
├── scripts/              ← opcional, codigo ejecutable (bash, python, etc.)
├── references/           ← opcional, docs de referencia
├── templates/            ← opcional, plantillas/assets
└── assets/               ← opcional, fuentes, iconos, etc.

SKILL.md — formato

---
name: skill-name
description: >
  Descripcion clara de que hace la skill y cuando debe activarse.
  Esta descripcion es el mecanismo principal de triggering.
---

# Instrucciones

Cuerpo markdown con las instrucciones completas.
Idealmente < 500 lineas.

Carga progresiva (3 niveles)

  1. Metadata (name + description) — siempre en contexto (~100 palabras). El agente la lee para decidir si activar la skill.
  2. Cuerpo del SKILL.md — se carga cuando la skill se activa. Instrucciones principales.
  3. Recursos bundled (scripts/, references/, etc.) — se cargan bajo demanda. El SKILL.md indica cuando leer cada archivo.

Carpetas opcionales

Carpeta Proposito
scripts/ Codigo ejecutable que el agente corre (bash, python). Puede ejecutarlos sin cargarlos en contexto.
references/ Documentacion extensa, leida solo cuando es relevante. Si > 300 lineas, agregar TOC al inicio.
templates/ Plantillas que la skill usa como base para generar outputs.
assets/ Archivos estaticos (fuentes, iconos, imagenes).

Tareas

Fase 1: Estructura de directorios y skills iniciales

  • 1.1 Crear la carpeta skills/ en la raiz del proyecto con subcategorias:

    skills/
    ├── README.md              ← documentacion del sistema de skills
    ├── devops/                ← skills de operaciones y deploy
    ├── analysis/              ← skills de analisis de datos/logs
    ├── communication/         ← skills de comunicacion y notificaciones
    ├── coding/                ← skills de desarrollo y code review
    └── system/                ← skills de administracion del sistema
    
  • 1.2 Crear skills iniciales de ejemplo:

    • skills/devops/deploy-service/SKILL.md — deploy de un servicio via SSH
    • skills/analysis/log-analyzer/SKILL.md — analisis de logs con patrones
    • skills/communication/daily-report/SKILL.md — generar y enviar reporte diario
    • skills/system/health-check/SKILL.md — verificar salud de servicios

Fase 2: Tipos puros en pkg/skills/

  • 2.1 Crear pkg/skills/types.go con los tipos puros:

    // SkillMeta es la metadata extraida del frontmatter YAML del SKILL.md.
    type SkillMeta struct {
        Name        string `yaml:"name"`
        Description string `yaml:"description"`
        Category    string // derivado de la ruta del directorio
    }
    
    // Skill es la representacion completa de una skill cargada.
    type Skill struct {
        Meta         SkillMeta
        Instructions string            // cuerpo markdown del SKILL.md
        BasePath     string            // ruta al directorio de la skill
        Scripts      []string          // rutas relativas a scripts/
        References   []string          // rutas relativas a references/
        Templates    []string          // rutas relativas a templates/
    }
    
    // SkillMatch indica si una skill es relevante para un contexto dado.
    type SkillMatch struct {
        Skill      SkillMeta
        Confidence float64   // 0.0 - 1.0
    }
    
  • 2.2 Crear pkg/skills/match.go — funcion pura que dado un mensaje y una lista de SkillMeta, retorna las skills mas relevantes:

    func Match(query string, skills []SkillMeta) []SkillMatch
    

    Implementacion inicial: keyword matching simple contra name + description.

Fase 3: Loader en shell/skills/

  • 3.1 Crear shell/skills/loader.go — carga skills desde el filesystem:

    // Loader descubre y carga skills desde un directorio base.
    type Loader struct {
        basePath string
    }
    
    func NewLoader(basePath string) *Loader
    func (l *Loader) LoadAll() ([]skills.Skill, error)       // carga todas las skills
    func (l *Loader) LoadMeta() ([]skills.SkillMeta, error)  // solo metadata (nivel 1)
    func (l *Loader) LoadSkill(name string) (*skills.Skill, error)  // skill completa (nivel 2)
    func (l *Loader) ReadResource(skill, path string) (string, error)  // recurso (nivel 3)
    
  • 3.2 Implementar parsing del SKILL.md:

    • Extraer frontmatter YAML entre ---
    • Extraer cuerpo markdown
    • Listar archivos en subcarpetas opcionales

Fase 4: Integracion con el runtime

  • 4.1 Anadir skillLoader *shellskills.Loader al struct Agent en agents/runtime.go

  • 4.2 Crear una tool skill_search en tools/skills/ que permita al LLM buscar skills relevantes:

    // Def: name="skill_search", params=[{name: "query", type: "string"}]
    // Exec: usa el loader para buscar skills por relevancia
    
  • 4.3 Crear una tool skill_load en tools/skills/ que cargue el contenido completo de una skill:

    // Def: name="skill_load", params=[{name: "skill_name", type: "string"}]
    // Exec: retorna las instrucciones completas del SKILL.md
    
  • 4.4 Crear una tool skill_read_resource para cargar recursos bajo demanda:

    // Def: name="skill_read_resource", params=[{name: "skill_name"}, {name: "path"}]
    // Exec: lee un archivo de scripts/, references/, templates/, o assets/
    
  • 4.5 Registrar las tools de skills en el builder de tools de runtime.go

  • 4.6 Inyectar la lista de skills disponibles (nivel 1: metadata) en el system prompt del agente, para que sepa que skills tiene a disposicion.

Fase 5: Configuracion

  • 5.1 Anadir seccion skills: al config schema en internal/config/schema.go:

    type SkillsCfg struct {
        Enabled    bool     `yaml:"enabled"`
        SkillsPath string   `yaml:"path"`          // default: "skills/"
        Categories []string `yaml:"categories"`     // filtro opcional de categorias
    }
    
  • 5.2 Anadir SkillsCfg al AgentConfig principal

  • 5.3 Respetar el filtro de categorias: si un agente solo tiene categories: [devops, system], no carga skills de analysis/ o communication/

Fase 6: Ejecucion de scripts

  • 6.1 Evaluar como ejecutar scripts de skills de forma segura:

    • Los scripts viven en skills/<cat>/<name>/scripts/
    • El agente necesita permisos para ejecutarlos (similar a ssh_command)
    • Opcion A: ejecutar via os/exec con sandbox basico (allowlist de interpreters)
    • Opcion B: ejecutar via SSH contra localhost (reutiliza infra existente)
    • Opcion C: solo permitir bash scripts con validacion previa
    • Recomendacion: opcion A con allowlist configurable de interpreters
  • 6.2 Crear shell/skills/executor.go para ejecutar scripts:

    type Executor struct {
        allowedInterpreters []string // ["bash", "python3", "sh"]
        timeout             time.Duration
    }
    func (e *Executor) Run(ctx context.Context, scriptPath string, args []string) (string, error)
    
  • 6.3 Crear tool skill_run_script en tools/skills/:

    // Def: name="skill_run_script", params=[{name: "skill_name"}, {name: "script"}, {name: "args"}]
    // Exec: ejecuta un script de la skill con el executor
    

Fase 7: Tests

  • 7.1 Unit tests para pkg/skills/types.go — verificar parsing de metadata
  • 7.2 Unit tests para pkg/skills/match.go — verificar matching de skills
  • 7.3 Unit tests para shell/skills/loader.go — verificar carga desde filesystem (con directorio temporal)
  • 7.4 Unit tests para shell/skills/executor.go — verificar ejecucion de scripts
  • 7.5 Integration test: un agente con skills habilitadas puede buscar, cargar y ejecutar una skill

Fase 8: Documentacion

  • 8.1 Crear skills/README.md con la guia completa del sistema de skills
  • 8.2 Actualizar CLAUDE.md — anadir skills/, pkg/skills/, shell/skills/ a la estructura
  • 8.3 Crear .claude/rules/create_skill.md — regla para crear nuevas skills
  • 8.4 Actualizar docs/creating-agents.md con la seccion de skills

Orden de ejecucion recomendado

  1. Fase 1 (estructura + skills de ejemplo) — valida el formato antes de escribir codigo
  2. Fase 2 (tipos puros) — base para el loader y matching
  3. Fase 3 (loader) — carga skills desde disco
  4. Fase 5 (config) — permite habilitar/configurar skills por agente
  5. Fase 4 (integracion runtime) — conecta skills al agente via tools
  6. Fase 6 (ejecucion scripts) — opcional, solo si hay scripts
  7. Fase 7 (tests) — validar todo
  8. Fase 8 (docs) — cuando todo este estable

Decisiones de diseno

  • Skills vs Tools: las tools son atomicas (function calling). Las skills son flujos multi-paso que el agente sigue como instrucciones. Las skills USAN tools internamente.
  • Carga progresiva: no cargar todo en contexto — solo metadata siempre, instrucciones cuando se activa, recursos bajo demanda.
  • Skills como carpeta en raiz: viven en skills/ (no en pkg/ ni shell/) porque son contenido declarativo, no codigo Go. Similar a como agents/ tiene configs y prompts.
  • Subcategorias: organizadas por dominio (devops, analysis, etc.) como los tools por funcion (clock, http, ssh, etc.).
  • Seguridad de scripts: los scripts de skills deben tener las mismas restricciones que ssh_command — allowlist de interpreters, timeout, sin acceso a secretos directos.

Analogia con el patron del proyecto

pkg/skills/     → PURE: tipos SkillMeta, Skill, SkillMatch + matching puro
shell/skills/   → IMPURE: Loader (filesystem), Executor (os/exec)
tools/skills/   → tools de function calling para que el LLM interactue con skills
skills/         → contenido declarativo (SKILL.md + recursos)

Riesgos

  • Inflar el contexto del LLM si se cargan muchas skills de golpe — mitigado por carga progresiva
  • Ejecucion de scripts arbitrarios — mitigado por allowlist de interpreters y timeout
  • Complejidad innecesaria si los agentes actuales no necesitan skills — empezar con 2-3 skills simples y validar