Autohostear agent skills en tu sitio web

Tu sitio puede alojar skills instalables para IA — no hace falta GitHub. Lo monté con Next.js en una app en producción; lo más delicado fue alinear el redirect a www para que npx skills add funcione, y dar al agente contexto persistente del producto en lugar de respuestas genéricas.

Contexto

Si ya publicaste llms.txt en tu sitio, diste a los agentes un mapa de tu documentación. Los agent skills van un paso más allá: paquetes instalables que un developer puede agregar a Cursor, Claude Code, Copilot u otros editores con un solo comando:

bash
npx skills add https://www.tusitio.com

El CLI descarga un manifiesto desde tu dominio, lee cada SKILL.md y lo deja listo en el editor del usuario. No hace falta publicar en GitHub ni en skills.sh — tu sitio web es el registry.

Lo implementé en una app Next.js en producción, pero el mecanismo es agnóstico: cualquier host que sirva archivos estáticos en /.well-known/agent-skills/ funciona (Vite, Astro, Nginx, S3 + CloudFront, etc.). Next.js solo simplifica el deploy porque public/ se expone tal cual.

Por qué puede importar

No es obligatorio para todo sitio. Pero si vendes un producto, una API o una plataforma donde developers integran antes de registrarse, esto empieza a pesar.

Hoy mucha gente no abre la documentación en el browser: le pregunta al agente del editor. Si tu producto no está instalado como skill, el modelo responde con conocimiento genérico — mezcla versiones, inventa endpoints o cita páginas viejas aunque tu doc esté perfecta online. Lo vi pasar con integraciones concretas antes de tener un skill público.

Autohostear un skill en tu dominio te da cosas que un repo en GitHub o un link suelto no cubren igual:

  • Onboarding en un comando — quien evalúa tu producto no tiene que buscar qué leer primero; instala y el editor ya sabe por dónde empezar.
  • Contexto persistentellms.txt orienta una sesión de navegación; un skill queda en el editor y acompaña cada conversación de código.
  • Tú controlas la versión — actualizas el SKILL.md, despliegas, y quien reinstala o actualiza recibe la guía nueva. No dependes de que skills.sh indexe tu repo.
  • Canal de distribución propio — el dominio que ya usas para marketing y docs también sirve el paquete instalable. Menos fricción entre “vi tu landing” y “integré bien”.
  • Menos respuestas inventadas — un skill bien escrito acota stack, auth, límites y flujos reales. El agente deja de improvisar tanto.

Para un blog personal o un portfolio puede ser overkill. Para un SaaS, un SDK o documentación de integración que quieres que los agentes citén bien, sí vale la pena considerarlo — y el costo técnico es bajo si ya tienes un sitio estático o Next.js.

Qué es distinto de llms.txt

  • `llms.txt` (/llms.txt) — Índice curado de links para que un agente sepa qué páginas leer.
  • Agent skills (/.well-known/agent-skills/ o /.well-known/skills/) — Paquetes instalables con workflows y contexto embebido.

Son complementarios. llms.txt orienta la navegación; un skill se instala en el editor y queda disponible en cada sesión. En la práctica uso los dos.

Cómo funciona el discovery

Cuando alguien corre npx skills add https://www.tusitio.com, el CLI:

  • Pide el manifiesto en /.well-known/agent-skills/index.json o /.well-known/skills/index.json (el CLI prueba ambos)
  • Lee la lista de skills (name, description, files)
  • Descarga cada SKILL.md (y archivos extra si los declaras)
  • Los instala en la carpeta de skills del editor

Tu trabajo como maintainer: servir ese JSON y esos Markdown de forma estable, con URLs absolutas coherentes y sin sorpresas de redirect.

El problema que más tiempo me costó: www vs apex

El fallo no fue Next.js ni el formato del JSON. Fue el dominio canónico.

Tenía el apex (tusitio.com) redirigiendo a www.tusitio.com en Vercel/DNS. En el hero del landing publiqué:

bash
npx skills add tusitio.com

Luego https://tusitio.com. El CLI seguía fallando o comportándose raro porque:

  • El primer fetch iba al apex
  • Vercel respondía con 301/308 hacia www
  • Algunos clientes no siguen bien la cadena, cambian el host base, o resuelven paths relativos contra el host equivocado
  • El manifiesto existía en ambos lados en teoría, pero el install command debe apuntar al host que responde 200 directo, sin hop

