- Frente a la afirmación de que con la programación agéntica “la documentación de especificación puede sustituir al código”, se señala una limitación fundamental: si la especificación se vuelve lo bastante precisa, inevitablemente termina convergiendo a una forma idéntica al código
- Al observar el proyecto Symphony de OpenAI, su archivo SPEC.md no es realmente una especificación, sino prácticamente pseudocódigo en formato Markdown
- De hecho, al intentar una implementación en Haskell basada en la especificación de Symphony, surgieron numerosos bugs y problemas de confiabilidad, como esperas infinitas del agente
- El trabajo de especificación originalmente exige un pensamiento más profundo que programar, pero dentro de la actual cultura de optimización por velocidad en la industria, se termina produciendo en masa documentación de baja calidad generada por IA
- El principio de “garbage in, garbage out” se aplica exactamente igual a los agentes de programación, y con documentos sin claridad ni detalle es imposible generar código confiable
Dos malentendidos sobre la programación agéntica
- Existen dos malentendidos clave en los que se apoyan los defensores de la programación agéntica
- Malentendido 1: un documento de especificación es más simple que el código correspondiente — una visión de tercerización según la cual se puede convertir a los ingenieros en gestores que redactan especificaciones y delegan el trabajo a un equipo de agentes
- Malentendido 2: el trabajo de especificación es necesariamente más reflexivo que programar — la idea de que pasar por documentos de especificación mejora la calidad y fomenta mejores prácticas de ingeniería
Código disfrazado de especificación: análisis del caso Symphony
- El proyecto Symphony de OpenAI se presenta como un orquestador de agentes generado a partir de un documento de especificación (SPEC.md), pero en la práctica el contenido real de SPEC.md se parece más a pseudocódigo en Markdown que a una especificación
- Tipos de contenido incluidos en SPEC.md:
- Volcado en prosa del esquema de base de datos — enumeración de campos como
session_id, thread_id, codex_input_tokens, etc.
- Transformación en prosa del código — fórmulas como
available_slots = max(max_concurrent_agents - running_count, 0) para control de concurrencia, y la fórmula de backoff para reintentos (delay = min(10000 * 2^(attempt-1), agent.max_retry_backoff_ms))
- Secciones redundantes añadidas explícitamente para ayudar al modelo a generar código, como "Config Fields Summary (Cheat Sheet)"
- Secciones de "Reference Algorithms" que son, en la práctica, código en sí mismo, como la función
start_service()
- Sostener que el documento de especificación sustituye al código cuando en realidad ese documento se lee como código es engañoso
- Para que un documento de especificación sea lo bastante preciso, inevitablemente debe transformarse a una forma de código o redactarse en un inglés formal altamente estructurado
El argumento de la “interfaz estrecha” de Dijkstra
- Citando a Dijkstra, se señala que elegir una interfaz no es una simple división del trabajo, porque además añade el costo de colaboración y comunicación a través de esa interfaz
- Se presentan ejemplos históricos: la matemática griega se estancó al permanecer en actividades lingüísticas y visuales; el álgebra islámica decayó al volver a un estilo retórico; y Europa occidental progresó al salir de los “vanos intentos de precisión lingüística” de la escolástica medieval, gracias a sistemas simbólicos formales como los de Vieta, Descartes, Leibniz y Boole
- Los programadores agénticos no pueden evitar la “interfaz estrecha” (= código) que exige el trabajo de ingeniería; solo pueden transformar ese trabajo a una forma que parece distinta en la superficie, pero exige la misma precisión
Inestabilidad: problemas de confiabilidad en la generación de código basada en especificaciones
- Al pedirle a Claude Code, como recomienda el README de Symphony, una implementación en Haskell, el resultado no funcionó
- Aparecieron numerosos bugs y fue necesario corregirlos mediante prompts adicionales (algo visible en el historial de commits)
- Incluso cuando parecía “funcionar” sin mensajes de error, el agente
codex quedaba en espera infinita sin ningún avance ante un ticket simple de Linear (“crear un repositorio git vacío”)
- Tomando la expresión de Dijkstra, se confirma que el “vano intento de precisión lingüística” de Symphony sigue sin lograr generar implementaciones confiables
- Este problema no se limita a Symphony: incluso especificaciones YAML, extremadamente detalladas, ampliamente usadas y con suites de pruebas de conformidad, no logran que la mayoría de las implementaciones de YAML cumplan completamente el estándar
- La especificación de Symphony ya alcanza una sexta parte del tamaño de la implementación en Elixir incluida; si se expandiera más, se llegaría a una situación como la parábola de Borges en “Del rigor en la ciencia”, donde un mapa del mismo tamaño que el imperio termina volviéndose inútil
- Frente al contraargumento de que “el resultado sería mejor si se generara en un lenguaje más mainstream”, se responde que si el agente tiene dificultades para generar código Haskell, eso sugiere una falta de capacidad de generalización más allá de sus datos de entrenamiento
Slop: el problema de calidad en las especificaciones generadas por IA
- El trabajo de especificación, por naturaleza, debería ser más difícil que programar, ya que su propósito es empujar a pensar el proyecto de forma reflexiva y crítica antes de empezar a codificar
- Pero en una industria tecnológica donde la tendencia es reducir y devaluar el trabajo, partir de la premisa de que “hacer especificaciones es más fácil que programar” lleva a un fracaso anunciado
- Es imposible perseguir la optimización del tiempo de entrega y, al mismo tiempo, realizar el trabajo difícil e incómodo que exige redactar buenas especificaciones
- La Sección 10.5 de SPEC.md de Symphony (el contrato de extensión
linear_graphql) es un ejemplo representativo de slop: un resultado de agente compuesto por frases que parecen especificación, pero carecen de coherencia, propósito y comprensión del panorama general
- Se enumeran reglas aisladas, como que
query debe ser una cadena no vacía o que debe contener exactamente una operación GraphQL, pero falta el contexto global
- Incluso si estos documentos los hubiera escrito una persona, inevitablemente serían slop, porque están optimizados por tiempo de entrega y no por coherencia ni claridad
- El hecho de que fragmentos de código estén anotados como
text sin resaltado de sintaxis también es una señal de documentación generada por IA — probablemente porque el modelo siguió la solicitud de forma literal y no su intención
Conclusión
- Las especificaciones nunca fueron diseñadas originalmente como un mecanismo para ahorrar tiempo
- Si el objetivo es optimizar el tiempo de entrega, resulta más conveniente escribir el código directamente que pasar por un documento intermedio de especificación
- El principio de “garbage in, garbage out” se aplica tal cual: si se ingresan documentos sin claridad ni detalle, no existe un mundo en el que un agente de programación pueda completar esas carencias de manera confiable
- Los agentes de programación no leen la mente y, aun si lo hicieran, no hay mucho que puedan hacer cuando el pensamiento mismo es confuso
6 comentarios
Parece exactamente lo mismo que en la etapa de desarrollo guiado por modelos.
¿No existía ya desde antes el desarrollo basado en especificaciones, SDD?
Parece que, con soluciones basadas en Python o JavaScript, es posible lograr implementaciones satisfactorias solo con documentación de especificaciones detalladas. Estos días trabajo en el área de juegos y medicina con base en C/C++, y cada vez pienso más que automatizar solo con documentación de especificaciones detalladas, ni hablar de delegarlo por completo a un FULL AI AGENT, es algo demasiado arriesgado.
Comentarios en Hacker News
No estoy de acuerdo con la idea de que, si le das documentación poco clara, un agente de código no pueda completar los detalles
Los LLM son, en esencia, máquinas de interpolación/extrapolación del lenguaje, y son muy buenos para rellenar detalles faltantes
Hay muchos casos en los que producen código funcional con solo una explicación breve y concisa
Aun así, ese relleno de detalles no siempre es correcto, y para asegurar confiabilidad hay que imponer restricciones explícitas en las partes importantes
Hoy existe una cultura de escribir código, pero casi no existe una cultura de escribir especificaciones de ultra precisión, salvo en lugares como la NASA
Mientras más corto y común sea el código, mejor funciona, pero con descripciones complejas se rompe con facilidad
Al final, reconocer que “el relleno de detalles puede estar mal” significa que la generación confiable es difícil
Por ejemplo, existen lenguajes de síntesis de programas como Synquid
Muestran qué límites tiene una especificación matemáticamente exacta para la generación de programas
El problema llamado specification gap, es decir, demostrar si un programa implementa fielmente la especificación, es la tarea central
El lenguaje natural es demasiado ambiguo para definir programas
Que un LLM rellene detalles plausibles no resuelve esa brecha
Los lenguajes de especificación matemática son precisos, pero tienen una curva de aprendizaje alta y son mucho más difíciles e intensivos en trabajo que simplemente escribir prompts en Markdown
El modelo recuerda mis intereses o llena huecos con su propio conocimiento para producir una app, un juego o un whitepaper terminados
A veces es “exactamente lo que quería”, y otras es “justo la vibra que estaba describiendo”
Su capacidad para manejar significado, contexto y matices en algunas cosas incluso supera a la humana
La IA se está volviendo cada vez más inteligente y capaz
Es decir, no crean detalles completamente nuevos, sino que más bien recuperan cosas a partir de los datos de entrenamiento
Me identifica la frase “una especificación suficientemente detallada ya es código”
Esto va en la misma línea que No Silver Bullet de Brooks
Pero la mayoría de la gente no quiere ese nivel de detalle
Si dices “hazme una app de tareas” a la IA, en realidad significa “hazme una app mejor que la que imaginé”
Pero este enfoque no escala bien a otros tipos de software
Al final, esa diferenciación hay que expresarla como especificación
Pero en áreas como bases de datos, sistemas de archivos y cómputo paralelo, donde la exactitud y el rendimiento importan, la implementación es mucho más difícil que la especificación
Que una IA genere código que pase verificación formal en esos casos es un gran reto
Si quieres ganar dinero o competir, necesitas requisitos concretos
Si miras el vibe coding desde la teoría de la información, se asume que existe un decodificador capaz de reconstruir un espacio de programas útil a partir de un espacio pequeño de prompts
Ahí, la tasa de compresión es justamente la ganancia del vibe coding
Un prompt como “app de comunicación de equipo basada en canales IRC” es imposible de decodificar si no conoces Slack
Por eso es importante reconocer qué falta
Para programar con IA de forma efectiva, hay que dividir los prompts en unidades cortas y acompañarlos con documentación existente o código ya intentado
Según Algorithmic Information Theory, la cantidad de información de una cadena es igual a la longitud de su representación autocontenida más comprimida
Pero la condición de que sea “autocontenida” solo se cumple cuando los pesos del modelo cumplen el papel de libro de códigos
Los humanos asumimos mucho más contexto compartido que un LLM, así que tendemos a sobreestimar los límites del decodificador
Pero un sistema con restricciones fuertes y énfasis claros podría disparar la tasa de compresión del vibe coding
El lenguaje natural ofrece una nueva interfaz para personas a quienes los lenguajes de programación les resultan menos accesibles
El LLM no piensa por ellas, pero sí abre una nueva vía para convertir ideas en sistemas que funcionen
Pronto la gente probablemente va a crear un dialecto de inglés técnico tipo LLMSpeak para mejorar el rendimiento del modelo y la eficiencia de tokens
La idea sería reducir ambigüedad, ahorrar tokens y comprimir conceptos complejos en una sola palabra
Incluso podrían surgir reglas gramaticales como la Oxford comma para aumentar la claridad
Si vas a especificar todo con tanto detalle, ya no hay mucho motivo para usar prompts
Al final tendrías que redefinirlo otra vez en lenguaje humano, así que el ahorro de tokens sería limitado
Ver wiki de Lojban, video de un hablante de Lojban
Los intentos de dialectos artificiales probablemente fracasen como Esperanto
Ese tipo de lenguaje podría ser más útil entre LLMs
Los lenguajes de programación ya cumplen en parte ese papel
Una especificación (spec) es como un sobre (envelope) que contiene todos los programas que satisfacen ciertas condiciones
Construir ese sobre es más difícil que escribir un solo programa
Igual que un LLM genera código distinto cada vez, una especificación permite tanto implementaciones buenas como malas
En la práctica, cuando una implementación se adopta, esa pasa a ser la especificación de facto de la siguiente versión
En entornos con código heredado (brownfield), la especificación no es limpia, así que a los LLM les cuesta responder bien
Hay una explosión combinatoria al tener que considerar cómo interactúa cada línea de la especificación con las demás
Pero desde el punto de vista del compilador, el código también es solo una especificación
Al final, decir que “el código es más fácil que la especificación” es algo relativo
La especificación “almacenar credenciales de usuario” puede abarcar desde bcrypt hasta cookies en texto plano
Los humanos tenemos el instinto de pensar “eso no se debe hacer”, pero un agente no lo sabe si no se lo indicas
Por eso, para asegurar la seguridad, también hay que especificar qué no se debe hacer
Si el rendimiento o la seguridad importan, esas propiedades deben declararse
Por ejemplo, una frase como “este programa debe ser O(n)” es mucho más simple que la implementación
Parece que cada persona usa spec con un sentido distinto
Para mí, spec define el “qué (what)”, plan define el “cómo (how)” y build packet significa los “pasos detallados”
En la mayoría de los casos, lo importante es el “qué”
Es mucho más fácil escribir como especificación que los datos se conservan de A a B, pasando por C y llegando a D, y que se representan en formato F en E, que implementarlo en código Rust
Cuando haces ingeniería con agentes, muchas veces el documento de especificación termina siendo más largo que el código
El lenguaje natural es imperfecto, pero el código es exacto
El objetivo de la especificación es conservar la funcionalidad a través de múltiples iteraciones de desarrollo
Los documentos de diseño estilo waterfall me resultaron más efectivos que las pruebas o los comentarios
Con este enfoque también pude refactorizar sin problemas proyectos completos de vibe coding o cambiarles el lenguaje
Ahora se siente como si hubiéramos vuelto al flujo de desarrollo de los años 70 y 80
Una frase como “implementar una interfaz TCP” es mucho más corta que el código real
Al final, si puede mapearse a un esquema claro, el lenguaje natural también puede ser bastante compacto
La dirección Spec → LLM es ineficiente y derrochadora
Más bien, LLM → Spec es más realista
Si la especificación existe en una forma compilable, el LLM puede usar esa retroalimentación para generar mejor código
Los intentos de crear “inglés validado (validated English)” solo agregan más complejidad
Al final, lo importante es el código que realmente funciona
El código contiene muchas más cosas que la especificación
En la mayoría de los proyectos, 90% es código de framework o infraestructura y solo 10% es lógica de negocio
La especificación es mucho más concisa porque no trata detalles del lenguaje o del framework
Así se obtiene un código casi al mismo nivel que la especificación
Incluso expertos del dominio pueden leerlo y también es fácil de probar
Pero el código real cambia bastante
El choque entre ver la especificación como herramienta de gestión y verla como herramienta de ingeniería produce disonancia cognitiva
Los managers ven la especificación como un ticket delegable, mientras que los desarrolladores la usan como una herramienta para refinar el pensamiento
Algunos desarrolladores empiezan adoptando por comodidad la forma de pensar del manager, pero pronto se dan cuenta
Puedes sostenerte un rato con hype o reuniones con inversionistas, pero al final los usuarios quieren un producto real
Lo siguiente será reinventar también el waterfall y agile, supongo.
Como desarrollador embebido en C, preparo la especificación de forma que casi todo el flujo de cada Feature/Subfeature pueda verificarse con diagramas.
Después de revisar la especificación en detalle y confirmarla definitivamente,
genero y utilizo código que corresponde completamente 1 a 1 con la especificación.
Al revisarlo como especificación, la legibilidad es muy superior a la revisión de código.