La IA ya escribe código, y lo hace, por lo general, rápidamente y de forma razonable. Además, lo compila bien y si falla, itera y lo arregla. A estas alturas esto no lo discute nadie
Lo que se discute menos es de qué depende ese código. Y la respuesta está vinculada a un viejo conocido en ingeniería de software: depende de lo que le pidas, es decir, cómo de completos sean los requisitos. Un modelo de lenguaje no llega con una idea de tu sistema en la cabeza; llega con tu petición y nada más. Si le pides algo preciso, te devuelve algo que se ajusta. Si le pides algo con huecos, cosas que dabas por sabidas y no escribiste, no levanta la mano para preguntar. Tira para adelante y los rellena.
Pero, ¿con qué se rellenan los huecos? La respuesta es muy LLM: con lo que estadísticamente toca, lo más común, lo que en el grueso de los casos sería una respuesta sensata. Que no tiene por qué ser la que tú necesitabas ni ajustarse a tu base de código, ni considerar el contexto ampliado a la petición que estás haciendo. Esto es uno de los principales “matices” que hace difícil integrar código generado con LLMs de forma natural en bases de código suficientemente complejas.
Jurassic Park lo explicó hace treinta años mejor que cualquier diagrama:
El ADN de dinosaurio que recuperan de los mosquitos conservados en ámbar está hecho polvo: le faltan cadenas enteras. Millones de años degradándose lo han dejado lleno de huecos y sin secuencia completa no hay clonación. ¿La solución de los genetistas? Completar esos huecos con ADN de rana. Y cuela: los dinosaurios nacen y el parque abre .
El problema llega después. El parque estaba pensado solo con hembras, para que los dinos no se reprodujeran. Lo que nadie tuvo en cuenta es que algunas ranas cambian de sexo cuando no hay individuos del otro alrededor. Ese detalle viajaba escondido en el ADN del relleno. Resultado: los dinosaurios empiezan a criar. Nadie lo pidió, nadie lo vio venir, y para cuando se dan cuenta el parque ya se les ha ido de las manos.
Y fíjate de dónde sale el fallo: del material con el que taparon lo que faltaba. Aquel relleno que parecía inofensivo, un parche técnico sin mayor importancia, era lo que de verdad decidía si el sistema se mantenía bajo control o no.
Un modelo de lenguaje hace exactamente esto con tu código. Donde tu petición no especifica con detalle, él rellena, y rellena con la opción más probable, que casi nunca es la tuya. Lo que te devuelve compila y pasa el chequeo (linter) sin pestañear. La suposición que se inventó por el camino no la ves: aparece meses después, en producción, el día que el sistema hace algo que nadie le pidió.
Y aquí viene lo que casi todo el mundo subestima. Especificar no es describir qué tiene que hacer la pantalla nueva. Eso es la parte fácil. Lo difícil son las reglas con las que tiene que hacerlo:
→ Seguridad: qué se valida, qué se cifra, contra qué amenazas hay que proteger.
→ Invariantes de negocio: lo que tiene que seguir siendo cierto pase lo que pase. Un descuento no se aplica dos veces, un pedido cancelado no factura, no se envían nuevas ofertas a clientes en mora.
→ Estilo y convenciones: los patrones que el proyecto ya usa y que no se deben romper.
→ Rendimiento: qué es aceptable y qué no a la escala real, no a la del ejemplo de juguete.
Todo eso es la especificación y un agente debe tenerla en cuenta cada vez para el código que se genere de forma agéntica. Si no lo pones encima de la mesa, no se evapora: lo rellena el modelo a su manera. Y lo que para algo entrenado con medio internet es "lo normal" puede no tener nada que ver con cómo se hacen las cosas en tu empresa.
Pruébalo. Pídele a cualquier asistente "hazme un login seguro". ¿Seguro contra qué? ¿Qué política de contraseñas, qué pasa tras cinco intentos fallidos, hay doble factor, con qué algoritmo hasheas? No has fijado ni una sola regla, así que se las inventa él. Te dará un login y funcionará. Y casi seguro no será el que tú tenías en la cabeza. Mete esas reglas en la petición y el margen para que improvise se reduce de forma radical. Mismo modelo, mismo prompt en apariencia: lo único que ha cambiado es lo que le diste.
Y todo esto se complica cuando hablamos de código heredado, que es donde de verdad muchas organizaciones se pasan la vida. En un sistema con quince años encima, media docena de esas reglas no están escritas en ningún sitio. Viven dentro del propio código, ese `if` que valida dos veces por una razón que alguien tuvo clarísima en 2014, o en la cabeza de alguien que se fue de la empresa hace tres. El código te dice lo que hace. El porqué lo hace así casi nunca te lo cuenta.
Así que cuando le sueltas a la IA "tócame esto", le faltan justo las reglas que nadie llegó a escribir. Ni puede preguntarte por ellas, porque no sabe que están ahí. Las rellena, como siempre. Solo que ahora lo hace sobre un terreno donde un caso límite mal entendido arrastra años de consecuencias detrás.
Tras un par de años en este tema de generar código con agentes, me sorprende todavía que el debate de los equipos de desarrollo arranque siempre en qué LLM utilizar. Esa es la parte fácil. La pregunta correcta debería ser ¿cómo vamos a dotar a cualquier LLM que compremos del contexto suficiente para que pueda modificar nuestra base de código de una manera eficiente? Frecuentemente no escucho esa pregunta, lo cual tiene consecuencias: consumos masivos de tokens, alucinaciones y ADN de rana esparcido por todas partes en la base de código.
Como siempre en IA, la base es el dato, la organización de la base de código y la documentación de desarrollo para que sea utilizable de forma rentable por un LLM. Algo sabemos de eso 😊. Hablemos
Descubre cómo abordar este problema en entornos reales