DEV Community

Cover image for ¿Qué es DESIGN.md para Agentes de Codificación?
Roobia
Roobia

Posted on • Originally published at apidog.com

¿Qué es DESIGN.md para Agentes de Codificación?

Los agentes de codificación son rápidos, pero no conocen la arquitectura de tu repositorio hasta que se la das por escrito. Si le pasas a Claude Code, Codex o Cursor un ticket ambiguo, puede generar código que compila, pasa una prueba rápida y aun así rompe límites importantes: lógica de dominio en controladores HTTP, llamadas externas dentro de transacciones o tipos duplicados que ya existían. Un archivo DESIGN.md reduce ese riesgo porque documenta la intención arquitectónica dentro del repositorio, justo donde el agente busca contexto.

Prueba Apidog hoy

TL;DR

DESIGN.md es un archivo Markdown en el repositorio que explica la intención arquitectónica, restricciones e invariantes de una base de código para que agentes como Claude Code, Codex o Cursor generen cambios compatibles con el sistema existente.

  • README.md responde: qué es el proyecto y cómo empezar.
  • AGENTS.md responde: cómo construir, probar y trabajar en este repo.
  • CLAUDE.md responde: instrucciones específicas para Claude Code.
  • DESIGN.md responde: por qué el sistema tiene esta forma y qué reglas no deben romperse.

Introducción

El fallo típico aparece rápido: pides añadir un endpoint de reembolso a un servicio de pagos y el agente devuelve un controlador funcional que llama directamente a la base de datos, ignora errores de la pasarela e inventa un nuevo tipo de moneda porque no vio el existente.

El diff puede verse limpio. Las pruebas pueden pasar. Pero el cambio sigue estando mal porque viola decisiones arquitectónicas que no estaban en el contexto del agente.

DESIGN.md resuelve ese problema de forma práctica: coloca en la raíz del repositorio las reglas que un ingeniero sénior explicaría antes de dejar que alguien toque una parte crítica del sistema.

Qué es realmente DESIGN.md

DESIGN.md es un registro de texto plano del porqué tu código tiene la forma que tiene.

No debería duplicar lo que ya dice el código. Debe capturar lo que el código no puede explicar por sí solo:

  • por qué una capa no puede importar otra;
  • por qué las llamadas externas pasan por outbox;
  • por qué el dinero se representa como enteros;
  • por qué un agregado es la única ruta válida de escritura;
  • qué alternativas ya se probaron y se rechazaron.

Ejemplo de decisión que sí pertenece a DESIGN.md:

El controlador HTTP nunca llama directamente a la pasarela de pago. Toda llamada externa se agenda mediante outbox porque la pasarela puede agotar tiempo de espera bajo carga y necesitamos reintentos idempotentes.

Ejemplo de texto que no aporta:

PaymentController maneja pagos.

Eso el agente ya lo puede leer del código.

La idea está relacionada con prácticas anteriores como ARCHITECTURE.md y los ADRs, pero escrita para una audiencia que incluye agentes de codificación: reglas claras, declarativas y fáciles de recuperar desde el contexto.

DESIGN.md vs AGENTS.md vs CLAUDE.md vs README

Estos archivos no compiten. Cada uno tiene un trabajo distinto.

AGENTS.md es un formato abierto para guiar agentes de codificación. El proyecto agents.md lo describe como un formato simple para indicar comandos de build, test, lint, estilo, convenciones de commits y reglas operativas.

Según la documentación de memoria de Claude Code, CLAUDE.md cumple ese rol para Claude. Anthropic recomienda que, si ya tienes AGENTS.md, puedes crear un CLAUDE.md que lo importe con @AGENTS.md.

La diferencia clave: AGENTS.md y CLAUDE.md deberían ser cortos. La documentación de Claude Code recomienda mantener CLAUDE.md por debajo de unas 200 líneas porque archivos largos consumen contexto y reducen la fiabilidad.

La arquitectura profunda no debería vivir ahí. Debe estar en DESIGN.md y ser referenciada desde los archivos operativos.

Archivo Audiencia Responde a Cambio esperado Longitud
README.md Humanos Qué es esto y cómo empezar Cambia con el producto Media
AGENTS.md Agentes de codificación Cómo construir, probar, lintar y trabajar aquí Cambia con herramientas Corta
CLAUDE.md Claude Code Instrucciones específicas para Claude Cambia con herramientas Corta
DESIGN.md Agentes, ingenieros y revisores Por qué el sistema tiene esta forma y qué no debe romperse Cambia con arquitectura Media y densa

