Cómo escribir una spec para agentes de IA: plantilla, formato EARS y ejemplos
Una plantilla de spec para copiar y pegar, el formato EARS, el alcance negativo y la prueba de la niña lista: cómo escribir una especificación de requisitos con la que un agente de IA realmente pueda construir.
Una spec solo es buena si alguien sin nada de tu contexto puede leerla y construir lo correcto. Esa prueba es todo el trabajo.
Quien busca una “plantilla de spec” o una “especificación de requisitos de software” normalmente está resolviendo un problema de coordinación entre personas. Quiere un documento que alinee al equipo, consiga la aprobación de los stakeholders y sobreviva a un traspaso. El formato clásico de SRS del IEEE-830, con introducción, alcance, requisitos funcionales, requisitos no funcionales, especificaciones de interfaz y restricciones, se diseñó justo para eso. Y lo resolvió bastante bien.
El trabajo cambia cuando quien lee la spec es un agente de IA.
Un equipo humano arrastra contexto de una reunión a otra. Hace preguntas antes de empezar. Nota cuando algo se ve raro y te consulta. Un agente de IA no hace nada de eso. Empieza cada sesión sin ningún recuerdo de las conversaciones que tuvieron, sin memoria de las decisiones que tomaste la semana pasada y sin intuición alguna sobre tus reglas de negocio implícitas. Todo lo que el agente necesita saber tiene que estar en el documento.
Anthropic dice cuál es el objetivo sin rodeos en sus Claude Code best practices: “las specs más útiles son autocontenidas: nombran los archivos y las interfaces involucradas, dicen qué queda fuera del alcance y terminan con un paso de verificación de punta a punta que demuestra que la feature funciona.” Esa es la vara. El resto de este texto es cómo pasarla.
La mayoría de quienes prueban Spec-Driven Development ya entiende el porqué. Leyó qué es Spec-Driven Development, cree que la spec es el artefacto correcto para darle a un agente de IA, y entonces abre un archivo en blanco y escribe: “El sistema debe manejar la autenticación de usuarios de forma segura.” Después no entiende por qué el resultado sigue saliendo mal.
El problema no es la falta de compromiso. Escribir una buena spec es una habilidad en sí misma, y casi nada la enseña. Este artículo cubre la prueba de calidad de una spec, el formato de frase que cierra la ambigüedad, lo que tienes que excluir de forma explícita, un ejemplo completo de una fintech real y una plantilla para copiar y pegar.
Es el complemento práctico de Spec-Driven Development con Claude Code y del caso de estudio que muestra lo que estos documentos producen a escala.
La única prueba de una buena spec
La prueba va antes que cualquier plantilla.
No le dirías: “Haz eso de las tareas.”
Le dirías: “Cuando alguien crea una tarea, guarda el título, verifica que la persona tenga permiso en ese workspace y envía una notificación en tiempo real a todos los que estén viendo esa lista en ese momento.”
Ese nivel de especificidad es la spec. El agente no es poco inteligente: simplemente no tiene contexto entre sesiones. Cada conversación empieza de cero. La spec es la única memoria que recibe.
El principio no se trata de simplificar de más. Obliga a que cada regla implícita salga a la luz. “Verificar permisos” es fácil de decir en una conversación. En una spec tienes que escribir: ¿qué permisos? ¿En qué operaciones? ¿Qué pasa si falla: rechazo silencioso o respuesta de error? ¿La verificación de permisos va antes o después de validar el input? Cada una es una pregunta que el agente va a responder de alguna forma. El principio es cómo controlas esas respuestas.
Sé específico, no genérico
Los requisitos vagos son donde los agentes alucinan alcance. La solución es la precisión.
Vago vs. ejecutable
| Vago: el agente adivina | Ejecutable: el agente sabe |
|---|---|
| "El sistema debe ser rápido." | GET /api/v1/tasks responde en menos de 500ms en p95 para listas de hasta 1.000 tareas. |
| "Valida el título." | Vacío → "Title is required"; 1 carácter → "Min 2 characters"; 501 caracteres → "Max 500". |
| "Maneja los errores con elegancia." | Si el proveedor da timeout, reintenta 3 veces con backoff exponencial y luego lo encola para revisión manual. |
| "La UI debe verse limpia." | La lista de tareas renderiza en menos de 200ms. Skeleton durante la carga. Estado vacío: "No tasks yet. Create one." |
La pregunta correcta para cada requisito: “Si le diera esta línea a alguien sin contexto, ¿podría implementarla sin hacer ninguna otra pregunta?” Si la respuesta es no, hazla más específica. Los adjetivos (rápido, limpio, seguro, robusto) no son requisitos. Son una invitación para que el agente los llene con sus propios supuestos.
Declara el alcance negativo
Lo que explícitamente no vas a construir importa tanto como lo que sí. Es la mejor defensa contra un agente que, “con toda la buena intención”, agrega features que nunca pediste.
Escríbelo como una lista simple, al principio del documento. Llama a la sección “Non-Goals” u “Out of Scope”. Sé directo:
## Non-Goals (v1)
- No recurring tasks
- No calendar integration (planned v2)
- No time tracking
- No task dependencies, subtasks only, max 50 per task
- No bulk operations (multi-select, bulk delete)
- No offline mode
Esta sección evita un tipo de error que es invisible hasta que sale caro: el agente extiende el modelo de datos para una feature que no querías, y ahora llevas tres horas refactorizando algo que nunca pediste construir.
Empecé a agregar una justificación de una línea a cualquier ítem que pueda parecer un olvido. “Sin registro de horas. El producto no compite en analytics.” Esa línea cierra un hueco que el agente podría llenar con la respuesta equivocada.
Los ejemplos concretos le ganan a los adjetivos
Las reglas de validación abstractas se implementan mal una y otra vez. Los ejemplos concretos, no.
No escribas “validar el título de la tarea de forma adecuada”. Escribe una tabla:
Campo de título: ejemplos de validación
| Input | Resultado esperado |
|---|---|
| "" (string vacío) | Error: "Title is required" |
| "A" (1 carácter) | Error: "Title must be at least 2 characters" |
| "Review PR #123" (válido) | Éxito: título guardado |
| "A" × 501 (501 caracteres) | Error: "Title must be 500 characters or fewer" |
| " " (solo espacios) | Error: "Title is required" (trim antes de validar) |
Esa última fila es la que muerde siempre. Ningún agente la va a agregar si no la agregas tú, porque nada en “validar el título de la tarea” implica hacer trim antes de validar. Los ejemplos concretos convierten la interpretación en verificación: el agente produce la salida exacta para ese input, o no.
Este patrón sirve para cualquier validación, cualquier máquina de estados, cualquier flujo condicional. Piensa en pares de input/output y escribe los pares. Es la forma más directa de especificar comportamiento.
Escribe los requisitos en EARS
Los requisitos en lenguaje natural suenan razonables hasta que los implementas. “El sistema debe validar los permisos del workspace.” ¿En qué operaciones? Si falla, ¿rechaza en silencio o lanza un error? ¿Antes o después de validar el input?
EARS (Easy Approach to Requirements Syntax) cierra ese hueco. Alistair Mavin lo desarrolló en Rolls-Royce PLC mientras analizaba regulaciones de aeronavegabilidad para el sistema de control de un motor a reacción. Se publicó por primera vez en 2009 y hoy lo usan Airbus, NASA, Intel y Bosch. Encaja casi perfecto con lo que necesitan los agentes de IA: frases sin ambigüedad, ejecutables por una máquina, con disparadores y condiciones explícitos.
Los seis patrones de EARS
| Patrón | Plantilla | Ejemplo |
|---|---|---|
| Ubicuo | THE SYSTEM SHALL [acción]. | THE SYSTEM SHALL validar los permisos del workspace en cada operación sobre tareas. |
| Dirigido por eventos | WHEN [disparador], THE SYSTEM SHALL [respuesta]. | WHEN se completa una tarea, THE SYSTEM SHALL registrar el timestamp y el usuario que la completó. |
| Dirigido por estado | WHILE [estado], THE SYSTEM SHALL [restricción]. | WHILE una tarea está archivada, THE SYSTEM SHALL NOT permitir ediciones. |
| Comportamiento no deseado | IF [condición no deseada], THE SYSTEM SHALL [mitigación]. | IF se crean más de 50 subtareas, THE SYSTEM SHALL mostrar "Subtask limit reached" y rechazar la operación. |
| Opcional | WHERE [feature flag / config], THE SYSTEM SHALL [comportamiento]. | WHERE las notificaciones están activadas, THE SYSTEM SHALL notificar a todos los asignados cuando una tarea cambia de estado. |
| Complejo | WHEN [evento] AND [condición], THE SYSTEM SHALL [A] BEFORE [B]. | WHEN se completa una tarea AND hay una regla de automatización configurada, THE SYSTEM SHALL ejecutar la automatización BEFORE actualizar el estado de la tarea. |
No usas los seis en cada requisito. Elige el patrón según el tipo de requisito. Una invariante constante es Ubicuo. Una acción del usuario es Dirigido por eventos. Una condición de guarda es Dirigido por estado. Elige la plantilla, llena los huecos y la ambigüedad desaparece.
Una nota práctica sobre el vocabulario: EARS usa SHALL (comportamiento obligatorio) y SHALL NOT (comportamiento prohibido). Mapéalos directo a MoSCoW: SHALL = Must Have, SHOULD = Should Have, MAY = Could Have. No los suavices. “The system should validate permissions” no es el mismo requisito que “THE SYSTEM SHALL validate permissions.” El primero le da al agente una salida. El segundo, no.
La técnica del Implementation FAQ
Antes de que tu agente vea la spec, pregúntate: ¿qué va a tener que adivinar?
Lista cada ambigüedad y respóndela en la spec, en una sección explícita de preguntas y respuestas. Llámala “Implementation FAQ” u “Open Questions”. Cada hueco que sacas a la luz se convierte en una decisión que tomaste a propósito, y no en un supuesto equivocado metido en silencio en el código.
Así se ve para una feature de gestión de tareas:
## Implementation FAQ
**Q: What happens when a user tries to delete a task that has subtasks?**
A: Cascade delete all subtasks. Prompt for confirmation:
"This will also delete 3 subtasks. Continue?" Require explicit
confirmation before proceeding.
**Q: Who can see unassigned tasks?**
A: All members of the workspace, regardless of role. Only workspace
owners can assign tasks to others.
**Q: What happens if an assignee is removed from a workspace while they
have open tasks?**
A: Tasks remain open. The assignee field becomes null. A system
notification is sent to the workspace owner listing affected tasks.
**Q: Can a task belong to more than one project?**
A: No, one task belongs to exactly one project. This is a v1
constraint, not a design choice to revisit.
**Q: What timezone is used for due dates?**
A: Store as UTC. Display in the authenticated user's profile timezone.
If no timezone is set, display UTC with a "(UTC)" label.
Las entradas que más necesitas son las que quedan fuera del camino feliz: borrado en cascada, estados en conflicto, usuarios eliminados, zonas horarias, ediciones concurrentes. Son justo los casos que los agentes peor resuelven cuando los dejas adivinar, porque los datos de entrenamiento están saturados de implementaciones del camino feliz y casi vacíos de edge cases.
Escribo el FAQ imaginando al agente en plena implementación, llegando a un punto de decisión sobre el que la spec no dice nada. ¿Qué haría? Esa situación va al FAQ, con la respuesta correcta al lado.
Del SRS a la spec para agentes de IA
La especificación de requisitos de software clásica tenía cinco secciones principales: introducción, descripción general, requisitos funcionales, requisitos no funcionales e interfaces externas. Los equipos las escribían en prosa, organizada por feature. Esa estructura sigue siendo el esqueleto correcto. Lo que cambia con los agentes de IA no es la forma, sino los supuestos que hay debajo.
Un SRS tradicional podía contar con contexto compartido. Cada ingeniero del equipo había estado en las sesiones de planificación. Conocía la historia del producto. Hacía preguntas en la daily. El conocimiento implícito no hacía falta escribirlo porque vivía en la cabeza de la gente. Un agente de IA no tiene nada de eso. Si tu spec dice “validar permisos”, el agente no puede preguntarte qué quisiste decir. Adivina y sigue.
Tres cambios hacen que el SRS sea ejecutable por un agente, y no solo legible por un equipo.
Primero, EARS cierra la ambigüedad a nivel de frase, algo que el IEEE-830 nunca abordó. El estándar decía que “los requisitos deben ser inequívocos”. EARS te da la gramática para imponerlo frase por frase: WHEN, WHILE, IF, WHERE, SHALL.
Segundo, el alcance negativo te protege de agregados plausibles. Un equipo humano sabe lo que no está construyendo porque estuvo en la sala cuando se tomó la decisión. El agente no estuvo. Una sección “Out of Scope” explícita es obligatoria, no opcional.
Tercero, una línea final de “Confirm before building” frena a un agente ansioso antes de que se lance al código sin verificar lo que entendió. Terminas la spec pidiéndole al agente que reformule los requisitos clave con sus propias palabras antes de escribir un solo carácter de código. Si entendió algo mal, te enteras a costo cero, no después de tres sesiones de implementación.
Todo lo demás del SRS clásico, los IDs de trazabilidad, los criterios de aceptación, la sección de restricciones, la tabla de riesgos, se transfiere tal cual. La estructura estaba bien. Cambió el lector.
Una spec que nunca puede cobrar dos veces
La mejor forma de ver cómo se combinan estas técnicas es un caso real y difícil. Esto es muy parecido a la spec que escribí para la fintech cripto: un endpoint de cobro en el que un reintento nunca puede cobrarle dos veces al cliente.
# Spec: Create a payment charge (POST /v1/charges)
# Status: requirements:approved
## Overview
A merchant creates a charge against a customer. This moves money, so it
must be safe to retry and impossible to double-bill.
## In scope
- Create a charge from an authenticated merchant request.
- Return the charge id and status.
- Guarantee exactly-once billing under client retries.
## Out of scope (v1)
- Refunds (separate spec: 005-refunds).
- Partial captures.
- Multi-currency. All amounts are BRL, stored as integer cents. Never float.
## Functional requirements (EARS)
- FR-1 WHEN a merchant POSTs a charge with a valid Idempotency-Key,
THE SYSTEM SHALL create at most one charge for that key.
- FR-2 WHEN the same Idempotency-Key is replayed within 24h,
THE SYSTEM SHALL return the original charge and create no new one.
- FR-3 IF the amount is <= 0,
THE SYSTEM SHALL reject with 422 "amount must be positive".
- FR-4 IF the merchant is over its rate limit,
THE SYSTEM SHALL reject with 429 and a Retry-After header.
- FR-5 WHILE a charge is pending,
THE SYSTEM SHALL NOT allow a second capture.
## Acceptance criteria (examples the agent must satisfy)
- amount=1000, key=abc -> 201, status=pending
- same key=abc, replayed -> 200, same charge id, no new row
- amount=0 -> 422 "amount must be positive"
- amount=-50 -> 422 "amount must be positive"
- 6th request in 1s, one merchant -> 429, Retry-After: 1
## Non-functional
- p95 latency under 300ms at 200 requests/sec per merchant.
- Every money value is an integer. No floating point anywhere in the path.
## Data
- charges(id, merchant_id, amount_cents, currency, status,
idempotency_key, created_at)
- UNIQUE(merchant_id, idempotency_key) # this is what enforces FR-1
## Verification
- Integration test replays one key 50x concurrently; assert exactly one
row and one ledger entry.
- Load test holds p95 < 300ms at 200 rps.
## Confirm before building
Do not write code until you restate FR-1 through FR-5 and the uniqueness
constraint in your own words. If any acceptance criterion is ambiguous,
ask before implementing.
Veamos por qué cada parte se gana su lugar.
“Out of scope” nombra lo que esta spec no cubre. Sin eso, el agente podría extender la tabla de cobros con una columna refund_amount porque los reembolsos parecen relacionados. Son columnas extra, archivos de migración y un modelo de datos ahora acoplado a una feature que todavía no especificaste.
FR-1 y FR-2 juntos especifican la idempotencia desde los dos lados: al recibirlo por primera vez, crea un cobro; en el replay, devuelve el original. Decirlo dos veces cierra el hueco en ambas direcciones. Una sola frase EARS no alcanza aquí, porque las dos situaciones (primera llamada vs. llamada repetida) producen respuestas HTTP distintas.
FR-3 y FR-4 son el patrón de “comportamiento no deseado”. Especifican lo que el sistema tiene que hacer cuando algo sale mal. Sin ellos, el agente elige sus propias respuestas de error. A veces 400, a veces 500, a veces nada.
La sección de criterios de aceptación no es un archivo de tests. Es una tabla de pares input/output que vive en la spec para que el agente verifique su propio trabajo antes de que tú revises nada. Cada fila es una comprobación que el agente puede ejecutar.
“Every money value is an integer. No floating point anywhere in the path.” Esa sola frase evita el error de redondeo de punto flotante que le pega a un sistema de pagos al segundo día en producción. Vive en la spec y no en un comentario de código, porque los comentarios no sobreviven al cambio de sesión.
La constraint UNIQUE del modelo de datos es lo que de verdad garantiza el FR-1. Si la dejas fuera, el agente puede implementar la idempotencia en la lógica de la aplicación. La lógica de la aplicación falla con reintentos concurrentes. La constraint de la base de datos, no.
“Confirm before building” es la última línea. El agente reformula FR-1 a FR-5 con sus propias palabras antes de escribir un carácter de código. Si entendió mal el FR-2, te enteras ahora, a costo cero. Sáltate esa línea y te enteras después de la implementación.
Tres documentos, no uno
La spec de una feature real no es un documento. Son tres, y tienen un orden estricto.
Carpeta de spec de la feature
- spec/
- tasks-feature/
- .statusgate// requirements:draft → approved, design:draft → approved, tasks:draft → approved
- requirements.md// QUÉ: aprobado antes de que empiece el diseño
- design.md// CÓMO: aprobado antes de que empiecen las tareas
- tasks.md// CUÁNTO: aprobado antes de que empiece la implementación
El archivo .status es el gate. El agente lo lee al inicio de cada sesión. Si dice requirements:draft, no avanza ningún trabajo de diseño. Cada documento forma parte de una cadena de dependencias: el diseño mapea a los requisitos, las tareas mapean al diseño. Si escribes los tres de una vez sin los gates de aprobación, te queda un waterfall. Con los gates, tienes iteración deliberada, donde cada fase se cierra antes de que se abra la siguiente.
requirements.md: QUÉ
Es el documento que escribes primero y el único que le pasas a un stakeholder no técnico para revisar. Se mantiene independiente de la tecnología.
Secciones: Overview, Goals, Non-Goals, User Stories (US-001…) con criterios de aceptación, Functional Requirements (FR-001… en EARS con prioridad MoSCoW), Non-Functional Requirements (NFR-001…), Constraints, Decisions (D-001…), Implementation FAQ (Q-001…), Success Metrics, Risks.
Estos IDs (US-001, FR-001, NFR-001, D-001) son cómo el diseño se conecta con los requisitos, cómo las tareas se conectan con el diseño y cómo respondes “¿por qué existe este código?” seis meses después sin leer toda la codebase. Nunca te los saltes.
design.md: CÓMO
Es el documento técnico. Cada requisito funcional tiene que tener una decisión de diseño correspondiente. Si un requisito no mapea al diseño, o el diseño está incompleto, o el requisito no hace falta implementarlo.
Secciones: Executive Summary (la arquitectura en dos frases), Requirements Mapping (tabla explícita: a qué sección del diseño mapea el FR-001), System Architecture, Data Model, API Contract, Edge Cases, Testing and Verification Strategy, Technical Decisions (TD-001… con alternativas consideradas y justificación), Risks.
La tabla de mapeo de requisitos es la sección más importante y la que más se salta. Obliga a una comprobación: cada FR tiene que tener un lugar en el diseño. Cualquier FR sin mapeo es un hueco, y un hueco en el diseño es un hueco en el código.
tasks.md: CUÁNTO
Es lo que el agente implementa, una tarea a la vez. Las tareas duran entre 2 y 4 horas cada una. Lo que sea más grande se divide.
Secciones: Requirement Coverage (trazabilidad de FR a tareas), Implementation Readiness Check (un gate de pasa/no pasa: ¿están aprobados los requisitos y el diseño? ¿están respondidos todos los ítems Q-001?), Tasks, cada una con título, referencia al requisito (FR-003), archivos que toca, tamaño estimado, dependencias de otras tareas, criterios de aceptación y comandos de verificación.
Los criterios de aceptación de cada tarea son lo que el agente ejecuta para verificar su propio trabajo antes de marcar la tarea como terminada. Si no están, el agente declara victoria según le parezca que el código se ve bien, no según si realmente funciona.
La plantilla de requirements.md
Ponla en la carpeta de la feature, completa cada sección y pásasela al agente. Es la estructura exacta que uso en cada feature.
# [Feature Name], Requirements
**Status:** draft
**Version:** 1.0
**Author:** [name]
**Date:** [YYYY-MM-DD]
---
## Overview
[One paragraph: what this feature does, why it exists now, and who it's for.]
## Goals
- [Measurable goal 1, e.g., "Users can create and assign tasks in under 30 seconds."]
- [Measurable goal 2]
- [Measurable goal 3]
## Non-Goals (v1)
- [Thing you will NOT build, be explicit]
- [Another thing out of scope, add rationale if the omission might look like a mistake]
- [Third item]
## User Stories
### US-001: [Story title]
**As a** [persona],
**I want to** [action],
**so that** [benefit].
**Acceptance criteria:**
- [ ] [Observable, testable criterion]
- [ ] [Observable, testable criterion]
- [ ] [Edge case criterion]
### US-002: [Story title]
[Repeat structure]
---
## Functional Requirements
### FR-001, [Requirement name] [Must Have]
THE SYSTEM SHALL [specific, unambiguous behavior].
**Priority:** Must Have
**User story:** US-001
**Notes:** [Any clarification or related constraint]
### FR-002, [Requirement name] [Must Have]
WHEN [trigger], THE SYSTEM SHALL [response].
**Priority:** Must Have
**User story:** US-001
### FR-003, [Requirement name] [Should Have]
WHILE [state], THE SYSTEM SHALL NOT [prohibited action].
**Priority:** Should Have
**User story:** US-002
### FR-004, [Requirement name] [Must Have]
IF [unwanted condition], THE SYSTEM SHALL [mitigation].
**Priority:** Must Have
**User story:** US-001
### FR-005, [Requirement name] [Could Have]
WHERE [feature flag / config], THE SYSTEM SHALL [behavior].
**Priority:** Could Have
**User story:** US-002
### FR-006, [Requirement name] [Must Have]
WHEN [event] AND [condition], THE SYSTEM SHALL [A] BEFORE [B].
**Priority:** Must Have
**User story:** US-001
[Continue with FR-007, FR-008...]
---
## Non-Functional Requirements
### NFR-001, Performance
THE SYSTEM SHALL respond to [specific endpoint or operation] in under
[X]ms at p95 for [load condition, e.g., "lists up to 1,000 tasks"].
### NFR-002, Security
THE SYSTEM SHALL [specific security behavior, e.g., "validate a signed
JWT on every mutation before any business logic runs"].
### NFR-003, Accessibility
THE SYSTEM SHALL meet WCAG 2.1 AA for all new UI components in scope.
---
## Constraints
- **Technology:** [e.g., "Must use the existing PostgreSQL instance, no new databases."]
- **Timeline:** [e.g., "Must ship before [date] to support [event]."]
- **Compliance:** [e.g., "All PII fields must be encrypted at rest."]
- **Integration:** [e.g., "Must call the existing notification service via its current API, no schema changes."]
---
## Decisions
### D-001: [Decision title]
**Decision:** [What was decided]
**Rationale:** [Why, include what problem it solves]
**Alternatives considered:** [What else was evaluated and why it was rejected]
**Date:** [YYYY-MM-DD]
---
## Implementation FAQ
**Q: [Anticipated ambiguity 1, focus on edge cases and deletion behavior]**
A: [Explicit answer, no hedging, no "it depends"]
**Q: [Anticipated ambiguity 2, conflicting states, concurrent operations]**
A: [Explicit answer]
**Q: [Access / visibility edge case]**
A: [Explicit answer, who sees what under which conditions]
**Q: [Timezone / locale / formatting question if relevant]**
A: [Explicit answer, specify storage format and display format separately]
---
## Success Metrics
- [ ] [Metric 1, e.g., "P95 latency for task list under 500ms in staging under 1,000-task load."]
- [ ] [Metric 2, user-observable outcome if no instrumentation exists]
- [ ] [Metric 3]
---
## Risks
| Risk | Likelihood | Impact | Mitigation |
| -------- | ---------------- | ---------------- | ------------ |
| [Risk 1] | Low / Med / High | Low / Med / High | [Mitigation] |
| [Risk 2] | | | |
Antes de pasarle la spec al agente
Gate de preparación de la spec
- Obligatorio:Pasa el principio de la niña lista: alguien sin contexto puede construir lo correcto a partir de esto.Si tendrías que explicar de palabra algo que no está en el documento, el documento no está terminado.
- Obligatorio:Cada requisito funcional está en formato EARS.Si escribiste 'debe ser rápido' o 'manejar los errores con elegancia', búscalo y reemplázalo.
- Obligatorio:Los Non-Goals son explícitos: al menos 3 cosas que no vas a construir.La ausencia de una sección de Non-Goals es un riesgo de alcance, no una spec limpia.
- Obligatorio:Las reglas de validación tienen tablas de ejemplos de input/output.Las reglas de validación en prosa casi siempre quedan subespecificadas. Las tablas cierran el hueco.
- Obligatorio:Todas las User Stories tienen criterios de aceptación testeables.Si un criterio no se puede testear de forma independiente, es un objetivo vago, no un requisito.
- Obligatorio:Existen IDs estables y únicos: US-001, FR-001, NFR-001, D-001.Los vas a referenciar en design.md y tasks.md. Sin IDs, se rompe la trazabilidad.
- Obligatorio:El Implementation FAQ cubre los 3 edge cases principales.Como mínimo: el borrado en cascada, el escenario de estados en conflicto y cualquier edge case de control de acceso.
- Obligatorio:Los requisitos de rendimiento tienen números, no adjetivos.'Rápido' no es un requisito. '500ms en p95 para listas de hasta 1.000 tareas' sí lo es.
- Obligatorio:La spec termina con una línea de 'Confirm before building'.El agente reformula los requisitos clave con sus propias palabras antes de escribir código. Si entendió algo mal, te enteras ahora, no después.
- Obligatorio:El archivo .status dice 'requirements:draft' hasta que lo revises y lo apruebes.Draft no es aprobado. El agente no debe pasar al diseño con una spec en draft.
- Obligatorio:Los requisitos no funcionales cubren rendimiento, seguridad y accesibilidad.Son las tres secciones que más faltan en los primeros borradores.
FAQ
¿Qué tan largo debe ser un requirements.md?
Lo bastante largo para evitar supuestos equivocados y lo bastante corto para que se siga manteniendo. Una feature típica de producción queda entre 400 y 800 líneas, contando el boilerplate de la plantilla.
Si pasas de 1.000 líneas, pregúntate si es una feature o dos. Si estás por debajo de 200, pregúntate si de verdad respondiste las preguntas difíciles o solo escribiste las preguntas.
¿Necesito los tres documentos para cada feature?
Para un script descartable o un arreglo de dos horas, no. Manda el prompt y listo. El overhead no vale la pena.
Para cualquier cosa que abarque varias sesiones, implique decisiones reales de arquitectura o maneje datos que no puedes reescribir fácilmente, los tres se pagan solos. El design.md evita los errores más caros; el tasks.md evita el mayor desperdicio de esfuerzo de implementación.
¿Cuál es la diferencia entre Non-Goals y Constraints?
Los Non-Goals son features que eliges no construir en esta versión: 'sin tareas recurrentes'. Las Constraints son los límites dentro de los que tienes que trabajar: 'hay que usar la base de datos existente, sin servicios nuevos'.
Los Non-Goals protegen el alcance. Las Constraints le dan forma al espacio de soluciones. Ambos van en los requisitos, en secciones separadas.
¿Puedo usar esta plantilla con agentes que no sean Claude Code?
Sí. El formato es markdown plano. Cualquier agente que pueda leer archivos se beneficia de esta estructura: Cursor, Copilot, GPT-4o en un custom GPT, Gemini. La sintaxis EARS y los IDs estables no dependen del modelo.
El archivo de gate .status es propio del workflow de SDD que uso, pero los documentos en sí funcionan con cualquier agente capaz.
Mi equipo escribe specs en Confluence o Notion. ¿Tengo que pasarme a archivos markdown?
No necesariamente. El valor está en la estructura y el contenido, no en el formato. Puedes escribir una spec en Notion y pegarla en el contexto del agente al inicio de cada sesión.
La razón por la que uso archivos markdown en el repo es la trazabilidad: la spec vive al lado del código que gobierna, se versiona en git junto con él y el agente la lee directamente, sin copiar y pegar. Ese último punto importa más de lo que parece. La fricción es lo que hace que las specs se salten.
¿Cómo manejo un requisito que cambia a mitad de la implementación?
Actualiza el requirements.md, agrega una nota de cambio con la fecha, vuelve a poner el .status en 'requirements:draft' y apruébalo de nuevo antes de que el agente continúe.
La disciplina es: nunca dejes que el agente implemente a partir de una spec que no volviste a leer desde el cambio. Un requisito modificado que no se propaga al diseño crea una contradicción entre lo que hace el código y lo que dice la spec. Tu yo del futuro va a tener que desenredarlo en frío.
¿Y si no sé todas las respuestas cuando escribo la spec?
Escribe lo que sí sabes y pon las preguntas abiertas de forma explícita en la sección de Implementation FAQ, marcadas como abiertas, no respondidas. Sigue siendo mejor que el silencio, porque el agente ve la pregunta y sabe que tiene que preguntar en vez de adivinar.
Después resuélvelas antes de aprobar la spec. Una pregunta abierta en una spec aprobada es un bug diferido.
Por dónde seguir
Una buena spec lleva entre 30 y 90 minutos de escritura para una feature típica. Ese tiempo vuelve en la primera sesión de implementación: lo dedicas a problemas que son difíciles de verdad, no a depurar requisitos mal entendidos.
La newsletter
Don’t Code, Specify. Cada semana, agentes de IA en producción de verdad. Sin hype: lo que funcionó y lo que se rompió.
Suscríbete en Substack (se abre en una pestaña nueva)