Cómo escribir una spec que el agente no malinterprete

“El usuario tiene que poder cancelar un pedido.” Se lo pasás al agente y a los diez minutos tenés la funcionalidad hecha. Anda.
Entonces aparecen las preguntas. ¿Se puede cancelar un pedido que ya salió del depósito? ¿La cancelación devuelve la plata sola o eso lo hace alguien a mano? ¿Se le avisa al cliente? ¿Qué pasa si cancela dos veces? ¿El stock reservado se libera en el momento o cuando alguien confirma? Ninguna de esas cosas estaba en la frase que escribiste, y todas están decididas en el código que acabás de recibir — porque el agente las resolvió solo, sin avisarte.
Esto es la parte práctica de trabajar con especificaciones: cómo se escribe una que no deje esos huecos. Si querés antes el panorama —qué resuelve el método, qué cuesta y cuándo conviene— está en el artículo anterior. Acá vamos directo a la escritura.
Una spec no es un documento largo
El error más común es medir la especificación por su extensión. Una spec de seis páginas escrita en prosa suelta puede tener los mismos huecos que la frase de arriba, y encima ahora hay que leerla entera para encontrarlos.
Lo que la hace buena no es cuánto dice, sino que cada afirmación sea verificable y no admita dos lecturas. Y hay una regla de corte que ordena todo: la spec dice qué tiene que pasar, nunca cómo se implementa. El cómo es la etapa siguiente. Si estás escribiendo nombres de funciones o decidiendo la estructura de la base de datos, te saliste.
Anatomía de una spec
Cinco partes, y ninguna es opcional:
1. Objetivo. Una o dos líneas: qué problema resuelve y para quién. Sirve para que, cuando aparezca una duda que la spec no cubre, haya un criterio para resolverla.
2. Alcance: lo que entra y lo que queda afuera. La segunda mitad es la que casi nadie escribe y la que más rinde. “La cancelación no modifica la facturación ya emitida” evita que el agente, tratando de ser completo, se meta a tocar el módulo de facturación.
3. Requisitos. El corazón, y donde entra la notación de la sección siguiente. Uno por línea, cada uno verificable por separado.
4. Casos borde y comportamiento no deseado. Qué pasa cuando algo sale mal, llega dos veces, o llega fuera de orden. Es lo que el agente rellena con suposiciones si no está.
5. Criterios de aceptación. Cómo se comprueba que está hecho. Si un requisito no se puede comprobar, o está mal escrito o no era un requisito.
Dónde vive cada cosa: AGENTS.md y la spec
Una confusión que hace perder tiempo: mezclar los dos documentos que lee el agente, que tienen vidas distintas.
AGENTS.md guarda las reglas permanentes del proyecto — los comandos,
las convenciones, las decisiones que ya se tomaron. Vale para cualquier tarea
y se escribe una vez. La spec describe un cambio concreto y vive lo que
dura ese cambio; cuando la funcionalidad está hecha, cumplió su función.
La regla para saber dónde va cada cosa es preguntarse si lo vas a repetir:
algo que tendrías que volver a escribir en la próxima especificación —que los
montos se guardan en centavos, que las fechas van en UTC— no es parte de esta
funcionalidad, es una regla del proyecto y va en AGENTS.md. Al revés
también: llenar el AGENTS.md con detalles de una feature lo infla y hace
que se diluyan las reglas que importan. Cómo escribirlo está en el artículo
del repositorio.
EARS: cinco plantillas para no dejar huecos
Acá está la herramienta más útil de todo esto, y no la inventó nadie de la IA. EARS —Easy Approach to Requirements Syntax— la creó Alistair Mavin con su equipo en Rolls-Royce, escribiendo los requisitos del control de un motor de avión, y la presentaron en la conferencia IEEE de ingeniería de requisitos en 2009. Existe desde mucho antes que los agentes, porque el problema que resuelve no es nuevo: que dos personas lean la misma frase y entiendan cosas distintas.
Son cinco plantillas de oración. Cada requisito entra en una:
Ubicua — vale siempre, sin condición.
El sistema debe registrar toda cancelación con usuario, fecha y motivo.
Cuando — respuesta a un disparador.
Cuando el usuario confirma la cancelación, el sistema debe liberar el stock reservado.
Mientras — vale durante un estado.
Mientras el pedido esté en preparación, el sistema debe permitir cancelarlo sin costo.
Donde — vale si una característica está presente.
Donde el pedido se haya pagado con tarjeta, el sistema debe iniciar la devolución automáticamente.
Si… entonces — comportamiento no deseado, el error y su manejo.
Si el pedido ya fue despachado, entonces el sistema debe rechazar la cancelación e informar que corresponde iniciar una devolución.
Esas cinco líneas responden todas las preguntas que quedaron abiertas en la frase del principio. Y fijate lo que pasó de paso: cada una se convierte en un test casi sin traducción, porque ya tiene la condición, la acción y el resultado esperado separados.
La regla de formación es simple: cero o más precondiciones, cero o un disparador, un solo sistema, una o más respuestas. Si una oración necesita dos disparadores, son dos requisitos.
Una aclaración honesta: EARS no viene integrado en las herramientas de spec-driven development —en spec-kit hay un pedido abierto para sumarlo—. Es una disciplina de escritura, no una función que se activa. Lo cual también quiere decir que podés usarla hoy sin instalar nada.
El modo plan: la forma más barata de empezar
Si todo lo anterior te parece mucho, hay una puerta de entrada que cuesta un atajo de teclado. En Claude Code es Shift+Tab; otras herramientas tienen su equivalente. El agente entra en modo plan: puede leer tu código pero no puede escribir nada.
Lo que cambia es la conversación. Sin poder tocar archivos, el agente se dedica a lo único que le queda: leer el proyecto, decirte qué entendió y preguntarte lo que falta. Esas preguntas son exactamente los huecos que, en modo normal, habría rellenado solo.
Es la forma más barata de conseguir casi todo el beneficio del método sin adoptar ninguna metodología: no escribís una spec, la redactás con él. Y si lo que te describe no es lo que tenías en la cabeza, lo corregís cuando cuesta una frase, no cuando cuesta veinte archivos.
El flujo completo, y por qué es un bucle
Si nunca lo hiciste, lo más confuso es que el flujo se enumera como una lista de siete pasos, pero no funciona como una lista. Dos cosas que conviene ver antes de los nombres: la constitución no forma parte del ciclo —se escribe una vez por proyecto y queda— y los otros seis se repiten.
Las dos etapas que más se saltean son justamente las que sostienen el ciclo. La clarificación es el momento en que el agente pregunta lo que la especificación no dice, en vez de asumirlo — es el paso donde se cazan los huecos mientras todavía son baratos. Y la validación es comprobar que lo implementado hace lo que la spec decía, no que “anda”: son cosas distintas, y sin criterios de aceptación escritos no hay contra qué comparar.
La pregunta práctica es cuándo termina, porque este bucle tiene una trampa: siempre hay algo para pulir, y el agente nunca te va a decir “ya está”. La regla de corte que funciona es una vuelta entera sin cambios. Si revisaste la especificación, el plan y la implementación y no tocaste nada, terminó. Si no la fijás explícitamente, el ciclo se sostiene solo por inercia y termina costando más que la funcionalidad.
Qué pedirle en cada paso
Hasta acá la teoría. Esto es lo que yo escribiría en cada etapa, con un ejemplo que se sigue de punta a punta: una CLI en Python para registrar horas trabajadas por proyecto. Lo que importa de estos pedidos no es la redacción sino las restricciones: son las que evitan que el agente se adelante.
Constitución. Se escribe una vez y define las reglas del proyecto.
Vamos a crear la constitución de un proyecto nuevo: una CLI en Python para
registrar horas trabajadas por proyecto. Proponeme un docs/constitution.md
con principios innegociables, cortos y verificables, que cubran:
simplicidad del stack, relación entre spec y código, separación entre
lógica e interfaz, política de tests, persistencia de datos, e idioma del
código y de los mensajes. Máximo 15 líneas. Esperá mi aprobación.
El tope de 15 líneas es lo que evita el documento inflado que después nadie lee. Y “esperá mi aprobación” te devuelve el control antes de que siga solo.
Especificación. El qué, nunca el cómo.
No escribas código en ningún momento. Vamos a redactar la especificación de
la primera funcionalidad. Leé docs/constitution.md.
Idea inicial: una CLI para empezar y frenar el registro de horas sobre un
proyecto, y ver el total por proyecto y por semana.
1. Hacéme preguntas de UNA EN UNA para eliminar ambigüedades: casos límite,
qué pasa ante errores, qué queda afuera del MVP. Máximo 6 preguntas.
2. Con mis respuestas, generá specs/001-horas/spec.md con: contexto y
objetivo, usuarios, historias de usuario, requisitos funcionales
numerados (RF-1, RF-2…) con criterios de aceptación en notación EARS,
requisitos no funcionales, casos límite, fuera de alcance, criterios de
finalización, y las dudas que queden marcadas [NECESITA ACLARACIÓN].
3. Solo el qué y el porqué. Nada de stack, arquitectura ni nombres de
archivos: eso va en el plan.
Lo de una pregunta por vez es la diferencia entre que contestes y que abandones: una lista de quince preguntas de golpe no la responde nadie. El tope de seis lo obliga a priorizar las que más ambigüedad sacan.
Ahí aparece la sigla que se usa en todos los pasos que siguen: RF es un requisito funcional, cada una de las cosas que el sistema tiene que hacer. Van numerados —RF-1, RF-2, y así— para poder señalarlos después sin transcribirlos: “el plan no cubre el RF-4” es una frase que se entiende sin volver a leer la especificación entera.
Clarificación. Buscar agujeros, todavía sin taparlos.
Revisá specs/001-horas/spec.md como si fueras alguien de QA muy exigente.
Listá: (1) ambigüedades que queden, (2) contradicciones entre requisitos,
(3) casos límite no cubiertos, (4) cosas que choquen con la constitución.
No propongas soluciones todavía: solo detectá.
“No propongas soluciones todavía” no es un capricho: si empieza a arreglar mientras busca, deja de buscar.
Plan técnico. Recién acá aparece el cómo.
Leé docs/constitution.md y specs/001-horas/spec.md. No escribas código.
Generá specs/001-horas/plan.md con: estructura de módulos, modelo de datos
con un ejemplo, contrato de la CLI (comandos, salidas, códigos de salida),
decisiones técnicas justificadas —con la alternativa que descartaste— y
estrategia de tests. Marcá qué RF cubre cada parte.
Pedir que marque qué requisito cubre cada parte convierte el plan en algo comprobable: si un RF no aparece en ningún lado, falta algo.
Tareas. Partir el plan en pasos que entren en una sentada.
A partir de spec.md y plan.md, generá specs/001-horas/tasks.md: tareas
chicas (20 a 30 minutos cada una), en orden de dependencia, cada una con los
RF que cubre y una línea "Hecho cuando:" verificable. Usá checkboxes.
El “Hecho cuando” es lo que impide que una tarea se dé por terminada por sensación en vez de por comprobación.
Implementación. De a una tarea, y frenando.
Implementá SOLO la tarea T2 de specs/001-horas/tasks.md, siguiendo plan.md
y la constitución. Escribí primero los tests y después el código. Corré
pytest -q y mostrame el resultado. Al terminar: marcá T2 en tasks.md, decime
qué RF cubre, y pará. No empieces T3.
Ese “pará, no empieces T3” es la restricción más importante de todas. Sin ella encadena tareas y terminás revisando seis cambios juntos, que es exactamente el problema que el método venía a evitar.
Validación. Contra la spec, no contra la impresión.
Recorré specs/001-horas/spec.md requisito por requisito. Para cada uno
decime qué test lo cubre y el resultado de ejecutarlo. Si alguno no está
cubierto o falla, decilo claramente. Después comprobá los criterios de
finalización y dame un veredicto: ¿la spec está cumplida?
La pregunta final es la que separa “anda” de “hace lo que la especificación decía”. Son dos cosas distintas y solo una está escrita.
Lo mínimo que cambia el resultado
No hace falta adoptar el flujo completo para que esto sirva. Si tuvieras que quedarte con dos cosas:
Escribí los requisitos con las plantillas. Convertir “el usuario tiene que poder cancelar un pedido” en cinco oraciones con cuando, mientras y si… entonces lleva cinco minutos y elimina la mayoría de las suposiciones antes de que existan.
Y no dejes que escriba hasta haber leído qué entendió. Sea con el modo plan o pidiéndoselo en una frase, es el punto de todo el método donde menos esfuerzo compra más.
Las dos se hacen sin instalar nada y sin adoptar ninguna metodología. Es, otra vez, la misma idea de siempre: lo que cuesta caro no es que el agente escriba mal, es que escriba bien algo que vos no pediste.
Comentarios
Iniciá sesión para comentar y dar "me gusta".
Todavía no hay comentarios. Sé la primera persona en escribir uno.