Una configuración práctica:

README.md      -> onboarding humano
AGENTS.md      -> comandos, estilo, pruebas, flujo de trabajo
CLAUDE.md      -> @AGENTS.md + reglas específicas de Claude
DESIGN.md      -> arquitectura, invariantes y decisiones
Enter fullscreen mode Exit fullscreen mode

En AGENTS.md puedes añadir:

## Arquitectura

Antes de cambios estructurales, lee `DESIGN.md`.
Sus reglas de capas, invariantes y decisiones arquitectónicas son obligatorias.
Enter fullscreen mode Exit fullscreen mode

Si trabajas con Claude Code, CLAUDE.md puede ser tan simple como:

@AGENTS.md
@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Para una guía más amplia de contexto en Claude, consulta los flujos de trabajo de Claude Code.

Qué incluir en DESIGN.md

Un buen DESIGN.md responde preguntas que el agente no puede inferir de un archivo individual.

Incluye estas secciones:

  • Forma del sistema: capas, módulos y dirección de dependencias.
  • Invariantes: reglas que siempre deben cumplirse.
  • Decisiones clave y justificación: no solo qué se decidió, sino por qué.
  • Alternativas rechazadas: opciones que no deben reintroducirse.
  • Reglas de datos y dominio: dinero, tiempo, IDs, multi-tenencia, borrado.
  • Fuente de verdad del contrato API: ubicación de OpenAPI y tipos generados.
  • Dónde va el nuevo código: mapa rápido para endpoints, casos de uso, clientes externos.
  • Fuera de alcance / no tocar: código generado, legacy congelado, migraciones aplicadas.
  • En caso de duda: qué debe hacer el agente si una tarea contradice el diseño.

Plantilla práctica de DESIGN.md

Puedes copiar esta plantilla y ajustarla a tu servicio.

# DESIGN.md: Servicio de API de Pagos

Este archivo registra la intención arquitectónica del servicio.
Léelo antes de generar o modificar código.

Si un cambio solicitado entra en conflicto con una regla de este archivo,
detente y señala el conflicto. No lo eludas silenciosamente.

## Forma del sistema

Las dependencias apuntan hacia adentro:

http -> app -> domain <- infra

- `domain/` no importa `http/`, `app/` ni frameworks.
- `infra/` implementa interfaces declaradas en `domain/` o `app/`.
- `http/` nunca toca la base de datos ni la pasarela directamente.
- `http/` llama a casos de uso en `app/`.

## Invariantes

- Una entrada del libro mayor es inmutable una vez escrita.
- Las correcciones son nuevas entradas compensatorias, no updates ni deletes.
- El saldo se deriva del libro mayor; no se almacena como campo mutable.
- El dinero se representa como unidades menores enteras + código ISO-4217.
- Nunca usar floats para dinero.
- Nunca mezclar monedas en una operación.
- Cada llamada externa de pago usa `idempotency_key`.
- Los reintentos no deben producir doble cargo.
- Los saldos no pueden ser negativos salvo autorización explícita de `OverdraftPolicy`.

## Decisiones clave

### Outbox para llamadas a pasarela

Los controladores escriben una intención en la base de datos dentro de la misma
transacción del cambio de negocio. Un worker procesa esa intención y llama a la
pasarela.

Justificación: la pasarela puede agotar tiempo de espera bajo carga. Hacer llamadas
externas en línea mezcla latencia HTTP, reintentos y consistencia transaccional.

Regla: no llamar a la pasarela desde un controlador de request.

### Ruta única de escritura por agregado

Solo `Account.post_entry()` escribe en el libro mayor.

Justificación: una segunda ruta de escritura causó desviación de saldo.

Regla: añadir nuevo comportamiento como método del agregado, no como queries ad-hoc.

### Event sourcing solo para el libro mayor

El libro mayor usa event sourcing. El resto del sistema usa CRUD.

Justificación: necesitamos auditoría perfecta para dinero, no complejidad global.

## Alternativas rechazadas

- Carga perezosa de ORM dentro de agregados.
- Almacenar el saldo como columna actualizada in situ.
- Usar una librería externa genérica de `Money`.
- Webhooks síncronos desde el hilo de request.

No reintroducir estas opciones sin una decisión explícita de arquitectura.

## Reglas de datos y dominio