La solución: elegir un solo host canónico (https://www.tusitio.com) y usarlo en todas partes:

  • Comando de instalación en la web
  • WEBSITE_URL / NEXT_PUBLIC_WEBSITE_URL en el código
  • Links en llms.txt, sitemap, Open Graph, JSON-LD
  • Documentación y README

No mezcles tusitio.com en un sitio y www.tusitio.com en otro.

Cómo verificar antes de anunciar el comando:

bash
# Debe responder 200 sin depender de -L (sin redirect)
curl -sI https://www.tusitio.com/.well-known/agent-skills/index.json

# Si usas apex, mira la cadena completa
curl -sI https://tusitio.com/.well-known/agent-skills/index.json

# El cuerpo del manifiesto
curl -s https://www.tusitio.com/.well-known/agent-skills/index.json | jq .

Si el primer curl al apex devuelve 301/308 y el de www devuelve 200, tu URL pública para npx skills add debe ser www.

Opcional pero recomendable: forzar el redirect en un solo lugar (Vercel → Domains → redirect apex → www, o regla en next.config.ts) y documentar cuál es el host oficial.

Estructura de archivos

En la raíz del proyecto (ejemplo Next.js):

text
public/
└── .well-known/
    └── agent-skills/
        ├── index.json
        ├── getting-started/
        │   └── SKILL.md
        ├── api-reference/
        │   └── SKILL.md
        └── otro-skill/
            └── SKILL.md

En Astro/Vite/CRA es igual: carpeta public/ (o static/) → se sirve en la raíz del dominio.

Importante: los skills públicos para instalación viven aquí. Los skills de desarrollo interno pueden seguir en .agents/skills/ (ver nota 006). Son dos capas distintas; no hace falta publicar todo lo que usas en local.

Pasos para implementarlo

Antes de empezar: un sitio ya desplegado, acceso al repo, y claro cuál es tu dominio canónico (con o sin www).

1. Crear carpetas y manifiesto

bash
mkdir -p public/.well-known/agent-skills/mi-primer-skill

Crea public/.well-known/agent-skills/index.json:

json
{
  "skills": [
    {
      "name": "mi-primer-skill",
      "description": "Guía de onboarding de mi producto. Úsalo cuando un dev empiece desde cero.",
      "files": ["SKILL.md"]
    }
  ]
}
  • name debe coincidir con el nombre de la carpeta
  • files lista los archivos dentro de esa carpeta (hoy casi siempre solo SKILL.md)

2. Escribir el SKILL.md con frontmatter

Crea public/.well-known/agent-skills/mi-primer-skill/SKILL.md:

markdown
---
name: mi-primer-skill
description: "Guía de onboarding de mi producto. Úsalo cuando un dev empiece desde cero."
user-invocable: true
---

# Mi producto — Getting started

## Qué es

Un párrafo claro sobre el producto.

## Primeros pasos

1. Crear cuenta
2. Obtener API key
3. Hacer tu primer request

El frontmatter YAML es obligatorio para el ecosistema npx skills. Sin él, el CLI puede ignorar o malinterpretar el skill.

3. CORS en Next.js (si usas Next)

Herramientas en el browser o algunos clientes fetch cross-origin. En next.config.ts:

typescript
headers: async () => [
  {
    source: '/.well-known/:path*',
    headers: [
      { key: 'Access-Control-Allow-Origin', value: '*' },
      { key: 'Access-Control-Allow-Methods', value: 'GET, OPTIONS' },
    ],
  },
],

En Nginx o CloudFront puedes agregar los mismos headers solo para /.well-known/*. En hosts puramente estáticos sin CORS, muchas veces igual funciona el CLI (Node), pero CORS no cuesta nada y evita sorpresas.

4. Fijar la URL canónica en el código

Define una constante y úsala en sitemap, llms.txt, metadata:

typescript
export const WEBSITE_URL =
  process.env.WEBSITE_URL ||
  process.env.NEXT_PUBLIC_WEBSITE_URL ||
  'https://www.tusitio.com';

Nunca hardcodees el apex en el hero si el canónico es www.

5. Mostrar el comando de instalación

En tu landing o docs:

bash
npx skills add https://www.tusitio.com

Usa exactamente el host que pasó el curl -sI con 200 directo.

6. Desplegar y probar de punta a punta

bash
# Manifiesto accesible
curl -s https://www.tusitio.com/.well-known/agent-skills/index.json

# Skill accesible
curl -s https://www.tusitio.com/.well-known/agent-skills/mi-primer-skill/SKILL.md | head

# Instalación real (en una máquina de prueba)
npx skills add https://www.tusitio.com

Si algo falla, revisa en este orden: redirect www → JSON válido → frontmatter en SKILL.md → CORS → deploy cacheado (purga CDN).

Errores comunes

  • `npx skills add` no encuentra skills — La URL suele apuntar al apex (tusitio.com) y ese dominio redirige a www. En el comando usa el host canónico: el que responde 200 sin redirect.
  • 404 en `index.json` — Los archivos no están en public/ o el path está mal escrito. Compara la ruta local con la URL en producción.
  • Skill vacío o sin metadata — Falta el frontmatter YAML al inicio del archivo. Agrega name, description y user-invocable.
  • Funciona en curl, falla en el browser — Falta CORS en /.well-known/*. Agrega los headers en next.config.ts, Nginx o CloudFront.
  • Cambiaste el skill y no se actualiza — El CDN cacheó la respuesta anterior. Purga la cache o baja Cache-Control en esas rutas.

Relación con el resto del stack

  • Nota 004llms.txt: mapa de links para agentes que navegan tu sitio
  • Nota 006.agents/: rules y skills internos (symlinks a editores)
  • Esta nota — skills públicos instalables por cualquier usuario vía npx skills add

En mi sitio tengo cuatro skills públicos (getting-started, api-rest, flutter-sdk, workflows) bajo public/.well-known/agent-skills/ y decenas de skills de desarrollo en .agents/skills/ que no publico.

Referencia rápida

text
Manifiesto:   /.well-known/agent-skills/index.json
Skill:        /.well-known/agent-skills/{name}/SKILL.md
Instalar:     npx skills add https://www.tusitio.com   ← host canónico, sin redirect
Next.js:      public/.well-known/... + headers CORS en next.config.ts
Canónico:     una sola URL (www o apex) en código, docs y comando
Verificar:    curl -sI manifiesto → 200; luego npx skills add

Más notas sobre Ingeniería de IA.