# 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

```yaml
---
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:
  ```go
  // 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:
  ```go
  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:
  ```go
  // 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:
  ```go
  // 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:
  ```go
  // 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:
  ```go
  // 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`:
  ```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:
  ```go
  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/`:
  ```go
  // 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