- Todas las marcas de tiempo son UTC.
- Las respuestas HTTP formatean fechas como RFC 3339.
- No cruzar límites de función con datetimes ingenuos.
- Los IDs son ULIDs generados en la capa de aplicación.
- No usar autoincremento de base de datos para IDs públicos.
- No usamos soft delete.
- Multi-tenencia: cada query debe tener alcance por `tenant_id`.
- Un método de repositorio sin alcance de tenant es un bug.

## Fuente de verdad del contrato API

- `api/openapi.yaml` es la especificación OpenAPI 3.1 autoritaria.
- Los tipos de request/response se generan desde OpenAPI.
- No editar manualmente `http/generated/`.
- Para endpoints nuevos o modificados:
  1. actualizar `api/openapi.yaml`;
  2. regenerar tipos;
  3. implementar;
  4. probar contra el contrato.
- Las respuestas de error siguen RFC 9457 (`problem+json`).
- Usar el helper `problem()`.
- No inventar formatos de error por endpoint.

## Dónde va el nuevo código

- Nuevo endpoint:
  - ruta en `http/routes/`;
  - DTO en `http/dto/`;
  - caso de uso en `app/usecases/`;
  - reglas de negocio en `domain/`.

- Nueva integración externa:
  - cliente en `infra/clients/`;
  - interfaz en `app/ports/`.

- Cross-cutting concerns:
  - autenticación, logging e idempotencia van en middleware;
  - no inline en handlers.

## Fuera de alcance / no tocar

- `http/generated/`: código generado desde OpenAPI.
- `legacy/billing_v1/`: congelado y en migración.
- `migrations/`: no editar migraciones aplicadas; crear una nueva.

## En caso de duda

Si una tarea requiere romper una regla anterior, señala el conflicto y propone
la alternativa más pequeña compatible con el diseño.
Enter fullscreen mode Exit fullscreen mode

La última sección es importante. Convierte el documento en una barandilla activa: le dice al agente qué hacer cuando la solicitud del usuario contradice la arquitectura.

Cómo hacer que los agentes lean DESIGN.md

Los agentes no tienen un parser especial para DESIGN.md. Lo tratan como contexto. Por eso debes enlazarlo desde el archivo que ya cargan.

Para Claude Code:

# CLAUDE.md

@AGENTS.md
@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Para agentes que siguen AGENTS.md:

# AGENTS.md

## Arquitectura

Lee `DESIGN.md` antes de:
- añadir endpoints;
- crear módulos;
- cambiar límites de capa;
- introducir dependencias externas;
- modificar persistencia;
- tocar contratos API.
Enter fullscreen mode Exit fullscreen mode

Tres reglas prácticas:

  1. No dupliques el contenido. Referencia DESIGN.md; no pegues todo en AGENTS.md.
  2. Usa encabezados y listas. Los agentes recuperan mejor reglas estructuradas que párrafos largos.
  3. Escribe reglas comprobables. “No llamar a la pasarela desde controladores” funciona mejor que “mantener buena separación”.

Ejemplo de feedback útil durante revisión:

Este cambio rompe la regla de DESIGN.md: `http/` no debe tocar la base de datos.
Refactoriza el acceso a datos dentro de un caso de uso en `app/`.
Enter fullscreen mode Exit fullscreen mode

Ese tipo de corrección suele ser mucho más efectiva que una explicación genérica.

Si estás construyendo flujos autónomos con agentes, este ciclo de “generar -> revisar contra reglas -> corregir” es clave. Puedes ver más ideas en crea tu propio Claude Code.

Anti-patrones de DESIGN.md

Un DESIGN.md malo puede ser peor que no tener ninguno. Si está obsoleto, los agentes y humanos confiarán en información falsa.

Evita estos anti-patrones.

1. Repetir el código

Mal:

`UserService` gestiona usuarios.
Enter fullscreen mode Exit fullscreen mode

Mejor:

La capa `domain/` no puede depender de `UserService`.
Las reglas de negocio de usuario viven en entidades y políticas de dominio.
Enter fullscreen mode Exit fullscreen mode

2. Convertirlo en tutorial

Los pasos para ejecutar comandos pertenecen a AGENTS.md, README.md o CONTRIBUTING.md.

Mal:

Para añadir un endpoint, ejecuta npm install, luego npm run dev...
Enter fullscreen mode Exit fullscreen mode

Mejor:

Todo endpoint nuevo debe actualizar primero `api/openapi.yaml`.
Enter fullscreen mode Exit fullscreen mode

3. Documentar aspiraciones como hechos

Mal:

El sistema usa CQRS.
Enter fullscreen mode Exit fullscreen mode

