---
name: diseno-herramientas-agente
description: >
  Principios de diseno de herramientas (tools) para agentes de IA: Principio de
  Consolidacion, reduccion arquitectonica, limite 10-20 tools por coleccion,
  description como prompt engineering, naming MCP y diseno de mensajes de error.
  Cargar cuando se disenan tools para agentes, se configura MCP, se definen
  toolBudget en agentes SWL, o se evalua la coleccion de herramientas de un agente.
version: "1.1.0"
herramientasPermitidas: [Read, Grep]
exclusiones:
  - "No cargar para implementar el hook que ejecuta los tools — este skill diseña la interfaz, no el handler; para implementar PreToolUse o PostToolUse cargar `hooks` o el agente correspondiente."
  - "No cargar para evaluar si un agente específico cumple su SLA — eso es `evaluacion-agentes`; este skill cubre diseño de colecciones de tools, no rendimiento de agentes."
  - "No cargar cuando el cambio es solo actualizar la descripción de una tool existente sin rediseñar la colección — el costo de carga no compensa para un fix de texto de una línea."
  - "No cargar para configurar permisos de red o escritura en frontmatter de agentes — eso cae bajo `seguridad-agentes` y `estructura-proyecto-claude`."
evolvable: true  # default para skill estandar
---
# Diseno de Herramientas para Agentes

## Cuando cargar

- Al disenar o revisar tools para agentes de IA (MCP servers, function calling)
- Al configurar `toolBudget` o `tools` en frontmatter de agentes SWL
- Al evaluar si un agente tiene demasiadas o muy pocas herramientas
- Al escribir descripciones de herramientas para consumo de LLMs
- Al disenar mensajes de error que un agente pueda interpretar

---

## Principio de Consolidacion

> Cuando multiples herramientas se solapan en funcionalidad, consolidar en una
> sola herramienta con parametros que controlan el comportamiento.

El exceso de herramientas similares degrada el rendimiento del agente porque:
- Aumenta el espacio de decision en cada turno
- Genera confuision sobre cuial herramienta usar para queii
- Consume tokens de contexto en las descripciones de cada tool

### Reduccion arquitectonica

Preferir la coleccion MINIMA de herramientas que cubra todos los casos de uso.
Si una herramienta puede hacer lo que dos hacen por separado con un parametro
adicional, consolidar.

```
MAL (3 tools solapadas):
- search_files_by_name
- search_files_by_content
- search_files_by_pattern

BIEN (1 tool con parametro):
- search_files(query, mode: "name" | "content" | "pattern")
```

### Limite de herramientas por coleccion

| Tamano de coleccion | Evaluacion |
|---------------------|------------|
| **1-10 tools** | Optimo. El agente puede razonar sobre todas sin confusion |
| **10-20 tools** | Aceptable. Documentar agrupacion logica para orientar al agente |
| **20-30 tools** | Riesgoso. Considerar dividir en sub-agentes especializados |
| **30+ tools** | Problematico. El agente perdera tiempo eligiendo y cometera errores |

En SWL, el `toolBudget` del frontmatter de agentes controla cuantos tool calls
puede hacer un agente por tarea (simple/standard/complex). El diseno de herramientas
complementa esto: menos herramientas mejor disenadas = menos calls necesarios.

---

## Description como prompt engineering

La `description` de una herramienta es un prompt para el LLM. No es documentacion
para humanos. Disenarla como instruccion de activacion:

### Estructura de una description efectiva

```
[QUE hace en 1 oracion]
[CUANDO usarla — condiciones de activacion]
[CUANDO NO usarla — desambiguacion con herramientas similares]
[RESTRICCIONES criticas si las hay]
```

### Ejemplo concreto

```
MAL:
  description: "Lee un archivo del sistema de archivos."

BIEN:
  description: "Lee el contenido de un archivo por su ruta absoluta.
  Usar para archivos de texto, codigo fuente, JSON, YAML y Markdown.
  Para archivos binarios (imagenes, PDFs) usar read_binary en su lugar.
  Limite: 2000 lineas por defecto; usar offset/limit para archivos grandes."
```

### Regla de los 100 tokens

La description de una herramienta debe tener entre 50 y 100 tokens. Menos de 50
no da suficiente contexto de activacion. Mas de 100 consume contexto sin beneficio
proporcional.

---

## Naming de herramientas MCP

Para servidores MCP, el nombre de la herramienta sigue el patron:
`ServerName:tool_name`

Reglas de naming:
- `tool_name` en snake_case (no kebab-case, no camelCase)
- Verbo + sustantivo: `search_files`, `create_issue`, `read_document`
- Sin prefijos redundantes: `github:github_create_issue` es redundante;
  usar `github:create_issue`
