EARS + IA y LLMs

Por: Artiko
earsiallmclaudepromptingagentes

EARS + IA y LLMs

Los agentes de IA que generan código (Claude Code, Cursor, Aider, Codex, Goose) tienen un punto débil predecible: rinden tan bien como la claridad del requisito. Un requisito ambiguo produce código ambiguo, con suposiciones implícitas que después hay que descubrir y corregir.

EARS es, en la práctica, el mejor lenguaje natural para prompting de requisitos.

Por qué los LLMs aman EARS

  1. Patrones reconocibles: los LLMs detectan plantillas estructuradas mucho mejor que prosa.
  2. Disparadores explícitos: When, While, Where, If/Then les dicen al modelo cuándo aplicar cada bloque.
  3. Sujetos nombrados: el modelo sabe qué función/servicio/componente debe contener el código.
  4. Respuestas verificables: el modelo puede generar tests automáticamente porque el requisito describe el resultado esperado.
  5. Sin palabras tóxicas: nada de “apropiado”, “rápido”, “fácil” — el modelo no tiene que inventar valores.

Comparación: prompt vago vs prompt EARS

Prompt vago:

Necesito un endpoint de login que valide credenciales y devuelva un token.
Si las credenciales son malas, da un error apropiado.

Salida típica del modelo: código razonable pero con decisiones implícitas — qué duración tiene el token, qué algoritmo, qué código HTTP, qué estructura el body, qué pasa si el usuario no existe vs si la contraseña es incorrecta. El modelo elige por vos.

Prompt EARS:

Implementá los siguientes requisitos:

REQ-AUTH-001: When a POST request arrives at /auth/login with a JSON body containing "email" and "password", the auth service shall validate the credentials against the users repository.

REQ-AUTH-002: When the credentials are valid, the auth service shall return HTTP 200 with a JSON body containing { "token": <JWT> } where the JWT is signed with HS256 and expires in 24 hours.

REQ-AUTH-003: If the email is not present in the users repository, then the auth service shall return HTTP 401 with body { "error": "invalid_credentials" }.

REQ-AUTH-004: If the email is present but the password hash does not match, then the auth service shall return HTTP 401 with body { "error": "invalid_credentials" }. The response shall be indistinguishable from REQ-AUTH-003.

REQ-AUTH-005: The auth service shall not log credentials or tokens in any log line.

Stack: TypeScript, Hono, bcrypt, jose para JWT.
Arquitectura: hexagonal (puerto Repository, adaptador Postgres).

Salida del modelo: código preciso. Cada respuesta del endpoint corresponde a un requisito numerado. El modelo no tiene que adivinar.

El patrón “EARS + stack”

Para máxima precisión, los prompts deberían incluir:

  1. Requisitos en EARS (qué)
  2. Stack y restricciones (con qué)
  3. Convenciones del proyecto (cómo encajar en lo existente)
  4. Criterios de validación (cómo probar que está bien)
[EARS requirements]

Stack: <lenguaje, frameworks, librerías>
Arquitectura: <hexagonal/clean/MVC/...>
Convenciones: <naming, estructura de carpetas, patrones del proyecto>
Tests: <framework de testing, coverage objetivo>

EARS y plan de implementación

Antes de codear, pediúe al agente un plan derivado de los requisitos:

Antes de escribir código, generá un plan de implementación con:
- Archivos a crear/modificar
- Funciones o clases necesarias
- Mapeo de cada función a los REQ-* que cubre
- Tests a escribir (uno por REQ-*)

Esto fuerza al modelo a trazar cada línea de código a un requisito EARS. Si el modelo propone un archivo que no traza a ningún REQ, está sobre-construyendo.

EARS en archivos de contexto del agente

Herramientas como Claude Code, Cursor, OpenSpec, Spec-Kit cargan archivos de contexto (CLAUDE.md, AGENTS.md, cursor.rules, openspec/specs/). Los requisitos EARS persistidos ahí guían al agente sesión tras sesión.

Ejemplo specs/auth.md:

# Spec: Autenticación

## Requisitos

REQ-AUTH-001: When a user submits valid credentials to /auth/login, the auth service shall issue a JWT valid for 24 hours.

REQ-AUTH-002: If the credentials are invalid, then the auth service shall return HTTP 401 with body { "error": "invalid_credentials" } indistinguishably between "user not found" and "wrong password".

REQ-AUTH-003: While a session is active, when a request arrives with the JWT in the Authorization header, the auth middleware shall validate the JWT signature and shall populate `req.user` with the decoded claims.

REQ-AUTH-004: If the JWT signature is invalid or the token is expired, then the auth middleware shall return HTTP 401 and shall not invoke the downstream handler.

El agente puede leer este archivo en cada sesión y mantener consistencia.

EARS y testing generado por IA

Pediúe al agente que genere tests directamente de los requisitos:

Generá tests unitarios para el módulo de auth que verifiquen exactamente los REQ-AUTH-001 a REQ-AUTH-005. 
Cada test debe tener un comentario en el primer caso indicando qué REQ valida.
Usá Vitest + supertest.

El modelo va a generar tests donde cada uno tiene un mapeo claro a un requisito. Eso facilita revisar coverage funcional.

Spec-driven development con EARS

Frameworks como OpenSpec, Spec-Kit, BMAD y GSD estructuran el flujo así:

flowchart LR
    A[Idea/Feature] --> B[Explore]
    B --> C[Spec EARS]
    C --> D[Design]
    D --> E[Tasks]
    E --> F[Apply<br/>código generado]
    F --> G[Verify<br/>tests vs specs]
    G --> H[Archive]

Las specs en EARS son la fuente de verdad que sobrevive a múltiples sesiones del agente.

EARS y agentes autónomos de larga duración

Los agentes “always on” (harnesses) trabajan en background — picking tasks, ejecutándolas, reportando. Sin requisitos claros, divergen: empiezan a inventar features, hacer refactorings no pedidos, agregar tests “por las dudas”.

Los requisitos en EARS funcionan como rieles:

Antipatrones de prompting

- "Hacé el login que ya sabés."
+ "Implementá REQ-AUTH-001 a REQ-AUTH-005 como están definidos en specs/auth.md"

- "Quiero algo tipo Stripe checkout pero más simple."
+ "Implementá los siguientes 8 requisitos EARS [...]. El flujo es similar al checkout de Stripe pero solo soporta tarjeta y no soporta suscripciones."

- "Que el sistema sea seguro."
+ "Implementá los REQ-SEC-001 a REQ-SEC-014 [...]. Cubrí explícitamente: input validation (Valibot), rate limiting (5 req/min por IP), encrypted at rest (AES-256), HTTPS only, no logging de tokens/passwords."

EARS reduce hallucinations

Las “alucinaciones” de los LLMs son frecuentemente respuestas a la ambigüedad: cuando el modelo no tiene información suficiente, inventa. Si el prompt elimina ambigüedad — y EARS la elimina por construcción — las alucinaciones caen drásticamente.

Datos empíricos (Anthropic, OpenAI, Cursor) muestran que prompts estructurados reducen errores entre 30% y 60% comparado con prompts en prosa libre.

Workflow propuesto

  1. Escribir historia + AC en EARS durante refinamiento
  2. Guardar las specs EARS en el repo (/specs/<feature>.md)
  3. Promptear al agente referenciando los REQ-IDs
  4. Pedir un plan primero
  5. Aplicar el plan generando código + tests
  6. Verificar que cada REQ tiene un test que falla si el REQ se rompe
  7. Archivar la spec con el cambio

Resumen

En el siguiente capítulo vemos cómo derivar escenarios Gherkin directamente de requisitos EARS.