Si solo parte del sistema lo usa, escribe la verdad:

Objetivo: todas las escrituras pasan por casos de uso.
Actual: `legacy/` aún omite esta regla. No extender ese patrón.
Enter fullscreen mode Exit fullscreen mode

4. No tener propietario

Añade una regla en la plantilla de PR:

- [ ] ¿Este PR cambia una decisión descrita en `DESIGN.md`?
      Si sí, actualiza `DESIGN.md` en este mismo PR.
Enter fullscreen mode Exit fullscreen mode

5. Intentar sincronizarlo línea por línea

No documentes firmas de funciones o detalles que cambian cada semana. Documenta decisiones que cambian pocas veces al año.

6. Contradecir AGENTS.md

Si AGENTS.md dice una cosa y DESIGN.md otra, el agente elegirá arbitrariamente.

Separación recomendada:

  • AGENTS.md: comandos, herramientas, estilo, test, lint.
  • DESIGN.md: arquitectura, invariantes, decisiones, límites.

DESIGN.md para APIs y backend

En backend, DESIGN.md es especialmente útil porque las restricciones costosas suelen ser invisibles desde un archivo:

  • contratos API;
  • transacciones;
  • idempotencia;
  • consistencia;
  • multi-tenencia;
  • seguridad;
  • versionado;
  • errores;
  • capas.

Incluye estas reglas específicas.

1. Define la fuente de verdad del contrato API

Ejemplo:

`api/openapi.yaml` es la fuente de verdad del contrato HTTP.
Los tipos generados no se editan manualmente.
Todo endpoint nuevo o modificado actualiza OpenAPI antes de la implementación.
Enter fullscreen mode Exit fullscreen mode

Esto evita que el agente “arregle” una compilación editando tipos generados o inventando esquemas.

Si diseñas contrato primero en Apidog y exportas OpenAPI al repositorio, DESIGN.md puede apuntar a ese archivo como contrato autoritario.

El enfoque de diseño de contrato antes del código se explica en diseñar APIs para agentes de IA.

2. Explica límites de transacción

Ejemplo:

Las llamadas externas nunca ocurren dentro de una transacción de DB.
Usa outbox para efectos externos.
Enter fullscreen mode Exit fullscreen mode

Sin esta regla, un agente tenderá a implementar la llamada externa directamente en el handler.

3. Declara idempotencia como invariante

Ejemplo:

Todo endpoint que cree pagos, pedidos o aprovisionamientos acepta `Idempotency-Key`.
Los reintentos con la misma clave no duplican efectos.
Enter fullscreen mode Exit fullscreen mode

Esto es crítico en pagos y flujos de provisión.

4. Fija el modelo de errores

Ejemplo:

Todas las respuestas de error usan RFC 9457 (`application/problem+json`).
Usar `problem()`. No crear formatos ad-hoc por endpoint.
Enter fullscreen mode Exit fullscreen mode

Sin una regla explícita, cada endpoint generado puede terminar con un formato de error distinto.

5. Documenta multi-tenencia y auth

Ejemplo:

Toda query de repositorio recibe `tenant_id`.
Una query sin alcance de tenant es un bug de seguridad.
Enter fullscreen mode Exit fullscreen mode

El agente no siempre inferirá esta regla leyendo una consulta aislada.

6. Explica versionado y cambios disruptivos

Ejemplo:

Renombrar o eliminar un campo de respuesta pública es un breaking change.
No hacerlo en una versión menor.
Enter fullscreen mode Exit fullscreen mode

Esto evita que el agente “limpie” nombres de campos y rompa clientes.

Checklist para añadir DESIGN.md a un repo

Usa este flujo:

  1. Crea DESIGN.md en la raíz del repositorio.
  2. Añade solo decisiones reales, no aspiraciones.
  3. Empieza con 8-12 invariantes críticas.
  4. Incluye la ubicación de tu OpenAPI si es un backend.
  5. Añade una sección “Fuera de alcance / no tocar”.
  6. Añade una sección “En caso de duda”.
  7. Referéncialo desde AGENTS.md.
  8. Si usas Claude Code, impórtalo desde CLAUDE.md.
  9. Añade un checkbox en la plantilla de PR.
  10. Revisa el archivo cuando cambien límites, módulos o contratos.

Ejemplo mínimo para empezar:

# DESIGN.md

## Reglas obligatorias

