Constraint Decay: la vulnerabilidad de los agentes LLM en la generación de código backend
(arxiv.org)- Los agentes LLM son fuertes para generar código a partir de especificaciones flexibles, pero todavía son frágiles para respetar contratos de API, arquitectura, base de datos y restricciones de ORM que exige un backend de nivel de producción
- Con la misma especificación OpenAPI se fijaron los requisitos funcionales, y se aplicaron las mismas pruebas de comportamiento a 80 tareas greenfield y 20 tareas de implementación de funcionalidades en 8 frameworks web
- Las restricciones no funcionales se dividieron en 4 dimensiones: selección de framework, patrón de arquitectura, backend de base de datos e integración de ORM, para aislar el impacto de la complejidad estructural
- El colapso de restricciones es el fenómeno en el que el rendimiento cae bruscamente a medida que se acumulan los requisitos estructurales, y en tareas totalmente especificadas con configuraciones altas la assertion pass rate cayó en promedio 30 puntos
- La clave del fracaso está en los defectos de la capa de datos: la construcción incorrecta de consultas y las violaciones en tiempo de ejecución del ORM representan cerca del 45% de los fallos en la lógica del agente
Problema central y configuración de la evaluación
- Los agentes LLM son fuertes en la generación autónoma de código con especificaciones flexibles, pero todavía no se ha evaluado suficientemente su capacidad para respetar estrictamente las restricciones estructurales necesarias en software backend de nivel de producción
- Un backend de nivel de producción debe satisfacer no solo endpoints que sigan contratos de API, sino también requisitos no funcionales como patrones de arquitectura, integración de base de datos y una capa ORM especificada
- Los benchmarks existentes suelen recompensar soluciones funcionalmente correctas pero estructuralmente arbitrarias, por lo que no capturan suficientemente la dificultad del desarrollo backend con múltiples archivos y restricciones
- La investigación previa se ha centrado principalmente en resolver issues específicos dentro de codebases existentes, generación no restringida basada en prompts en lenguaje natural, soluciones de un solo archivo y completado de código esqueleto, sin abordar el efecto de variar sistemáticamente el grado de restricciones estructurales
- Se aisla el impacto de la complejidad estructural fijando los requisitos funcionales con la misma especificación OpenAPI y aplicando las mismas pruebas de comportamiento end-to-end en todas las condiciones
- El experimento está compuesto por 80 tareas de generación greenfield y 20 tareas de implementación de funcionalidades en 8 frameworks web
- Las restricciones no funcionales se dividen en 4 dimensiones: selección de framework, patrón de arquitectura, backend de base de datos e integración de ORM
- En la condición base solo se entrega la misma especificación de API, mientras que en las condiciones con restricciones se agregan requisitos como clean architecture, PostgreSQL y SQLAlchemy
- La evaluación usa tanto pruebas de comportamiento end-to-end como validadores estáticos para separar la precisión funcional del cumplimiento estructural
Resultados principales y significado
- El constraint decay se confirma como el fenómeno en el que el rendimiento del agente cae de forma significativa a medida que se acumulan los requisitos estructurales
- Incluso las configuraciones con mejor rendimiento muestran una caída promedio de 30 puntos en la assertion pass rate al pasar de la condición base a tareas totalmente especificadas, y algunas configuraciones más débiles se acercan casi a 0
- Incluso con el mismo contrato de API, hubo grandes diferencias en la tasa de éxito según el framework, y los agentes funcionan mejor en frameworks ligeros y explícitos como Flask
- En entornos con muchas convenciones, como FastAPI y Django, el rendimiento promedio baja mucho más
- El análisis de errores mostró que los defectos de la capa de datos son la causa principal, con ejemplos representativos como la construcción incorrecta de consultas y violaciones en tiempo de ejecución del ORM
- Los defectos de la capa de datos se clasifican como la causa central de cerca del 45% de los fallos en la lógica del agente
- Cumplir al mismo tiempo con los requisitos funcionales y estructurales sigue siendo un problema importante sin resolver para los agentes de codificación
- El pipeline de evaluación, la colección de tareas, las trayectorias de ejecución de los agentes y los scripts de análisis están disponibles en constraint-decay
1 comentarios
Comentarios de Hacker News
Era completamente escéptico sobre la generación de código con LLM, pero ahora más del 80% del código que uso en el trabajo es generado
Aun así, sus límites ya se han vuelto bastante claros, y han empezado a notarse en algunos proyectos; este artículo parece confirmar mis sospechas
Cuanto más compleja es la tarea, más termino agregando restricciones en especificaciones Markdown, reglas, skills, guías de estilo, casos límite, manejo de errores y directrices de optimización
En algún momento, parece que estamos trasladando la complejidad que estaba en el mundo más formal y determinista de los lenguajes de programación al mundo informal y no determinista del lenguaje natural
La mejora en velocidad de escritura es enorme, y por supuesto el negocio ve esto como un aumento de productividad, pero el costo es evidente y mucha gente parece ignorarlo
Nadie los revisa al 100%, y aun cuando se revisan, es algo muy subjetivo
No está claro cuál es la diferencia entre “seguir un enfoque RESTful”, “usamos REST y no GraphQL” y “el 90% de los endpoints están orientados a recursos, pero algunos parecen RPC, así que ignóralo”
Todo se ve bastante tonto
En la práctica, es como compilar programas llenos de comportamiento indefinido, pero que en su mayoría “parecen funcionar”
Que el negocio vea esto como una mejora de productividad da la sensación de que estamos volviendo a medir la “productividad” en líneas de código por segundo
Una vez que el codebase deja de caber dentro del primer 20% de la ventana de contexto y sale del nivel de ser totalmente repetible en una sola inferencia, el harness de ejecución y las técnicas de parcheo de código se vuelven mucho más importantes
El enfoque de apply_patch que OAI ha ido puliendo para sus modelos parece ser la mejor estrategia para codebases gigantes
Los métodos basados en rangos de líneas o en buscar y reemplazar simple se rompen en los bordes, y para manejar casos complicados como archivos cshtml se necesitan múltiples anclas espaciales
Las acciones de prepare/commit son ideales para iterar sobre contexto ambiguo distribuido en muchos archivos grandes y refinar esas anclas
Los LLM no pueden crear nada realmente nuevo
“La investigación sistemática revela el fenómeno de descomposición de restricciones en agentes de programación basados en LLM. Los modelos actuales sobresalen en generación sin restricciones, pero su rendimiento cae cuando deben seguir reglas arquitectónicas explícitas. Para el usuario final, esta dicotomía significa que los agentes son confiables para prototipado rápido, pero siguen siendo difíciles de confiar para desarrollo backend de nivel de producción.”
La gran debilidad de este estudio es que, por costos, no probó lo suficiente a los modelos de frontera, así que conviene tomar con cuidado las cifras concretas de rendimiento
Aun así, la conclusión de que el rendimiento del modelo cae cuando tanto el comportamiento como la arquitectura tienen que ser correctos es interesante y vale la pena seguirla
Si solo hay requisitos funcionales, esto equivale a una especie de síntesis de programas, y el aprendizaje por refuerzo puede optimizar eso muy bien
Cuando se mezclan requisitos funcionales y no funcionales, en realidad le estás dando al modelo una especificación incompleta, y el modelo tiene que adivinar en cierta medida la intención del usuario para llenar los huecos
Esa es también la razón por la que poner ejemplos del estilo de código deseado en el prompt es tan potente
Cuanto más material de referencia hay, más depende de repetir lo que ya salió antes
También es posible que los autores presten menos atención y dediquen menos esfuerzo a la edición en los capítulos finales
En Amazon hay cantidades enormes de material, pero los LLM todavía no están en un punto en el que escriban bien
Si propone soluciones incompatibles y luego le das más contexto y requisitos, tiende a quedarse fijado en la arquitectura original y le cuesta adaptarse
A veces incluso intenta colar cambios para favorecer el plan inicial
Parece que grandes porciones del espacio de soluciones posibles se vuelven inalcanzables
Por ejemplo, hace como un año, cuando se aplicaban guardrails a generadores de imágenes, todas las personas empezaban a verse parecidas, y los generadores de historias empezaban a usar solo unos pocos nombres estándar
Me pregunto si esto todavía pasa incluso en los modelos de frontera
No me interesan mucho los análisis de debilidades de estos modelos. Por experiencia, cuando el modelo mejora y se incrementa el esfuerzo de razonamiento, muchas debilidades desaparecen por completo
Sobre todo si le dices con claridad el comportamiento que quieres, y no sorprende que la tasa de fallo suba cuando aumenta la cantidad de criterios de aceptación
La situación es peor. Los agentes no solo tienen más dificultades bajo “restricciones estructurales”, sino que son todavía peores cuando esas mismas restricciones estructurales tienen que cambiar
Cuando diseñamos un sistema o un componente, establecemos ideas que se vuelven invariantes
Algunas invariantes son grandes, como una arquitectura amplia, y otras son pequeñas, como la elección de una estructura de datos
Pero al final llega el momento en que quieres agregar una función que entra en conflicto con esas invariantes
En ese momento normalmente hay tres opciones: no agregar la función, montar la función encima de las invariantes de manera poco elegante o ineficiente, o volver atrás y cambiar las invariantes
Por lo general, solo una de esas opciones es correcta, y al menos una suele estar muy mal y producir malos resultados
Los agentes, incluso cuando pueden seguir restricciones, son muy malos para detectar el momento en que hay que cambiar las restricciones
Este es uno de los límites entre reconocimiento de patrones y razonamiento, y pese al marketing sobre procesos de pensamiento, los LLM no razonan en absoluto
Todos los intentos de hacer que parezcan razonar se parecen más a un esfuerzo recursivo de aislamiento en el que el harness intenta meter un rayo en una botella
Me recordó a un artículo reciente que delegaba a los LLM tareas de edición de documentos en varios campos https://arxiv.org/abs/2604.15597
En ese artículo se planteaba que la programación era prácticamente el único ámbito en el que la mayoría de los LLM podían realizar tareas de horizonte largo sin acumular errores ni arruinar el documento
En este caso solo leí el resumen, pero parece que analiza la programación con más detalle y muestra un fenómeno similar
Aunque más que una tarea de horizonte largo, parece más cercano a un “horizonte largo de estilo” respecto a un conjunto mayor de restricciones estructurales
Discusión relacionada: https://news.ycombinator.com/item?id=48073246
Es un artículo muy interesante y estoy totalmente de acuerdo, pero no creo que cuente algo nuevo
Ya desde el principio estaba un poco fuera de lugar la expectativa de que bastara con soltar alguna solución de programación agentiva dentro de un proyecto y lanzarle una lista de tareas para que siguiera mágicamente las restricciones predefinidas del proyecto
No creo que ningún stack de programación agentiva pueda hacer eso en su estado base
Para que un agente entienda de forma estable el contexto, las restricciones y los objetivos, sigue haciendo falta un mecanismo adecuado, y viendo cómo los principales laboratorios de IA siguen actualizando herramientas, habilidades y procesos, está claro que sigue siendo un área en desarrollo
Esta capa adicional podría ser mucho más rentable que el modelo puro y el consumo de tokens
Incluso modelos abiertos como los que parece que probaron ahora, bien puestos en marcha, ya pueden producir código de producción que siga las restricciones deseadas
Me da curiosidad saber cómo ha sido su código de producción en los últimos meses
He experimentado bastante con programación agentiva de horizonte largo https://medium.com/@vishvananda/i-spent-2-billion-tokens-wri..., y también he visto que imponer ciertos patrones de arquitectura empeora el rendimiento del agente
Si las restricciones se incorporan durante el proceso en vez de agregarse después, mejora un poco
Hay un efecto secundario que yo llamo calcificación: cuando cierto patrón empieza a aparecer en el codebase, el agente sigue ese patrón hasta que domina el contexto y se refuerza a sí mismo
En un codebase existente, eso puede ser una fortaleza o una debilidad según la calidad del código
Cuando terminen más ejecuciones en codebases nuevos que incluyan directrices de arquitectura desde el principio, probablemente habrá más aprendizajes
Además, los modelos modularizan razonablemente bien cuando tienen margen para “planear” una implementación, pero rara vez deciden por sí solos que después convendría abstraer
Eso pasa especialmente tras varias iteraciones en un codebase nuevo o cuando se los mete en un codebase legado, y muchas veces termina en archivos gigantes
Si el usuario se los señala, el modelo sí lo critica correctamente, lo cual resulta bastante gracioso cuando fue su propio código desde el inicio
Suena como otra versión de “mientras más larga se vuelve la charla, más se diluyen los guardrails”
La razón por la que no se puede usar toda la ventana de contexto es que, hacia el final, la salida deja de respetar las restricciones o los guardrails
Pero para producir código de nivel producción de manera estable, el modelo necesita una visión amplia, y eso llena muy rápido la ventana de contexto
Es parecido a decir “haz este cambio teniendo en mente todo lo que hay en estos 6 directorios”, pero solo tenerlo todo en mente ya llena la ventana de contexto y le hace perder la capacidad de seguir restricciones
Aunque entonces el patrón de fallo probablemente sería centrarse en satisfacer el linter mientras va olvidando poco a poco los requisitos
Además, repetir ciclos de intento/fallo tampoco le hace nada bien al contexto
En la investigación usaron lenguajes de tipado dinámico como Python y JS
Por mi experiencia, los codebases con tipado estático son más fáciles de mantener también para las personas, así que podría pasar lo mismo con los agentes
Usando Codex o Claude Code sobre código Go, he visto incontables veces al agente hacer cambios, ejecutar el build, encontrar errores y volver a corregirlos
Hoy en día los modelos manejan bastante bien los tipos en Python
En Python, un tipado estático fuerte existe como opción desde hace años, y simplemente debería ser el valor predeterminado
Hablan de “trabajo a través de 8 frameworks web”, y me da curiosidad si alguien ha visto que los LLM construyan mejor con HTML+CSS+JS puro que trabajando con frameworks existentes
La combinación más sorprendente que he visto recientemente es Razor Pages con mejora progresiva en JavaScript
En esa configuración, los modelos recientes distinguen bastante bien qué cosas deben pasar del lado del servidor (cshtml) y cuáles del lado del cliente (js)
Recomiendo dedicar tiempo a pulir primero algunas partes del codebase hasta dejarlas en una forma idiomática, y luego marcar esos archivos como archivos de ejemplo con @
Funciona mucho mejor que intentar dirigirlo con Markdown
En casos como FastAPI funciona bastante bien, pero JavaScript parece ser lo peor
Incluso dándole directrices y ejemplos, tiende a meter un montón de código innecesario inline en vez de usar la API indicada