Spec-Driven Development: deja que la IA escriba el código, no los requisitos
En el artículo anterior de esta serie decía que el primer punto de aprobación en un pipeline de agentes — el que va justo después de la especificación — es el paso que la mayoría de equipos se salta primero, y el que más caro paga después. Aquí está el porqué, y lo que realmente debería llevar esa especificación.
Una petición vaga no es un atajo, es una decisión delegada
Hace unas semanas le pedí a un agente que "añadiese paginación al endpoint de la lista". Cinco palabras, treinta segundos escribirlas.
El agente eligió un tamaño de página. Eligió paginación basada en offset en lugar de cursor. Dio forma a la respuesta como le pareció que tenía sentido. Nada de eso estaba mal exactamente — simplemente no era lo que el equipo de frontend y yo habíamos hablado dos días antes, en una conversación completamente distinta que el agente nunca vio.
No había ahorrado treinta segundos. Simplemente había entregado una decisión a quien fuera que implementase la petición, y esta vez ese "quien fuera" era un agente que no tenía forma de saber que había una decisión que tomar.
Esa es la parte que se le escapa a la gente con los prompts vagos: no eliminan la ambigüedad, solo cambian quién la resuelve. Con un compañero humano, esa persona normalmente para y pregunta. Un agente, por defecto, elige algo plausible y sigue adelante.
Una especificación es un contrato, no papeleo
"Especificación" suena a documento que nadie lee. En la práctica, para una tarea que un agente está a punto de implementar, es más bien un contrato corto que ambas partes pueden exigirse:
- Objetivo — qué tiene que conseguir esto de verdad, no solo la petición de superficie.
- Criterios de aceptación — las condiciones concretas que deciden si está terminado.
- Casos esquina — estados vacíos, límites, acceso concurrente, todo lo que "lo normal" no cubre.
- Dependencias — qué APIs, módulos o datos toca, y qué no debería tocar.
- Restricciones — patrones existentes, componentes del design system, límites de arquitectura que debe respetar.
- Fuera de alcance — lo que esto no incluye explícitamente, para que nadie lo amplíe "ayudando".
Aquí es donde el contexto que describía en artículos anteriores deja de ser conocimiento general del proyecto y se convierte en algo específico de esta tarea concreta. El CLAUDE.md le dice a un agente cómo funciona el proyecto. Una especificación le dice qué se supone que tiene que hacer esta pieza de trabajo en particular.
Deja que la IA escriba el código, no que decida los requisitos
Esta es la línea que de verdad me importa, y es fácil que se difumine.
Un agente puede ayudar perfectamente a construir la especificación — convertir una petición en bruto en un borrador estructurado, sacar a la luz casos esquina que no se os habían ocurrido, listar dependencias que se os habían olvidado. Para eso está exactamente un Refiner Agent.
Lo que no debería hacer es resolver en silencio una pregunta abierta por su cuenta y pasar directamente a la implementación. Si no se había decidido el estilo de paginación, la salida correcta no es una suposición disfrazada de código — es una ambigüedad señalada, esperando respuesta.
El fallo no es "la IA escribió mal código". Es "la IA decidió algo que nadie le pidió que decidiera, y resultó que se equivocó".
Los casos esquina son más baratos en papel que en un diff
Escribir "¿qué pasa cuando la lista está vacía?" como una línea toma diez segundos.
Descubrir que el agente lo resolvió devolviendo null en silencio, tres archivos más adentro de un componente que a nadie se le ocurrió revisar, cuesta una sesión de debugging y una vuelta de PR.
Cada caso esquina que detectáis al escribir la especificación es una frase. Cada caso esquina que detectáis en la revisión es una conversación, un diff, y normalmente una reimplementación. La especificación no es trabajo extra pegado a la tarea "de verdad" — es el punto más barato de todo el proceso para detectar un problema.
Los tests deben remitirse a la especificación, no a la implementación
Hay una trampa sutil aquí: una verificación que solo comprueba la implementación contra sí misma no verifica nada. Si el agente escribe el código y luego escribe los tests para lo que hace ese código, ambos han estado moldeados por el mismo conjunto de suposiciones.
Los tests se ganan su sitio cuando se escriben contra los criterios de aceptación que existían antes de que existiera la implementación — no contra lo que el código acabó haciendo. Esa es la única versión de "pasa los tests" que de verdad significa que se cumplió la especificación, en lugar de significar que la implementación es coherente consigo misma y con sus propias suposiciones.
Conclusión
Spec-Driven Development no va de escribir más documentos. Va de decidir, a propósito, qué preguntas se responden antes de que exista código y cuáles estáis dispuestos a dejar en manos de la mejor suposición de un agente.
Una buena especificación no ralentiza al agente. Es lo que hace que su velocidad sea realmente útil, en lugar de rápida en una dirección que nadie pidió.
En el próximo artículo de esta serie lo haré práctico: Refiner, Implementer, Verifier: A Practical Multi-Agent Workflow — cómo ejecuto esto de verdad como tres pasadas separadas en lugar de tres buenas intenciones que intento sostener a la vez en la cabeza.
Hasta entonces, la pregunta que merece la pena hacerse antes de escribir el próximo prompt no es:
¿Puede el agente averiguar esto?
Es:
¿Hay una decisión escondida aquí que en realidad todavía no he tomado?
Si tenéis una plantilla de especificación o una configuración de Refiner que os funcione bien, me gustaría verla — no dudéis en escribirme.