- `domain/` no importa frameworks.
- `http/` no accede directamente a la base de datos.
- Toda escritura pasa por un caso de uso en `app/`.
- `api/openapi.yaml` es la fuente de verdad del contrato API.
- No editar código generado.
- Toda query debe tener alcance por `tenant_id`.
- Los errores HTTP usan `problem+json`.

## En caso de duda

Si una tarea contradice estas reglas, señala el conflicto antes de implementar.
Enter fullscreen mode Exit fullscreen mode

Conclusión

DESIGN.md documenta el porqué de tu arquitectura: invariantes, límites, decisiones y alternativas rechazadas.

Para agentes de codificación, eso cambia el resultado práctico:

  • menos violaciones de capas;
  • menos lógica de dominio en handlers;
  • menos tipos duplicados;
  • menos contratos API inventados;
  • errores y paginación más consistentes;
  • mejor comportamiento en transacciones, idempotencia y multi-tenencia.

No reemplaza a AGENTS.md ni a CLAUDE.md. Los complementa.

Mantén AGENTS.md corto y operativo. Mantén DESIGN.md enfocado en arquitectura. Referéncialo desde los archivos que el agente ya lee.

En APIs y backend, la mayor ganancia aparece cuando nombras la especificación OpenAPI como contrato autoritario. Diseña ese contrato primero, expórtalo al repositorio y haz que el agente implemente contra él.

Puedes descargar Apidog para diseñar APIs primero, exportar la especificación OpenAPI a la que apunta tu DESIGN.md y probar que los endpoints generados por agentes coinciden con el contrato.

Preguntas frecuentes

¿DESIGN.md es un estándar oficial como AGENTS.md?

No. AGENTS.md es un formato definido y ampliamente adoptado. DESIGN.md es una convención comunitaria, similar a ARCHITECTURE.md o los ADRs. Úsalo como patrón práctico, no como estándar formal.

¿Necesito DESIGN.md si ya tengo AGENTS.md o CLAUDE.md?

Sí, si tu arquitectura tiene restricciones no obvias. AGENTS.md y CLAUDE.md deberían ser cortos y operativos. La justificación arquitectónica profunda debe vivir en DESIGN.md.

Para el archivo operativo, consulta cómo escribir archivos AGENTS.md.

¿En qué se diferencia DESIGN.md de ARCHITECTURE.md?

La diferencia principal es la audiencia. ARCHITECTURE.md suele estar escrito para humanos. DESIGN.md está optimizado para humanos y agentes: reglas más declarativas, invariantes explícitas y referencias desde archivos de instrucciones.

Muchos equipos usan un solo archivo con uno de los dos nombres. Lo importante es el contenido.

¿Qué tan largo debe ser DESIGN.md?

Lo suficiente para cubrir las decisiones que los agentes suelen romper. No más.

Como regla práctica: dos a cuatro páginas enfocadas funcionan mejor que una narrativa larga. Si una línea no contiene una decisión, invariante o justificación, probablemente sobra.

¿Cómo hago que el agente realmente lo lea?

Referéncialo desde el archivo que el agente carga al inicio.

Para Claude Code:

@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Para AGENTS.md:

Antes de cambios estructurales, lee `DESIGN.md`.
Enter fullscreen mode Exit fullscreen mode

No pegues todo el contenido dentro del archivo corto.

¿El agente siempre seguirá DESIGN.md?

No. Estos archivos son contexto, no restricciones impuestas por el runtime.

Por eso las reglas deben ser claras, absolutas y revisables. También ayuda añadir una instrucción explícita:

Si una tarea contradice este archivo, señala el conflicto antes de implementar.
Enter fullscreen mode Exit fullscreen mode

¿DESIGN.md ayuda con contratos API?

Sí. Uno de sus usos más valiosos en backend es declarar que la especificación OpenAPI es autoritaria.

Ejemplo:

`api/openapi.yaml` es la fuente de verdad.
No editar tipos generados.
Enter fullscreen mode Exit fullscreen mode

Diseñar ese contrato primero en una herramienta como Apidog le da al agente un objetivo claro.

¿Dónde debería vivir DESIGN.md?

En la raíz del repositorio, junto a README.md y AGENTS.md.

En monorepos, usa:

/DESIGN.md                  -> reglas globales
/services/payments/DESIGN.md -> reglas locales del servicio de pagos
/packages/sdk/DESIGN.md      -> reglas locales del SDK
Enter fullscreen mode Exit fullscreen mode

Así los agentes pueden leer el diseño global y el diseño más cercano al código que están modificando.

Top comments (0)