En los artículos anteriores de esta serie expliqué cómo se organizan los WebPerf Snippets como Skills y cómo los scripts devuelven JSON estructurado para minimizar el trabajo del agente. Queda un tercer nivel de optimización: cuánto contexto consume cada Skill al activarse.
El problema no es que los scripts sean grandes. Es que el SKILL.md cargaba todo el conocimiento disponible en el momento de activación, aunque la mayor parte no fuera necesaria para decidir qué script ejecutar.
El sistema de progressive disclosure de Anthropic
La guía oficial de Skills de Anthropic (The Complete Guide to Building Skills for Claude) define tres niveles de contenido con un principio claro: cargar solo lo necesario en cada momento, y acceder al detalle únicamente cuando se necesita.
L1 — Frontmatter YAML (siempre en contexto)
---
name: webperf-core-web-vitals
description: Intelligent Core Web Vitals analysis...
---
El frontmatter forma parte del system prompt permanente. Está en contexto en cada conversación, independientemente de qué Skill esté activa. Por eso existe un límite de 1.024 caracteres en la descripción: ese contenido se paga siempre.
L2 — Cuerpo del SKILL.md (cargado al activar la Skill)
Se carga cuando el agente determina que la Skill es relevante. Debe contener lo estrictamente necesario para que el agente decida qué script ejecutar: lista de scripts disponibles, flujos de trabajo y árboles de decisión. Cada kilobyte aquí se consume en cada sesión donde la Skill se activa.
L3 — references/, scripts/, assets/ (cargados bajo demanda)
Documentación detallada, descripciones de cada snippet, tablas de umbrales, esquemas de resultados. Se leen únicamente cuando el agente los necesita para interpretar un resultado concreto. Hasta ese momento, el coste es cero.
El problema: todo era L2
El generador de Skills, scripts/generate-skills.js, añadía al cuerpo del SKILL.md cuatro bloques que podían haberse quedado en L3:
Tabla de snippets con descripciones truncadas
| LCP Trail | Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-c |
El recorte a 100 caracteres no aportaba valor real. Ni era suficiente para entender el snippet, ni dejaba al agente decidir cuándo consultarlo.
Bloque de instrucciones de ejecución duplicado cinco veces
Las mismas seis líneas aparecían de forma idéntica en los cinco Skills de categoría, siendo ya cubiertas por el meta-Skill webperf:
1. mcp__chrome-devtools__navigate_page → navigate to target URL
2. mcp__chrome-devtools__evaluate_script → run snippet code
3. mcp__chrome-devtools__get_console_message → capture console output
SCHEMA.md inaccesible
El archivo .claude/skills/SCHEMA.md (19 KB) documenta el esquema completo de valores de retorno JSON para los 47 scripts. Existía pero ningún Skill lo referenciaba. Imposible que el agente lo consultara.
La solución: mover el detalle a L3
Todos los cambios se han realizado en un único archivo: scripts/generate-skills.js del repositorio webperf-snippets. Los Skills son artefactos generados y no se editan directamente.
Crear references/snippets.md con el detalle completo
En lugar de añadir al cuerpo del SKILL.md una sección por snippet (con descripción y tabla de umbrales), se escribe un archivo separado en L3:
const snippetLines = [];
for (const meta of metas) {
snippetLines.push(`---`);
snippetLines.push(`## ${meta.title}`);
if (meta.description) {
snippetLines.push("");
snippetLines.push(meta.description);
}
snippetLines.push("");
snippetLines.push(`**Script:** \`scripts/${meta.basename}.js\``);
if (meta.thresholds) {
snippetLines.push("");
snippetLines.push("**Thresholds:**");
snippetLines.push("");
snippetLines.push(meta.thresholds);
}
}
fs.writeFileSync(
path.join(refsDir, "snippets.md"),
snippetLines.join("\n") + "\n"
);
Sustituir la tabla truncada por una lista compacta
❌ Antes:
## Available Snippets
| Snippet | Description | File |
| --------- | ---------------------------------------------------------------------------------------------------- | -------------------- |
| LCP Trail | Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-c | scripts/LCP-Trail.js |
✅ Después:
## Scripts
- `scripts/LCP-Trail.js` — LCP Trail
- `scripts/LCP.js` — Largest Contentful Paint (LCP)
Descriptions and thresholds: `references/snippets.md`
Copiar SCHEMA.md a references/schema.md
const schemaSrc = path.join(CLAUDE_SKILLS_DIR, "SCHEMA.md");
if (fs.existsSync(schemaSrc)) {
fs.copyFileSync(schemaSrc, path.join(refsDir, "schema.md"));
}
Con esto, el agente puede consultar el esquema completo cuando recibe un resultado inesperado, sin que ese coste de 19 KB se pague en cada sesión.
Eliminar las instrucciones de ejecución duplicadas
Se eliminó el bloque repetido de los cinco Skills de categoría y se sustituyó por una línea de referencia al final:
> Execute via `mcp__chrome-devtools__evaluate_script` → read with `mcp__chrome-devtools__get_console_message`.
Añadir sección ## References al final del SKILL.md
## References
- `references/snippets.md` — Descriptions and thresholds for each script
- `references/schema.md` — Return value schema for interpreting script output
La estructura resultante
skills/webperf-core-web-vitals/
SKILL.md ← L2: lista de scripts + workflows
scripts/
CLS.js ← L3: ejecutado cuando se necesita
LCP.js
...
references/
snippets.md ← L3: descripciones y umbrales
schema.md ← L3: esquema de valores de retorno
Resultados
| Skill | Antes | Después | Reducción |
|---|---|---|---|
| webperf-loading | 24.199 B | 11.149 B | −54% |
| webperf-core-web-vitals | 13.890 B | 10.266 B | −26% |
| webperf-interaction | 17.143 B | 12.443 B | −27% |
| webperf-media | 13.273 B | 12.017 B | −9% |
| webperf-resources | 11.700 B | 11.026 B | −6% |
| Total L2 | 82.916 B | 59.612 B | −28% |
Los Skills con menor reducción (webperf-media, webperf-resources) tienen WORKFLOWS.md extensos con árboles de decisión detallados. Ese contenido es deliberadamente L2: el agente lo necesita en el momento de decidir qué script ejecutar.
En una auditoría completa con tres Skills activas simultáneamente, el L2 pasa de ~55 KB a ~34 KB. Los ~18 KB de references/snippets.md y los 19 KB de references/schema.md quedan disponibles bajo demanda. En el caso típico de una sesión de diagnóstico (ejecutar dos o tres scripts, interpretar resultados directos), nunca se leen.
Conclusión
El sistema de progressive disclosure no cambia lo que el agente puede hacer: todos los snippets siguen disponibles, todas las descripciones siguen accesibles, el schema sigue consultable. Lo que cambia es cuándo se paga el coste de ese conocimiento.
El agente carga lo mínimo para tomar decisiones. El detalle existe, pero solo aparece en contexto cuando es necesario para interpretar un resultado concreto. Para una colección de 47 snippets distribuidos en seis Skills, la diferencia entre cargar todo siempre y cargar solo lo necesario es de más de 20 KB por sesión de análisis completo, y cero bytes de contexto de detalle en el caso habitual.