====== 7. AGENTS.md ======
Qué es ''AGENTS.md'' en dos líneas está en [[cursos:sdd:02-conceptos-basicos#fichero_agentsmd|Conceptos básicos]], y cómo se genera el primero, en [[cursos:sdd:03-opencode#init|OpenCode]] y [[cursos:sdd:04-claude-code#init|Claude Code]]. Aquí, qué entra en él, dónde va todo lo demás y cómo se escriben las referencias para que funcionen igual en las dos herramientas.
----
===== 1. Qué es AGENTS.md =====
''AGENTS.md'' es un markdown en la raíz del repositorio con las instrucciones fijas del proyecto: lo que le contarías a un compañero nuevo el primer día. **Se carga entero en todas las sesiones**, encaje o no con la tarea. Es un [[https://agents.md/|estándar abierto]]: el mismo fichero lo leen Claude Code, OpenCode, Codex, Cursor, Copilot o Gemini CLI.
==== Pequeño: el detalle va en skills ====
Como se paga en cada petición, ''AGENTS.md'' tiene que ser **pequeño**: solo lo imprescindible y un índice. El detalle se reparte en [[cursos:sdd:08-skills-agentes#que_es_una_skill|skills]], una por tema, y el agente carga solo la que necesita para la tarea.
AGENTS.md
.opencode
└── skills
├── producto
│ └── SKILL.md
├── tecnologia
│ └── SKILL.md
├── arquitectura
│ ├── SKILL.md
│ ├── cliente.md
│ └── servidor.md
└── despliegue
├── SKILL.md
├── desarrollo.md
└── produccion.md
Las que tiene que haber como mínimo:
* ''producto'': para qué sirve el producto, qué valor aporta y sus capacidades principales.
* ''tecnologia'': el stack, los frameworks, las decisiones técnicas y las restricciones del sistema completo.
* ''arquitectura'': organización de directorios, patrones de arquitectura y convenciones de nombres.
* ''despliegue'': cómo se despliega la aplicación, lo común a todos los entornos.
Si hay varias arquitecturas, el ''SKILL.md'' se queda con lo común y cada una va en un fichero de apoyo dentro de la //skill//: ''cliente.md'', ''servidor.md'', ''movil.md''. Con el despliegue igual: ''desarrollo.md'' y ''produccion.md'' con lo propio de cada entorno.
---
name: arquitectura
description: Carpetas, patrones y nombres del proyecto. Usar antes de crear
cualquier clase o fichero.
---
# Arquitectura
- Un paquete por funcionalidad (`pedidos`, `clientes`), no por capa.
- Los controladores solo validan y delegan: la lógica va en los servicios.
Lee además `servidor.md` si tocas `servidor/` y `cliente.md` si tocas `cliente/`.
''AGENTS.md'' dice **cuándo** usar cada una:
# Pedidos
API REST de pedidos con cliente web. Compilar y probar: `./mvnw verify`.
## Skills del proyecto
Antes de empezar, lee la skill que necesite la tarea:
- `.claude/skills/producto/SKILL.md`: antes de escribir o revisar una especificación.
- `.claude/skills/tecnologia/SKILL.md`: antes de añadir una dependencia.
- `.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.
- `.claude/skills/despliegue/SKILL.md`: antes de tocar el despliegue.
**La //skill// sola no basta.** El agente la carga solo si decide que encaja con la tarea, y muchas veces no lo decide: en las [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|pruebas de Vercel]] no llegó a usarse en más de la mitad de los casos. El índice de ''AGENTS.md'' está siempre en contexto, así que convierte esa decisión en una instrucción. Y como da la ruta del fichero, funciona también en un agente que no sepa de //skills//.
Cómo generar un primer ''AGENTS.md'' con ''/init'' y cómo mantenerlo: [[cursos:sdd:03-opencode#init|/init en OpenCode]].
==== CLAUDE.md: no usarlo ====
Existe también ''CLAUDE.md'', el fichero propio de Claude Code. **No lo uses**: si en una carpeta hay ''CLAUDE.md'', Claude Code lee solo ese y **deja de leer el ''AGENTS.md''** de esa misma carpeta, sin avisar. El equipo que usa otra herramienta ve unas normas y el que usa Claude Code ve otras.
Como basta con que alguien cree un ''CLAUDE.md'' para que el ''AGENTS.md'' deje de valer, se añade una **regla de arquitectura** que lo impida: un test que falla si aparece alguno en el repositorio.
class SinClaudeMdTest {
@Test
void noHayNingunClaudeMd() throws IOException {
try (Stream ficheros = Files.walk(Path.of("."))) {
List claudeMd = ficheros
.filter(f -> !f.startsWith("./target") && !f.startsWith("./.git"))
.filter(f -> f.getFileName().toString().equalsIgnoreCase("CLAUDE.md"))
.toList();
assertThat(claudeMd)
.as("Las instrucciones van en AGENTS.md, no en CLAUDE.md")
.isEmpty();
}
}
}
----
===== 2. Cómo se organiza AGENTS.md =====
La [[#que_es_agentsmd|sección 1]] dice que ''AGENTS.md'' es un índice pequeño. Aquí va qué entra en él, dónde va todo lo demás y cómo se escriben las referencias para que funcionen igual en Claude Code y en OpenCode.
==== Qué entra ====
El agente **obedece** lo que pone el fichero: en el [[https://arxiv.org/abs/2602.11988|estudio de ETH Zurich]], cuando ''AGENTS.md'' nombra una herramienta, el agente la usa en casi todas las tareas, y si no la nombra, casi nunca. Pero el fichero encarece cada tarea más de un 20 %, y solo mejora el resultado cuando cuenta lo que no es estándar. Así que entra solo lo que vale **para todas las tareas** y **no se deduce del código**:
* **Una frase** con qué es el proyecto.
* **Órdenes** para compilar, probar y comprobar, si no son las habituales.
* **Convenciones que se apartan de lo normal**: las que el agente no adivinaría leyendo el código.
* **Límites**: lo que no se hace nunca y lo que se pregunta antes.
* **El índice de //skills//**, con cuándo leer cada una.
Fuera: la descripción general del proyecto, el árbol de carpetas, la lista de dependencias y las reglas de estilo. Las tres primeras el agente las saca del propio código, y en el estudio no le ayudaron a encontrar antes los ficheros que tenía que tocar. El estilo lo impone el formateador, no un párrafo.
**No dejes tal cual el ''AGENTS.md'' que genera ''/init''.** Mete justo lo que sobra: descripción, arquitectura y dependencias. Los ficheros generados por el modelo salen peor que los escritos a mano. Úsalo de borrador y recorta.
# Pedidos
API REST de pedidos con cliente web.
## Órdenes
- Compilar y probar: `./mvnw verify`
- Solo los tests del servidor: `./mvnw -pl servidor test`
## Convenciones
- Los importes son `BigDecimal` con escala 2; nunca `double`.
- Los errores de negocio heredan de `ErrorDeNegocio`; los controladores no lanzan `RuntimeException`.
- Cada requisito de `specs/` tiene al menos un test que cita su identificador (`R-12`).
## Límites
- No modifiques una migración ya aplicada: crea una nueva.
- Pregunta antes de añadir una dependencia o de cambiar un requisito de `specs/`.
## Skills del proyecto
Explora primero el código que toca la tarea. Después lee la skill que necesite:
- `.claude/skills/producto/SKILL.md`: antes de escribir o revisar una especificación.
- `.claude/skills/tecnologia/SKILL.md`: antes de añadir una dependencia.
- `.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.
- `.claude/skills/despliegue/SKILL.md`: antes de tocar el despliegue.
Cabe en una pantalla, y así tiene que seguir: **menos de 200 líneas**, mejor menos de 60. Cada instrucción de más hace que el modelo cumpla peor todas las demás, no solo la nueva.
==== Dónde va lo demás ====
^ Qué es ^ Dónde va ^ Ejemplo ^
| Lo que vale en todas las tareas | ''AGENTS.md'' raíz | «Los importes son ''BigDecimal''» |
| Lo que vale solo en una carpeta | ''AGENTS.md'' de esa carpeta | ''servidor/src/test/AGENTS.md'': «los tests de integración crean los pedidos con ''PedidoFactory''; no se mockea el repositorio» |
| El detalle que solo hace falta en algunas tareas | Una //skill// | ''arquitectura'', ''despliegue'' |
| Un procedimiento que se lanza para una tarea concreta | Una //skill// | ''revisar-pr'' |
| Lo que tiene que cumplirse siempre | Un test, el linter o un //hook// | ''SinClaudeMdTest'', el formateador |
* **''AGENTS.md'' por carpeta**: Claude Code y OpenCode lo cargan cuando el agente trabaja con ficheros de esa carpeta. Solo se crea si sus normas difieren de las de la raíz, y **no puede contradecirla**: cada herramienta los junta en un orden distinto, así que no está claro cuál gana.
* **Lo que tiene que cumplirse siempre** no va en ''AGENTS.md'': ahí es una petición, no una garantía. Si de verdad no puede fallar, un test que lo compruebe, como el de la [[#claudemdno_usarlo|regla de ''CLAUDE.md'']].
==== Cómo se escriben las referencias ====
Cada referencia lleva **la ruta entre comillas invertidas** y **cuándo leerla**. Nunca con ''@'':
^ Referencia ^ Claude Code ^ OpenCode ^
| ''`.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.'' | La lee cuando la tarea lo pide | La lee cuando la tarea lo pide |
| ''@.claude/skills/arquitectura/SKILL.md'' | La carga entera al arrancar, en todas las sesiones | No la entiende: es texto |
| ''Ver la skill de arquitectura.'' | No sabe cuándo leerla | No sabe cuándo leerla |
**El ''@'' anula el índice.** En Claude Code, ''@ruta'' importa el fichero al arrancar, así que un índice escrito con ''@'' carga todas las //skills// en cada sesión: lo mismo que meterlas en ''AGENTS.md''. El ejemplo de la [[https://opencode.ai/docs/rules/|documentación de OpenCode]] usa ''@'' y en Claude Code hace justo eso.
La condición se escribe con **las palabras con las que se pedirá la tarea** («antes de escribir o revisar una especificación»), sin «MUST» ni mayúsculas. En la [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|prueba de Vercel]], «explora primero el proyecto y luego usa la //skill//» acertó más que «debes usar la //skill//»: con la orden tajante, el agente leía la documentación primero, seguía sus ejemplos sin mirar el proyecto y se dejaba cambios.
Lo mismo vale para la ''description'' de cada //skill// ([[cursos:sdd:08-skills-agentes#el_frontmatter|el frontmatter]]): las //skills// se activan casi por palabra clave. En la [[https://scottspence.com/posts/measuring-claude-code-skill-activation-with-sandboxed-evals|medición de Scott Spence]], con la palabra en el prompt se activaban casi siempre; con una forma genérica de pedirlo, entre un 20 y un 40 % de las veces.
----
===== Fuentes =====
* [[https://agents.md/|AGENTS.md]]: el estándar, con ejemplos y la lista de herramientas que lo leen.
* [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|AGENTS.md outperforms skills in our agent evals]]: la prueba de Vercel. Índice en ''AGENTS.md'': 100 %; //skill// sola: 53 %; //skill// con instrucción explícita: 79 %. La //skill// no llegó a usarse en el 56 % de los casos.
* [[https://dreaming.press/posts/agents-md-vs-agent-skills-evals.html|AGENTS.md vs Agent Skills evals]]: lectura crítica de la prueba de Vercel. Lo que decide es dónde está el aviso de cargar la documentación (siempre en contexto o a decisión del modelo), no el formato.
* [[https://scottspence.com/posts/measuring-claude-code-skill-activation-with-sandboxed-evals|Measuring Claude Code skill activation]]: otra medición. Sin ayuda, las //skills// se activan solas la mitad de las veces; cuando se activan, siempre es la correcta.
* [[https://aihero.dev/a-complete-guide-to-agents-md|A complete guide to AGENTS.md]]: ''AGENTS.md'' mínimo y el detalle en ficheros enlazados por tema; qué no meter en él.
* [[https://skills.cat/skills/heykvnzhao/dotfiles/agents-md-best-practices|agents-md-best-practices]]: //skill// que parte un ''AGENTS.md'' grande en un índice y un fichero por tema.
* [[https://github.com/opsmill/infrahub-sdk-python/pull/609|infrahub-sdk-python PR #609]]: caso real. Un ''CLAUDE.md'' de 317 líneas pasa a un ''AGENTS.md'' de 77 más un ''AGENTS.md'' por carpeta; después el repositorio añadió //skills// para sus procedimientos.
* [[https://www.humanlayer.dev/blog/writing-a-good-claude-md|Writing a good CLAUDE.md]]: por qué cada instrucción de más empeora el cumplimiento del resto, y la carpeta de documentos enlazada desde el índice.
* [[https://arxiv.org/abs/2602.11988|Evaluating AGENTS.md]]: estudio de ETH Zurich. Los ficheros de contexto encarecen más de un 20 % cada tarea y en general no mejoran el resultado; sí ayudan cuando cuentan prácticas no estándar del proyecto.
* [[https://code.claude.com/docs/en/memory|Claude Code: memory]]: menos de 200 líneas; los procedimientos y lo que vale solo para una parte del código, a //skills//; ''@ruta'' no ahorra contexto porque carga el fichero al arrancar.
* [[https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more|Steering Claude Code]]: el fichero de instrucciones como índice que apunta a otros ficheros.
* [[https://opencode.ai/docs/rules/|OpenCode: rules]]: OpenCode no sigue solo las rutas que aparecen en ''AGENTS.md''; hay que decirle cuándo leer cada fichero.