Formato de habilidades
Una habilidad es conocimiento reutilizable que un agente carga cuando lo necesita: una carpeta con un archivo SKILL.md y recursos de texto opcionales, en el formato abierto Agent Skills. Esta página es para quien escribe, importa o revisa habilidades. Como es texto de prompt más una herramienta del gateway, funciona igual con cualquier proveedor de modelos.
En esta página
- Qué es un paquete de habilidad
- Frontmatter de SKILL.md
- Ejemplo completo
- Límites del paquete
- Habilidades incluidas de serie
- Ciclo de vida y revisión
- Escaneo, importación y exportación
- Rutas de la API de habilidades
- Asignación a agentes
- Cómo llegan las habilidades al modelo
- Límites y limpieza del texto cargado
Qué es un paquete de habilidad#
Un paquete es una carpeta cuyo único archivo obligatorio es SKILL.md: un bloque de frontmatter YAML seguido de instrucciones en markdown. Puede incluir archivos de apoyo, como plantillas, ejemplos, documentos de referencia o scripts, siempre como texto.
Cada versión guarda sus archivos en el Drive de la organización, en /Shared/Skills/<nombre>/v<n>/, y la base de datos guarda el manifiesto: ruta, tamaño y sha256 de cada archivo. Las versiones son inmutables; restaurar una versión antigua crea una versión nueva con el mismo contenido.
client-email/
├── SKILL.md
└── examples/
└── follow-up-example.md
Frontmatter de SKILL.md#
SKILL.md debe ser UTF-8 válido, empezar con una línea --- y cerrar el bloque con otra. Las instrucciones que siguen al frontmatter no pueden estar vacías.
El analizador entiende un subconjunto pequeño de YAML, a propósito:
- Escalares, cadenas entre comillas y bloques con
>o|. - Listas en línea o en bloque.
- Un único nivel de mapa anidado, solo para
metadata. - Rechaza anclas, alias, etiquetas, mapas en línea y tabuladores en la sangría.
| Campo | Obligatorio | Regla o límite |
|---|---|---|
name | Sí | Patrón ^[a-z0-9-]{1,64}$. Único por organización e inmutable una vez creado. |
description | Sí | Hasta 1024 caracteres. Es lo que lee el agente para decidir si usa la habilidad: di qué hace y cuándo usarla. |
license | No | Texto libre. |
compatibility | No | Texto libre; se conserva al exportar. |
allowed-tools | No | Hasta 20 entradas. Es informativo: nunca concede herramientas. |
metadata | No | Mapa de clave a texto, hasta 30 entradas (por ejemplo category). |
Nota
Otras claves escalares de primer nivel se conservan al importar y exportar (hasta 20 claves y 300 bytes por valor), así que un viaje de ida y vuelta no pierde datos. El editor de la app no muestra compatibility ni esas claves extra: si guardas desde el editor, se pierden.
Ejemplo completo#
Este es el SKILL.md de la habilidad client-email en inglés, tal como se incluye en el backend. El nombre usa minúsculas y guiones, la descripción dice qué hace y cuándo usarla, y metadata lleva la categoría y la marca de habilidad de serie.
---
name: client-email
description: "Write a clear email to a client: subject, brief context, a concrete request or answer and the next step. Use it for replies, follow-ups, friendly collections and announcements."
metadata:
category: communication
builtin: "true"
---
# Client email
## When to use it
To write replies, follow-ups or notices to clients.
## Steps
1. Identify the goal in one sentence: inform, ask, confirm, collect or apologize.
2. Specific subject (at most 8 words) with the topic and, if relevant, the date or reference.
3. First paragraph: the answer or request. Then the minimum context.
4. Close with a single next step, who does it and by when.
5. Adjust the tone: warm and professional; in complaints acknowledge the problem first; in collections be firm and kind.
## Quality criteria
- Under 150 words unless more is needed.
- No figure, date or commitment that is not in the task data.
- Check names, amounts and attachments mentioned.
## Limits
Leave the email as a draft; sending it is decided by a person or by the organization policy.
Límites del paquete#
Estos topes se validan al crear, editar e importar. Una violación devuelve un código de error estable, por ejemplo file_too_large, too_many_files, extension_not_allowed o zip_bomb.
| Límite | Valor |
|---|---|
| Archivo subido al importar | 4 MB |
| Tamaño total de una versión | 2 MB |
| Tamaño de un archivo | 512 KB |
Archivos por habilidad (incluye SKILL.md) | 40 |
| Entradas revisadas de un zip | 300 |
| Rutas | Hasta 4 niveles (el nombre del archivo cuenta) y 160 caracteres. Cada segmento empieza por letra o dígito y usa A-Z, a-z, 0-9, ., _ o -, hasta 64 caracteres. |
| Extensiones admitidas | md, txt, csv, json, yaml, yml, py, js, sh (solo texto UTF-8, sin bytes NUL) |
| Razón de compresión de una entrada de zip | Hasta 100 a 1 (se comprueba en entradas de 64 KB o más) |
Habilidades incluidas de serie#
El backend trae un catálogo de habilidades iniciales embebido en el binario, en español y en inglés, con el mismo formato que una importación. Hoy son 55 por idioma, entre ellas bank-reconciliation, b2b-proposal, service-contract-review, month-end-close, client-email y project-plan.
La primera vez que una organización abre la biblioteca, se crean activas en su idioma. Si la organización ya tiene alguna habilidad, aunque esté borrada, no se crea ninguna, y las de serie que se borraron no vuelven. Las plantillas de rol declaran default_skills (solo nombres) y los agentes de ese rol las reciben sin necesidad de una asignación.
backend/internal/skills/builtin/
├── es/<name>/SKILL.md
└── en/<name>/SKILL.md
Ciclo de vida y revisión#
Una habilidad está en uno de cuatro estados: draft, in_review, active o disabled. Los miembros (permiso skills:write) crean borradores, editan, importan y restauran versiones. Los administradores (permiso skills:review) aprueban, rechazan, desactivan y borran.
- Una importación entra siempre en
in_review. - Si un miembro edita una habilidad activa, la versión nueva queda en
in_reviewy los agentes siguen usando la aprobada. Si la edita un administrador, la edición cuenta como revisión y queda activa. - La revisión indica qué versión leyó el revisor: si ya no es la actual, falla con
stale_review. Antes de activar se vuelven a comprobar los hashes de los archivos. - Un rechazo deja una nota y devuelve la habilidad a
draft, o la deja activa con la versión aprobada anterior si existe. - Borrar es lógico y quita las asignaciones. Crear otra habilidad con el mismo nombre la recupera con una versión nueva.
create (member) → draft ──submit──▶ in_review ──approve (admin)──▶ active
import (member) → in_review (always)
reject → draft, or stays active with the previous approved version
active ──disable (admin)──▶ disabled · delete (admin, soft)
Escaneo, importación y exportación#
Al guardar cada versión se escanea el paquete y se guardan advertencias para el revisor. El escaneo informa, no decide: el revisor lo ve todo antes de aprobar.
injection: el puntaje de inyección de algún archivo supera el umbral.script: el paquete trae archivos ejecutables como texto (py,js,sh).allowed_tools: el frontmatter declaraallowed-tools.import_note: la importación ajustó algo, por ejemplo omitió un archivo vacío.
- Importa un
.zipo unSKILL.mdsuelto conPOST /api/v1/skills/import(campo multipartfile). - La validación es estricta: rechaza rutas absolutas o con
.., barras invertidas, letras de unidad, enlaces simbólicos y archivos especiales, entradas cifradas, duplicados que solo difieren en mayúsculas y bombas de compresión. Quita una carpeta envoltorio única e ignora__MACOSX,.DS_StoreyThumbs.db. - Un administrador revisa la versión y la aprueba o la rechaza.
- Para sacarla,
GET /api/v1/skills/{id}/exportdevuelve un zip determinista con el diseño estándar (<nombre>/SKILL.mdmás recursos, sin bits de ejecución), o soloSKILL.mdcon?format=md.
Nota
La importación desde una URL no existe a propósito: exigiría un descargador protegido contra SSRF.
Rutas de la API de habilidades#
Todas las rutas van bajo /api/v1, con autenticación y aislamiento por organización. El cuerpo de una revisión lleva la decisión (approve o reject), la versión revisada y una nota.
POST /api/v1/skills/{id}/review
Content-Type: application/json
{ "decision": "approve", "version": 3, "note": "Checked tone and limits" }
| Ruta (bajo /api/v1) | Permiso | Qué hace |
|---|---|---|
GET /skills | skills:read | Lista las habilidades de la organización. |
POST /skills | skills:write | Crea un borrador desde el editor. |
POST /skills/import | skills:write | Importa un .zip o un SKILL.md; entra en in_review. |
PUT /skills/{id} | skills:write | Guarda una versión nueva. |
POST /skills/{id}/versions/{n}/restore | skills:write | Crea una versión nueva con el contenido de la versión n. |
POST /skills/{id}/submit | skills:write | Pasa de draft a in_review. |
POST /skills/{id}/review | skills:review | Aprueba o rechaza una versión concreta. |
POST /skills/{id}/disable | skills:review | Deja de servir la habilidad a los agentes. |
GET /skills/{id}/export | skills:read | Exporta el zip o, con ?format=md, solo SKILL.md. |
Asignación a agentes#
Una asignación vincula una habilidad con un agente mediante PUT y DELETE sobre /api/v1/agents/{id}/skills/{skillId}, con el permiso agents:write. Además están los valores por defecto de rol: los nombres de default_skills en la plantilla de rol llegan a todos los agentes de ese rol sin asignación explícita.
Un agente solo recibe una habilidad si está asignada (o es predeterminada de su rol), no está borrada ni desactivada y tiene una versión aprobada. Mientras una edición espera revisión, se sirve la versión aprobada. En cualquier otro caso la carga se deniega con skill_not_available.
Cómo llegan las habilidades al modelo#
La divulgación es progresiva, en dos pasos. En cada ejecución, el backend añade a la solicitud solo el nombre y la descripción de las habilidades que el agente puede usar, con topes: como máximo 12 habilidades, 240 caracteres por descripción y 3000 bytes en total. El runtime las presenta en el prompt con una regla explícita: una habilidad guía cómo trabajar y nunca concede herramientas, conexiones, permisos, autonomía ni aprobaciones.
Si una habilidad aplica, el agente la pide con una solicitud de herramienta. El Tool Gateway la sirve como herramienta nativa de lectura, sujeta al kill switch, la pausa y la auditoría, y responde con el cuerpo de la versión aprobada sin frontmatter más la lista de archivos. Con file devuelve un único recurso.
{ "tool": "skill", "action": "load", "args": { "name": "client-email", "file": "examples/follow-up-example.md" } }
Límites y limpieza del texto cargado#
Una vez cargada, la habilidad entra en el contexto de la tarea con varias salvaguardas:
- El texto viaja por su propio canal (
loaded_skills) como configuración de confianza de la organización, entre delimitadores propios, porque una persona aprobó esa versión exacta. - Aun así se limpia (caracteres invisibles, credenciales, delimitadores falsificados) y se puntúa contra inyección.
- Se acota en el backend (24 000 caracteres por respuesta, 4 cargas por tarea) y otra vez en el runtime (3 habilidades, 12 000 caracteres cada una, 20 000 en total).
- Los scripts son texto inerte: ejecutarlos exige la herramienta de código, con aprobación humana.