Skills para IA como documentación viva de un equipo de desarrollo
Cómo usar skills de IA para capturar convenciones, arquitectura y patrones internos de un equipo. No magia, sino documentación operativa.

Todos los equipos que conozco tienen convenciones que no están escritas en ningún sitio. Cómo se nombran los endpoints. Qué estructura tiene un servicio nuevo. Dónde van los tests de integración. Cuál es el patrón para manejar errores. Qué librerías están aprobadas y cuáles no. Por qué se eligió Kotlin en vez de Java para ese módulo.
Todo ese conocimiento vive en la cabeza de tres o cuatro personas del equipo. Cuando alguien nuevo entra, lo aprende a base de code reviews, preguntas en Slack y errores que le corrigen en PRs. Cuando alguien se va, parte de ese conocimiento desaparece.
Las skills de IA no son la solución mágica a este problema. Pero son una herramienta sorprendentemente buena para capturarlo de una forma que realmente se usa. No como un documento de Confluence que nadie lee, sino como instrucciones operativas que un agente de IA aplica cada vez que trabaja con tu código.
Qué es una skill (en el contexto que nos interesa)
En el artículo de MCP vs Skills ya explicaba la diferencia entre ambos conceptos. Aquí no voy a repetir eso. Lo que me interesa es un uso concreto: las skills como documentación viva de las prácticas de un equipo de desarrollo.
Una skill, en este contexto, es un documento estructurado que le dice a un agente de IA cómo trabaja tu equipo. No es un manual genérico. Es la codificación de vuestras decisiones, convenciones y patrones específicos.
La diferencia entre una skill y documentación tradicional es que la skill se ejecuta. No la lee una persona y la interpreta. La lee un agente y la aplica directamente al generar código, revisar PRs o crear tests.
Eso cambia radicalmente lo que merece la pena documentar y cómo hacerlo.
Ejemplo real: skill de convenciones backend
Voy a mostrar un ejemplo concreto de skill que uso en un proyecto con Kotlin y Spring Boot. No es un ejemplo inventado; es una versión simplificada de lo que tengo en un repositorio real.
# Backend Conventions - [Nombre del proyecto]
## Stack y versiones
- Kotlin 2.x, Spring Boot 3.x, Gradle (Kotlin DSL)
- Base de datos: PostgreSQL 16
- Tests: JUnit 5 + MockK + Testcontainers
## Estructura de paquetes
Seguimos estructura por feature, no por capa:
src/main/kotlin/com/example/project/ ├── order/ │ ├── OrderController.kt │ ├── OrderService.kt │ ├── OrderRepository.kt │ ├── Order.kt # Entidad │ ├── OrderDto.kt # DTOs de request/response │ └── OrderException.kt # Excepciones específicas ├── product/ │ └── … └── shared/ ├── config/ ├── security/ └── exception/
## Convenciones de código
### Naming
- Controllers: `{Feature}Controller`
- Services: `{Feature}Service` (interfaz) + `{Feature}ServiceImpl` solo si hay más de una implementación
- DTOs: `{Feature}Request`, `{Feature}Response`
- Excepciones: `{Feature}{Tipo}Exception` (ej: `OrderNotFoundException`)
### Endpoints REST
- Siempre versionados: `/api/v1/{recurso}`
- Plurales: `/api/v1/orders`, no `/api/v1/order`
- Filtros como query params, no path params
- Respuestas paginadas usan `Page<T>` de Spring Data
### Error handling
- Usamos `@RestControllerAdvice` centralizado
- Las excepciones de negocio extienden `BusinessException`
- El formato de error es siempre:
```json
{
"code": "ORDER_NOT_FOUND",
"message": "Texto descriptivo",
"timestamp": "2026-05-18T10:00:00Z"
}Tests
- Unit tests: MockK para mocks, sufijo
Test - Integration tests: Testcontainers, sufijo
IntegrationTest - Cada servicio tiene al menos: happy path, validación de input, caso de error principal
- NO mockeamos repositorios en integration tests
Antipatrones (no hacer)
- No usar
@Autowiredpor field injection. Siempre constructor injection. - No crear DTOs genéricos compartidos entre features. Cada feature tiene los suyos.
- No poner lógica de negocio en controllers.
- No usar
Optional<T>de Java. Usar nullable types de Kotlin. - No hacer queries con string concatenation. Siempre named parameters.
Ejemplo de servicio correcto
@Service
class OrderService(
private val orderRepository: OrderRepository,
private val eventPublisher: ApplicationEventPublisher
) {
fun getOrder(orderId: Long): OrderResponse {
val order = orderRepository.findByIdOrNull(orderId)
?: throw OrderNotFoundException(orderId)
return order.toResponse()
}
@Transactional
fun createOrder(request: CreateOrderRequest): OrderResponse {
val order = request.toEntity()
val saved = orderRepository.save(order)
eventPublisher.publishEvent(OrderCreatedEvent(saved.id))
return saved.toResponse()
}
}
Este documento, cargado como skill en un agente de IA, hace que el código que genera siga automáticamente las convenciones del equipo. No necesitas corregirlo en el code review porque ya sabe que usáis inyección por constructor, que los endpoints son plurales y versionados, y que los tests de integración usan Testcontainers.
---
## Qué meter en una skill
No todo merece estar en una skill. El contenido debería cumplir tres criterios:
**1. Es estable.** No cambia cada semana. Las convenciones de naming, la estructura de paquetes, los patrones de error handling... eso es estable. La versión exacta de una dependencia que estáis evaluando no lo es.
**2. Es operativo.** Alguien (o un agente) puede aplicarlo directamente al escribir código. "Usamos estructura por feature" es operativo. "Valoramos la clean architecture" no lo es (es demasiado abstracto).
**3. Es específico de vuestro equipo.** Si es una práctica universal de Kotlin o Spring Boot, no hace falta ponerla. El agente ya lo sabe. Lo que el agente no sabe es que vosotros usáis un `@RestControllerAdvice` centralizado con un formato de error concreto.
Concretamente, lo que suelo incluir:
### Convenciones de código
- Naming de clases, métodos, paquetes.
- Estructura de proyecto.
- Patrones de error handling.
- Cómo se definen los DTOs.
- Formato de logs.
### Patrones arquitectónicos
- Cómo se comunican los módulos entre sí.
- Qué patrón se usa para eventos (si usáis event-driven).
- Cómo se gestiona la transaccionalidad.
- Separación de responsabilidades entre capas.
### Decisiones técnicas clave
- Por qué se eligió una tecnología sobre otra.
- Restricciones de seguridad (qué librerías están prohibidas, qué endpoints necesitan auth).
- Políticas de versionado de API.
### Ejemplos concretos
- Un ejemplo de servicio bien hecho.
- Un ejemplo de test bien hecho.
- Un ejemplo de migración de base de datos.
### Antipatrones explícitos
- Cosas que no se deben hacer, con el motivo.
- Errores que se han cometido en el pasado y no se quieren repetir.
---
## Qué NO meter en una skill
Tan importante como saber qué incluir es saber qué dejar fuera. He visto skills que intentan ser una enciclopedia del proyecto y acaban siendo inútiles porque el agente se pierde entre tanto ruido.
**Información efímera.** El estado actual de un sprint, quién está de vacaciones, qué tickets están en progreso. Eso cambia constantemente y contamina el contexto del agente.
**Datos sensibles.** Credenciales, API keys, URLs de sistemas internos, nombres de clientes reales. Una skill puede acabar en el contexto de un LLM externo. Nunca pongas en una skill algo que no pondrías en un repo público.
**Detalles de implementación de terceros.** No necesitas explicarle al agente cómo funciona Spring Security internamente. Sí necesitas explicarle cómo lo habéis configurado vosotros.
**Todo lo que cambia cada semana.** Si una decisión aún no está consolidada, no la pongas en la skill. Espera a que se estabilice. Una skill con información contradictoria o desactualizada es peor que no tener skill.
**Opiniones personales no consensuadas.** "Yo prefiero usar corrutinas para todo" no es una convención del equipo. Si el equipo ha decidido usar corrutinas en un contexto específico, eso sí es documentable.
> La regla es sencilla: si no lo defenderías en un code review como convención del equipo, no va en la skill.
---
## Cómo versionarlo: junto al código, en el repo
Las skills deberían vivir en el mismo repositorio que el código. No en un wiki separado. No en un Google Doc. No en un canal de Slack fijado.
La razón es práctica: si la skill está en el repo, se versiona con git, se revisa en PRs y evoluciona junto al código que describe. Si está en otro sitio, se desincroniza en dos semanas.
Estructura que uso:
proyecto/ ├── .ai/ │ ├── skills/ │ │ ├── backend-conventions.md │ │ ├── testing-patterns.md │ │ ├── api-design.md │ │ └── deployment-checklist.md │ └── context/ │ ├── architecture-overview.md │ └── tech-decisions.md ├── src/ ├── build.gradle.kts └── …
La carpeta `.ai/skills/` contiene las skills propiamente dichas. La carpeta `.ai/context/` contiene documentos de contexto más amplio (visión general de arquitectura, decisiones técnicas tipo ADR) que complementan las skills pero no son instrucciones operativas.
Ventajas de este enfoque:
- **Versionado.** Cada cambio en una skill queda registrado en git. Puedes ver quién lo cambió, cuándo y por qué.
- **Code review.** Un cambio en una skill pasa por el mismo proceso de revisión que un cambio en código. Eso evita que una persona meta sus preferencias personales sin consenso.
- **Sincronización.** Si cambias una convención de código, puedes actualizar la skill en el mismo PR. Así nunca se desincroniza.
- **Descubrimiento.** Cualquier persona nueva que clone el repo ve las skills inmediatamente. No tiene que buscar en tres herramientas distintas.
---
## Cómo evitar documentación basura
El riesgo más grande de las skills es que se conviertan en otro depósito de documentación muerta. Para evitarlo, aplico tres prácticas:
### 1. Review obligatorio
Cualquier cambio en una skill pasa por PR con al menos un reviewer del equipo. No se mergea sin consenso. Si alguien quiere añadir una convención nueva, tiene que justificarla y el equipo tiene que aceptarla.
Esto parece obvio pero evita el problema más común: una persona escribe una skill con sus preferencias personales y el equipo la ignora porque no la siente suya.
### 2. Testing de skills
Suena raro, pero tiene sentido. Periódicamente (yo lo hago cada dos o tres sprints) hago una prueba sencilla: le doy la skill a un agente de IA y le pido que genere un componente nuevo. Luego reviso si el resultado sigue las convenciones del equipo.
Si el agente genera código que no cumple con vuestras convenciones, la skill no está bien escrita. Es un test funcional de la documentación.
```bash
# Ejemplo de prompt para testear una skill
"Usando las convenciones del proyecto, genera un nuevo servicio para gestionar
notificaciones. Incluye el controlador, el servicio, los DTOs, los tests
unitarios y un test de integración."Reviso el output y verifico:
- Estructura de paquetes correcta.
- Naming correcto.
- Error handling siguiendo el patrón.
- Tests con el formato esperado.
- Sin antipatrones.
Si falla en algo, actualizo la skill para que sea más clara en ese punto.
3. Fecha de revisión
Cada skill tiene una fecha de última revisión en el propio documento:
# Backend Conventions
> Última revisión: 2026-05-01 | Próxima revisión: 2026-08-01
> Responsable: @rogerSi la fecha de revisión pasa sin que nadie la revise, es una señal de que la skill puede estar desactualizada. No es automatización, es disciplina del equipo.
Skills para onboarding
Uno de los usos más potentes de las skills es el onboarding de nuevos miembros del equipo. En vez de una semana de reuniones explicando “cómo hacemos las cosas aquí”, la persona nueva puede:
- Leer las skills del repo (son documentos cortos y concretos).
- Usar un agente de IA con esas skills cargadas para hacer sus primeras contribuciones.
- El agente le genera código que ya sigue las convenciones, y la persona aprende los patrones del equipo mientras trabaja.
No sustituye al mentoring humano, pero lo complementa de una forma que antes no era posible. La persona nueva no tiene que adivinar convenciones ni esperar a que le corrijan en el PR. El agente ya le da el formato correcto desde el principio.
He visto equipos donde el tiempo de onboarding efectivo (hasta que la persona contribuye código que no requiere correcciones mayores de estilo) pasó de 3-4 semanas a menos de 1 semana usando skills bien escritas.
Relación con specs y SDD
Las skills encajan naturalmente en un flujo de Spec-Driven Development. La relación es esta:
- La spec define qué se va a construir y con qué criterios de aceptación.
- La skill define cómo se construye en este equipo (convenciones, patrones, restricciones).
- El agente usa ambas para generar código que cumple los requisitos y sigue los estándares.
Sin la spec, el agente no sabe qué construir. Sin la skill, el agente construye algo genérico que no encaja con vuestro proyecto. Necesitas las dos.
Un prompt típico que combina ambas:
Contexto: Carga las skills de backend-conventions.md y testing-patterns.md
Tarea: Implementa el ticket ORDER-123 siguiendo la spec adjunta.
Requisitos:
- Endpoint POST /api/v1/orders/bulk para creación masiva de pedidos
- Validación de stock antes de confirmar
- Evento OrdersBulkCreated al completar
- Tests unitarios y de integración
Spec: [contenido de la spec del ticket]El resultado es código que cumple la funcionalidad especificada Y sigue las convenciones del equipo. Eso es lo que hace que las skills no sean un documento decorativo: son una pieza funcional del flujo de trabajo.
Empezar pequeño
Si no tienes skills y quieres empezar, no intentes documentar todo el primer día. Empieza con una sola skill: las convenciones de código más básicas de tu proyecto. Lo mínimo que le dirías a alguien nuevo el primer día.
Una skill de 40-50 líneas bien escritas vale más que un documento de 500 líneas que nadie mantiene. Con el tiempo, irás añadiendo más skills a medida que identifiques patrones que el equipo repite y que el agente necesita conocer.
Lo importante no es tener la skill perfecta. Es tener una skill que se usa, se revisa y evoluciona con el proyecto. Eso ya es más documentación viva de la que tiene el 90% de los equipos.