- Maximo 64 caracteres para el nombre completo

---

## Diseno de mensajes de error para agentes

Los mensajes de error de las herramientas son INSTRUCCIONES para el agente sobre
como recuperarse. No son mensajes para humanos.

### Estructura de un error accionable

```json
{
  "error": "ARCHIVO_NO_ENCONTRADO",
  "message": "El archivo src/main.py no existe",
  "recovery": "Verificar la ruta con search_files antes de intentar leer.
               Rutas similares encontradas: src/app/main.py, src/core/main.py"
}
```

### Principios

1. **Incluir sugerencia de recovery**: El agente necesita saber queii hacer despues
2. **Ofrecer alternativas**: Si la accion fallo, sugerir acciones correctivas concretas
3. **No exponer internals**: Stack traces no ayudan al agente; acciones si
4. **Mensajes como reask**: Enviar el error como contexto para que el LLM reformule
   su siguiente intento (patron reask), no repetir el mismo call identico

---

## Integracion con el sistema SWL

### toolBudget en agentes

El campo `toolBudget` en frontmatter define limites por complejidad de tarea:

```yaml
toolBudget:
  simple: 10    # tareas de busqueda, lectura
  standard: 20  # implementacion de 1 slice
  complex: 35   # refactor multi-archivo
```

El diseno de herramientas afecta directamente el presupuesto: herramientas bien
consolidadas permiten hacer mas con menos calls.

### toolsRequeridos en skills

Los skills pueden declarar `toolsRequeridos` en frontmatter para indicar queii
herramientas necesitan. Esto permite al orquestador verificar que el agente
asignado tiene acceso a esas herramientas antes de delegarle la tarea.

### Evaluacion de colecciones

Antes de agregar una herramienta nueva a un agente, verificar:
1. No hay otra herramienta que ya cubra el caso de uso (consolidacion)
2. La description sigue el patron de activacion (no solo describe)
3. Los errores incluyen recovery actions
4. El total de herramientas no supera 20 por agente

---

## Anti-patrones

- **Tool sprawl**: Agregar herramientas sin consolidar las existentes
- **Description generica**: "Hace cosas con archivos" — no activa correctamente
- **Error opaco**: "Error 500" sin sugerencia de recovery
- **Herramienta monolitica**: Una sola herramienta con 30 parametros opcionales
- **Duplicacion cross-agente**: La misma herramienta implementada distinto en 3 agentes
- **Retry ciego**: Reintentar la misma llamada identica ante un error — usar reask

## Cuándo NO cargar

- Se implementa el handler de un PreToolUse o PostToolUse — este skill diseña la interfaz, no el código del hook. Para hooks cargar la regla `hooks.md` o el agente que corresponda.
- Se evalúa el rendimiento histórico de un agente específico (tasa de éxito, latencia) — eso es `evaluacion-agentes`, no diseño de colección.
- El único cambio pendiente es corregir el texto de la descripción de una tool existente sin rediseñar la colección — el costo de carga no compensa.
- Se configuran `permisosRed`, `permisosEscritura` o `nivelRiesgo` en el frontmatter de un agente — esas decisiones caen en `seguridad-agentes` y `estructura-proyecto-claude`.

## Gotchas / Errores comunes no obvios

- **Description escrita para un humano, no para un LLM**: la descripción dice "Ejecuta comandos de sistema operativo" en vez de "Úsala cuando necesites ejecutar comandos de shell, manipular archivos o instalar dependencias". El LLM necesita saber cuándo activar la tool, no solo qué hace. Causa: confundir documentación para desarrolladores con prompt de activación. Solución: comenzar la description con el disparador de uso ("Úsala cuando...", "Llama esto cuando...") y mencionar los casos de uso concretos que activan la herramienta.
- **Consolidación que rompe el límite de parámetros**: al consolidar tres tools en una, el parámetro `accion` acepta 15 valores posibles y el LLM los confunde. Causa: consolidar sin rediseñar la interfaz — la herramienta resultante hereda toda la complejidad de las tres. Solución: verificar después de consolidar que la interfaz resultante tiene ≤6 parámetros y ≤5 valores por enum; si no cabe, la consolidación está sobre-agrupando.
- **Error `recovery` genérico ("intenta de nuevo")**: el agente reintenta la misma llamada idéntica y falla de nuevo. Causa: el campo `recovery` dice "Reintenta más tarde" sin indicar qué debe cambiar. Solución: el `recovery` debe describir la acción correctiva específica ("Verificar que el archivo existe antes de llamar", "Reducir el campo `limit` a menos de 100").
- **Naming MCP sin prefijo de servidor**: la tool `buscar_documentos` de un MCP server colisiona con otra tool local del mismo nombre. Causa: no seguir el formato `ServidorMCP:nombre_tool`. Solución: en MCP servers siempre usar `NombreServidor:accion_sustantivo`; el `:` no es opcional aunque el servidor solo tenga una tool.
- **toolBudget `complex: 35` ignorado porque el agente no lo valida**: el orquestador asigna una tarea simple a un agente que usó 42 tool calls. Causa: `toolBudget` solo es efectivo si el hook de validación o el agente lo respeta activamente; declararlo en frontmatter sin lógica que lo cumpla no tiene efecto. Solución: verificar que el agente o el hook de control de presupuesto lee el campo `toolBudget` del frontmatter antes de asumir que el límite se aplicará automáticamente.

