Por qué los agentes de código funcionan y por qué fallan

Es el mismo modelo. El que alucinaba en el chat web sube una funcionalidad de 200 líneas de golpe en Claude Code. El /goal de Codex resuelve un issue completo de una vez. El modelo no se volvió más inteligente de repente. Lo que cambió fue la estructura.

Por qué funciona

El loop de la IA conversacional es así:

LLM → persona → LLM → persona

Todo el feedback es lenguaje natural. A una generación probabilística le sigue una evaluación probabilística. La precisión se degrada multiplicativamente.

El loop de un agente de código es diferente:

LLM → generación de código → guardado en disco → ejecución de tests → pass/fail → LLM
LLM → modificación de código → build → éxito/fallo → LLM
LLM → type check → mensaje de error → LLM

Dentro del loop hay compuertas deterministas. El sistema de archivos guarda exactamente lo que se escribe. Un test es pass o fail. El compilador dice que está mal si está mal. Estas compuertas actúan, sin pretenderlo, como un ratchet.

Un LLM es un unreliable component. Pero montar un reliable protocol sobre unreliable components es ingeniería básica. TCP construye reliable delivery sobre una unreliable network. RAID construye reliable storage sobre unreliable disks. ECC construye reliable computation sobre unreliable memory.

La razón por la que los agentes de código funcionan es la misma. Porque montaron deterministic verifiers (tests, build, linters, type checkers) sobre un unreliable LLM. No es el rendimiento del modelo sino la topology lo que causa el éxito.

Entonces, ¿por qué colapsan?

Dije que funcionan. Pero a veces colapsan. ¿Por qué?

Porque un ratchet que aparece por accidente no es lo mismo que uno diseñado conscientemente.

Existen tramos sin ratchet

¿Qué pasa cuando un agente modifica código sin tests? El build pasa, el lint pasa, pero la funcionalidad está rota. En tramos sin compuerta determinista, el LLM juzga probabilísticamente, y el juicio probabilístico se degrada multiplicativamente.

De 200 endpoints, 180 tienen tests y 20 no. El agente procesa los 180 impecablemente y planta bugs silenciosamente en los 20. Esa es la razón de “casi está listo, pero algo no anda bien”.

La cantidad de información del feedback es insuficiente

Hice un experimento ordenando 1000 palabras. La CPU lo hizo en 0.08 ms con 100 % de precisión. El LLM tardó 438 segundos con 97.7 %. Eso en sí es asombroso — 97.7 % con pura cognición. Pero el verdadero hallazgo estaba en otra parte.

Variando solo el nivel de feedback para el mismo resultado:

FeedbackResultado
Ninguno6 errores (99.4 %)
“Hay errores”10 errores (99.0 %) — empeoró
“Hay 23 errores”1 error (99.9 %)
“6 errores, aquí están”0 errores (100 %)

Decir solo “está mal” provoca sobrecorrección y empeora las cosas. Dar el número de errores establece un objetivo y el modelo busca con tenacidad. Indicar también la ubicación permite una corrección perfecta.

La mayoría de los agentes actuales están en el segundo nivel. Cuando un test falla, saben que “algo está mal”, pero no transmiten la razón estructural de por qué está mal. Hay mensajes de error, sí, pero esos son síntomas, no causas.

Existen puntos ciegos, y la repetición no los resuelve

En el experimento de ordenamiento, el LLM dejó 6 errores en R2. En R3 reportó “sin errores”. En R4b también reportó “sin errores”. Pasó por alto los mismos 6, de la misma manera.

Sin pistas, convergía en 99.4 % sin importar cuántas veces lo repitiera. Solo cuando le dije “quedan 6” alcanzó el 100 %.

Lo mismo ocurre con los agentes de código. El agente introduce un bug, hace self-review y dictamina “sin problemas”, y aunque le pidas que lo corrija, pasa por alto el mismo punto. Por eso retry no es la solución. Los puntos ciegos son una limitación estructural derivada de la naturaleza probabilística del modelo, no una falta de esfuerzo.

A escala, la multiplicación actúa

Un paso con 97.7 % de precisión encadenado dos veces da 0.977² = 95.4 %. Tres veces: 93.2 %. Diez veces: 79.2 %.

Un agente modifica bien un solo archivo. Pero ¿si le pides un refactoring que abarca 100 archivos? Aunque cada paso sea 97 %, tras 100 pasos: 0.97¹⁰⁰ = 4.8 %. El fracaso está prácticamente garantizado.

Esta es la explicación matemática de “el vibe coding colapsa a partir de 200 endpoints”. En proyectos pequeños el número de encadenamientos es bajo y la probabilidad aguanta; en proyectos grandes la multiplicación actúa de forma catastrófica.

Qué se necesita

La razón de que funcione y la razón de que colapse apuntan al mismo lugar: la presencia o ausencia de compuertas de verificación determinista.

Los agentes actuales dependen de ratchets que aparecen por accidente (tests, build, linters). Si se diseñan conscientemente, se vuelven más robustos.

Diseñar ratchets de forma consciente significa:

Primero, identificar los tramos sin ratchet. Código sin tests, APIs sin schema, datos sin tipos. Todo lugar donde el agente juzga probabilísticamente es un punto vulnerable.

Segundo, aumentar la cantidad de información del feedback. Devolver solo pass/fail provoca sobrecorrección. Hay que estructurar y transmitir “dónde, por qué, y en qué difiere de lo esperado”.

Tercero, insertar compuertas deterministas entre los eslabones de la cadena. Si se ejecutan 10 pasos de golpe, la multiplicación es catastrófica, pero si se fija cada paso con un ratchet, la degradación se reinicia.

Un LLM es un generador asombroso. Ordena 1000 palabras con 97.7 % de precisión mediante puro pensamiento. Algo que ni un humano podría hacer. Pero todo lo que no sea 100 % colapsa al repetirse. 0.977 elevado al cuadrado es 0.954.

Los agentes de código funcionan no porque el modelo sea inteligente, sino porque hay compuertas deterministas dentro del loop. Colapsan cuando esas compuertas faltan.

La generación puede ser probabilística. La verificación debe ser determinista.


Artículos relacionados