llms.txt Skills Specification
Draft v0.10 — Especificación para publicar y consumir Agent Skills a través de
llms.txt.
TL;DR — ¿Qué es esto?
Un estándar de dos caras:
- Publisher: cualquier sitio web puede anunciar skills descargables añadiendo una sección
## Skillsa sullms.txt. No requiere servidor, proceso persistente, ni autenticación. - Consumer: cualquier agente puede descubrir esas skills automáticamente consultando
/llms.txtantes de interactuar con un dominio. Una skill de referencia (llms-txt-aware) documenta exactamente cómo hacerlo.
El problema dual
Para los publishers
Hoy, si eres desarrollador de un sitio web y quieres que los agentes de IA sepan cómo interactuar contigo, tus opciones son:
- MCP: necesitas un servidor persistente. Excesivo para un blog en GitHub Pages o una API REST simple.
/.well-known/skills/: solo permite una skill por dominio.- Nada: el agente lee
llms.txtpero no sabe que existe una skill.
Para los consumers (agentes)
Hoy, cuando un usuario dice "usa https://img.automators.work/", el agente:
- No busca automáticamente
/llms.txt. - No descubre que el sitio publica una skill
placeholder. - No sabe que podría delegar la tarea al servicio remoto.
- En su lugar, crea una imagen local con Python/PIL, ignorando la URL por completo.
Este es el execution gap: el sitio publica la skill, pero el runtime no la consume.
La solución (lado publisher)
Añadir una sección ## Skills dentro de llms.txt. Una sola línea de markdown por skill:
## Skills
- [placeholder](https://github.com/MauricioPerera/llms-txt-skills/blob/master/skills/placeholder/SKILL.md): generate SVG placeholder image URLs for UI mockups. <!-- skill: {"version":"1.0.0"} -->
El agente que ya leyó llms.txt ahora sabe que existe una skill y dónde encontrarla. El metadata inline solo lleva version como hint rápido. Para verificación de integridad (sha256) y metadata completa (licencia, costo), el agente consulta /.well-known/agent-skills/index.json si está disponible.
La solución (lado consumer)
Antes de interactuar con cualquier dominio, el agente debe ejecutar este flujo:
1. Extraer el origen de la URL mencionada
2. HEAD /llms.txt (o leer Link header de una request previa)
3. Si 200 OK: leer el archivo COMPLETO (no solo ## Skills)
4. Aplicar constraints, endpoints, parámetros y ejemplos canónicos
5. Si existe ## Skills: listarlas al usuario y pedir opt-in
6. Si el usuario aprueba: descargar SKILL.md y seguir sus instrucciones exactas
7. Cachear por sesión
Implementamos este flujo como skill de referencia: llms-txt-aware.
¿Por qué usar la skill llms-txt-aware?
| Sin la skill | Con la skill |
|---|---|
| Usuario: "Crea imagen verde en img.automators.work" → agente crea PNG local con PIL | Usuario: "Crea imagen verde en img.automators.work" → agente busca /llms.txt → descubre skill placeholder → genera URL correcta /600x50?bg=22c55e |
| Usuario: "Busca teclados en demoshop" → agente abre browser sin saber qué hacer | Usuario: "Busca teclados en demoshop" → agente busca /llms.txt → descubre product-search → sabe exactamente qué endpoint llamar |
| Cada sitio requiere investigación manual | Un solo procedimiento cubre cualquier dominio |
La skill no inventa protocolos: usa lo que el sitio publica. Si el sitio no tiene llms.txt, falla silenciosamente y sigue con herramientas locales.
¿Por qué usar este estándar?
Para publishers (developers)
| Antes | Después |
|---|---|
| "Mi API existe pero los agentes no saben cómo usarla" | "Añadí 3 líneas a mi llms.txt y cualquier agente compatible puede descubrir la skill" |
| "Necesito mantener un servidor MCP" | "No necesito nada, es un sitio estático" |
| "La skill vive en un marketplace externo" | "La skill vive en mi repo, se despliega con mi API" |
| "Solo puedo publicar una skill" | "Puedo publicar tantas como necesite" |
Para consumers (agentes / runtimes)
| Antes | Después |
|---|---|
| Cada sitio requiere código custom o prompting manual | Un solo procedimiento (llms-txt-aware) cubre cualquier dominio |
| URLs en prompts se interpretan como decorativas | URLs en prompts disparan descubrimiento automático de skills |
| No sabemos qué versión de la skill usar | Metadatos inline indican versión; sha256 y licencia en .well-known |
| Sin contexto de cuándo usar la skill | La descripción del item de lista lo dice |
Para los usuarios
| Antes | Después |
|---|---|
| "¿Cómo hago que el agente use esta API?" | El agente detecta automáticamente la skill disponible |
| Instalar skills manualmente desde marketplaces | Skills descubiertas y validadas en el momento |
Comparación con soluciones actuales
| Característica | MCP | A2A | /.well-known/skills/ |
## Skills en llms.txt |
|---|---|---|---|---|
| Requiere servidor corriendo | Sí | Sí | No | No |
| Funciona en sitios estáticos | No | No | Sí | Sí |
| Múltiples skills por dominio | Sí | Sí | No | Sí |
Descubrimiento co-ubicado con llms.txt |
No | No | No | Sí |
| Sin infraestructura extra | No | No | Sí | Sí |
| Complejidad de implementación | Alta | Alta | Baja | Baja |
| Metadata e integridad (sha256, licencia) | N/A | N/A | No | Vía .well-known/agent-skills/index.json |
| Adecuado para | Integraciones complejas y stateful | Agent-to-agent | Sitios con una sola skill | Cualquier sitio estático o API |
Este estándar NO reemplaza MCP ni A2A. Es la capa de descubrimiento para el caso simple. Para metadata e integridad, se complementa con /.well-known/agent-skills/index.json: ## Skills es el puntero de descubrimiento, .well-known es la fuente de verdad de metadatos.
Kit de conformancia (para implementadores de runtimes)
¿Construiste tu propio runtime del estándar? Demostrá conformancia con un comando: el kit levanta un publicador-fixture determinista y valida cada MUST (core + Executable Skills v0.5) manejando tu runtime por MCP stdio, con cita de spec por check.
node conformance/run.mjs --cmd "tu-runtime {origin}"
Ver conformance/. El CI de este repo corre el kit contra el
mcpwasm publicado en cada push — la implementación de referencia demuestra su
conformancia con la misma herramienta que reciben los terceros.
Implementación de referencia
Este repo contiene:
- RFC v0.10: especificación completa del protocolo
- Parser y validador: herramientas de referencia en Python
- Generador/sincronizador: regenera
## Skills, la copia.well-knowny el índice canónico desde el frontmatter de cada skill - Firma y verificación: firma ed25519 de cada skill (autenticidad) y verificador independiente
- JSON Schema: validación estructurada de la salida del parser
- Skills de ejemplo:
placeholderyapi-clientparaimg.automators.work - Skill de consumo:
llms-txt-awarepara que los agentes descubran skills automáticamente - Consumers reales: plugin de Claude Code, MCP server cross-runtime, y un PR nativo a aider — ver estado de adopción
- Benchmark empírico: harness que mide el uso correcto de skills baseline vs discovery — ver evals/
- Tests manuales: resultados contra 3 dominios reales
Estructura del repo
llms-txt-skills/
├── llms.txt # Especificación del API + sección ## Skills
├── README.md # Este archivo
├── .gitignore
├── docs/
│ ├── rfc-skills-in-llms-txt.md # RFC completo (v0.10)
│ ├── adoption.md # Estado de adopción (consumers, trust model, hilos)
│ ├── articulo-propuesta.md # Divulgación
│ └── articulo-linkedin.md # Divulgación
├── scripts/
│ ├── parse_llms_txt_skills.py # Parser de referencia
│ ├── validate.py # Validador de llms.txt y skills
│ ├── generate.py # Generador/sincronizador + firma (--check para CI)
│ ├── verify_signatures.py # Verifica firmas ed25519 del índice
│ ├── skills-manifest.json # Qué skills publica el dominio + config de firma
│ └── deploy-cloudflare-pages.sh # Script de despliegue
├── schema/
│ └── llms-txt-skills.schema.json # Schema JSON para validación
├── skills/
│ ├── placeholder/SKILL.md # Skill de ejemplo: generador de imágenes
│ ├── api-client/SKILL.md # Skill de ejemplo: cliente HTTP
│ └── llms-txt-aware/SKILL.md # Skill de consumo (fuente canónica)
├── integrations/
│ └── mcp/ # MCP server: descubrir/consumir skills en cualquier runtime MCP
├── evals/
│ ├── harness.py # Benchmark baseline vs discovery (adapters LM Studio/Anthropic/CF)
│ ├── scenarios.json # Escenarios del benchmark
│ ├── results.md # Resultados medidos
│ └── README.md # Metodología
├── .claude-plugin/
│ └── marketplace.json # Marketplace de Claude Code
├── plugins/
│ └── llms-txt-aware/ # Plugin instalable (skill generado desde la fuente)
├── tests/
│ └── skill-test-results.md # Resultados de pruebas manuales
├── .well-known/
│ ├── skills/default/SKILL.md # Alias de compatibilidad (generado)
│ └── agent-skills/
│ ├── index.json # Índice canónico: metadata + sha256 + firma (generado)
│ └── signing-key.pub # Clave pública ed25519 del publisher (generado)
└── .github/workflows/
└── validate.yml # CI: valida + sincronización + firmas
Cómo usar la skill llms-txt-aware
Como plugin de Claude Code (recomendado)
Este repo es además un marketplace de Claude Code. Instalá el consumer skill en dos comandos:
/plugin marketplace add MauricioPerera/llms-txt-skills
/plugin install llms-txt-aware@llms-txt-skills
A partir de ahí, Claude Code activa la skill automáticamente cuando vayas a tocar un dominio web, según su description.
Como system prompt
Copiá el contenido de skills/llms-txt-aware/SKILL.md al system prompt de tu agente. La skill define un procedimiento de 6 pasos que el agente debe ejecutar antes de interactuar con cualquier dominio web.
Como skill local de Codex
En Codex (OpenAI), las skills se cargan desde ~/.codex/skills/. Copiá el directorio llms-txt-aware/ ahí y activala en la sesión con $llms-txt-aware.
Como regla de Ollama / LM Studio
Inyectá el contenido del SKILL.md como parte del system prompt del modelo. Funciona con cualquier modelo local que respete instrucciones de system prompt.
Como tool en un runtime custom
Convertí los 6 pasos del procedimiento en una función:
def discover_skills(domain: str) -> list[Skill]:
"""Busca llms.txt en el dominio y devuelve skills disponibles."""
llms = fetch(f"{domain}/llms.txt")
return parse_skills_section(llms)
El RFC §5.1 documenta 4 mecanismos de descubrimiento (HTTP Link header, DNS TXT, HTML meta tag, convention probe).
Cómo adoptar el estándar en tu dominio (3 pasos)
El camino más rápido: la plantilla de GitHub. Un publicador funcional desde el minuto cero — bundle de conocimiento de ejemplo, skills generadas y CI de validación incluidos. Click en Use this template, reemplazá
knowledge/, corré dos comandos. Los 3 pasos de abajo son el mismo flujo, hecho a mano.
El caso mínimo (L0) es una sola línea. Agregar la sección
## Skillsa tullms.txt(Paso 1) + unSKILL.md(Paso 2) ya te hace descubrible — nada más es obligatorio. Elsha256, la firma,tool.jseindex.jsonson endurecimiento opcional que el generador agrega por vos (Paso 3); subís de nivel cuando tu modelo de riesgo lo pida. La escalera completa L0→L3 está endocs/adoption.md.
Paso 1: Crea tu llms.txt
# Mi API
> Descripción compacta de lo que hace tu sitio.
## Endpoint
`GET https://ejemplo.com/api/recurso`
## Skills
- [mi-skill](https://github.com/MauricioPerera/llms-txt-skills/blob/master/skills/mi-skill/SKILL.md): descripción de cuándo usar esta skill. <!-- skill: {"version":"1.0.0"} -->
Paso 2: Crea tu SKILL.md
---
name: mi-skill
description: Qué hace esta skill y cuándo usarla.
version: 1.0.0
license: MIT
homepage: https://ejemplo.com
---
# mi-skill
Instrucciones detalladas para el agente.
Paso 3: Despliega
Sube ambos archivos a cualquier host estático. No necesitas servidor, proceso persistente, ni autenticación.
Mantener todo sincronizado (recomendado)
En vez de editar a mano la sección ## Skills, calcular el sha256 y copiar el .well-known, dejá que la herramienta haga el resto. Sin clonar nada ni tener Python, con el CLI (@rckflr/llms-skills):
npx @rckflr/llms-skills init mi-skill # scaffold del SKILL.md (+ tool.js con --tool) y del manifest
npx @rckflr/llms-skills publish # escribe ## Skills en llms.txt + index.json (+ firma si hay clave)
npx @rckflr/llms-skills publish --check # falla si hay drift (para CI)
Dentro de este repo, el generador Python de referencia hace exactamente lo mismo (salida byte-idéntica, verificada por cli/test.mjs):
python scripts/generate.py # regenera ## Skills, .well-known/skills/default y .well-known/agent-skills/index.json
python scripts/generate.py --check # falla si algo quedó desincronizado (lo usa CI)
Ambos toman name, description, version y license del frontmatter de cada SKILL.md, calculan el sha256 (CRLF→LF) y escriben las salidas de forma determinista. El step --check en CI garantiza que nunca haya drift entre el SKILL.md y lo publicado.
Para CI hay una GitHub Action reutilizable (definida en la raíz de este repo, auto-testeada por el propio CI): valida el llms.txt + skills y, si hay manifest, corre publish --check:
- uses: MauricioPerera/llms-txt-skills@master
Firmar las skills (autenticidad)
Si el manifest declara signing, el generador firma cada SKILL.md con ed25519 y agrega signing_key + signature al index.json (y escribe signing-key.pub). La firma es determinista (RFC 8032), así que --check sigue siendo idempotente.
python scripts/verify_signatures.py # verifica las firmas contra la clave pública del publisher
En producción, el publisher usa "signing": {"private_key_path": "..."} con una clave offline que nunca se commitea. El repo de ejemplo usa "demo_seed" (clave de demo derivada de un seed público, reproducible) — no usar en producción. Ver el modelo de confianza completo en el RFC §4.6.
Ejemplos reales de uso
Ejemplo 1: API de imágenes placeholder
https://img.automators.work/llms.txt → descubre la skill "placeholder"
→ el agente genera URLs correctas
Ejemplo 2: Blog con guía de estilo
https://blog.ejemplo.com/llms.txt → descubre la skill "content-style"
→ el agente sigue la guía al escribir
Ejemplo 3: API con lectura y escritura separadas
https://api.ejemplo.com/llms.txt → descubre "api-read" y "api-write"
→ el usuario elige cuál usar
Ejemplo 4: Tienda online con carrito y checkout
https://demoshop-88e.pages.dev/llms.txt → descubre 3 skills:
- product-search
- cart-add
- checkout-complete
→ el agente busca, agrega y compra
Ver el flujo completo documentado en la sección DemoShop.
DemoShop — flujo completo probado
DemoShop es una tienda demo desplegada en Cloudflare Pages que implementa el estándar ## Skills con 3 skills funcionales. Es un caso de uso real del Pattern A — API wrapping del RFC.
Skills publicadas
| Skill | Cuándo usar | Endpoint principal |
|---|---|---|
| product-search | Buscar productos por nombre, categoría o descripción | GET /api/products?q=... |
| cart-add | Agregar productos al carrito | POST /api/cart |
| checkout-complete | Completar un pedido con datos del cliente | POST /api/checkout |
Flujo simulado de compra
PASO 1: Descubrimiento
GET https://demoshop-88e.pages.dev/llms.txt
→ Parsea ## Skills, encuentra 3 skills disponibles
→ Pide opt-in al usuario para activarlas
PASO 2: Búsqueda
GET https://demoshop-88e.pages.dev/api/products?q=bluetooth
→ {"products": [{"id":1, "name":"Auriculares Bluetooth", "price":29.99}]}
→ Agente elige producto ID 1
PASO 3: Carrito
POST https://demoshop-88e.pages.dev/api/cart
Body: {"product_id": 1, "quantity": 2}
→ {"success": true, "message": "Agregado 2 x producto #1 al carrito"}
PASO 4: Checkout
POST https://demoshop-88e.pages.dev/api/checkout
Body: {"customer_name":"Ana Lopez","email":"[email protected]","address":"Av. Revolucion 456, CDMX"}
→ {"success": true, "order_id": "ORD-MPCWLKHZ", "status": "confirmado"}
Código fuente del demo
llms-shop-demo/
├── index.html # Frontend
├── api/products.json # Catálogo (8 productos)
├── functions/ # Cloudflare Pages Functions
│ ├── api/products/index.js
│ ├── api/products/[id].js
│ ├── api/cart.js
│ └── api/checkout.js
├── llms.txt # Espec API + ## Skills
└── skills/
├── product-search/SKILL.md
├── cart-add/SKILL.md
└── checkout-complete/SKILL.md
Lecciones del demo
- Sin autenticación: el flujo completo funciona stateless, sin sesiones ni tokens.
- Skills atómicas: cada operación tiene su propia skill. El agente puede usarlas individualmente o en secuencia.
- Sin servidor MCP: todo corre como archivos estáticos + functions serverless.
Limitaciones conocidas
El parser y validador de este repo son herramientas de referencia, no producción lista.
-
Parser YAML frontmatter: maneja solo pares
key: valueplanos. No soporta listas, objetos anidados, ni multi-line strings (|,>). -
Regex de URLs: soporta un nivel de paréntesis balanceados, pero no múltiples niveles.
-
Sub-headings dentro de
## Skills: un heading### ...dentro de la sección se adjunta a la descripción del item anterior. El RFC asume una lista plana. -
Verificación
sha256: el validador compara hash contra contenido real para paths locales (con normalización CRLF→LF). Para URLs remotas, la verificación sigue siendo responsabilidad del agente runtime. -
Modelo de confianza: el
sha256da integridad (no cambió en tránsito) pero no autenticidad — lo asevera el mismo documento que apunta a la skill. Para autenticidad el repo implementa firma ed25519 sobre una clave offline + key-pinning del lado del agente (RFC §4.6). Esto defiende contra un servidor comprometido sin la clave privada, pero no contra el robo de la clave offline; para provenance ligado a identidad, el RFC recomienda firma keyless con transparency log (Sigstore), que requiere red para verificar.
Licencia
MIT — este estándar y su implementación de referencia son de dominio público para su adopción.
No comments yet
Be the first to share your take.