- **Parser YAML inline zero-deps no maneja CRLF / comentarios / comillas** [CONFIRMADO x2]: hooks que parsean frontmatter de Markdown con regex inline (`/^---\n([\s\S]+?)\n---/`) fallan silenciosamente en Windows con `autocrlf=true`. Caso 2026-04-20: `auditar-skills-gaps.js` reportaba 133/143 falsos positivos. Caso 2026-05-18: `validar-intent-spec.js` no detectaba ningún agente, exit 0 silent sin emitir nudges. Tres reglas obligatorias para parsers YAML inline en hooks/scripts SWL:
  1. **Normalizar line endings**: `contenido = contenido.replace(/\r\n/g, '\n').replace(/\r/g, '\n')` ANTES del regex.
  2. **Strip comentarios inline**: `nivelRiesgo: ALTO  # ejemplo` → extraer `"ALTO"`, no `"ALTO  # ejemplo"`. Helper `limpiarValorYaml(crudo)` que aplica `crudo.match(/^(.*?)(?:\s+#.*)?$/)[1]`.
  3. **Strip comillas wrapping**: `nivelRiesgo: "ALTO"` → extraer `"ALTO"`, no `'"ALTO"'`. Helper aplica `slice(1,-1)` si empieza y termina con `"` o `'`.

  Considerar centralizar `limpiarValorYaml()` en `hooks/lib/yaml-mini.js` para reutilización. Causa: hookear los 3 detalles uno por uno cuando aparecen bugs en producción es costoso; aplicar las tres reglas desde el inicio del parser inline.

- **Hook validador no-funcional acumula bugs latentes silenciosamente**: cuando un hook PostToolUse warn-only (`blocking: false`) deja de funcionar por un bug interno (regex roto, parser incompleto, ruta excluida que matchea por error), no hay diferencia observable entre "hook OK, nada que reportar" y "hook roto, ningún reporte posible". Defensa en profundidad rota silenciosamente. Caso: F2 de PR #39 refactorizó 8 agentes ALTO bajo nueva regla obligatoria; 5 omitieron `maxTurnos`, hook debía emitirlos como `intent-spec-incomplete`, pero estaba roto por CRLF. Las 5 omisiones persistieron en main sin alarma.

  Tres mitigaciones obligatorias al crear un hook nuevo de validación:
  1. **Smoke test end-to-end tras creación**: alimentar input que debería emitir nudge → verificar que `nudges.jsonl` contiene la entrada esperada (no solo `exit 0`).
  2. **Validador 1-shot tras refactor masivo**: si N componentes se refactorizan bajo nueva regla obligatoria, ejecutar el validador 1-shot contra cada uno antes de declarar completo.
  3. **Canary mode opcional**: emitir 1 nudge inicial "hook activo, monitoreando" la primera vez que se ejecuta tras instalación/actualización, para confirmar que el hook corre en la plataforma del usuario.

- **Smoke tests de hooks JSON-in en Windows con `echo` shell pierden escapes**: al debuguear hooks que reciben JSON en stdin, NUNCA construir el JSON con `echo` o heredoc desde Git Bash. Caso 2026-05-18: `echo '{"file_path":"D:\\Python\\swl-ses\\..."}'` producía JSON con `D:Python...` (sin backslashes) — los `\\` se comían en shell expansion. El hook recibía path inválido, no encontraba archivo, exit 0 silent. Tomó 3 intentos identificar que el problema era el shell, no el hook. **Patrón correcto**: escribir el JSON con un script Node standalone (`require('fs').writeFileSync('input.json', JSON.stringify({...}))`) y luego `node hook.js < input.json`. JSON correctamente escapado garantizado.
