Loops que se mejoran solos
Producir y revisar no alcanza. Lo que separa un loop que converge de uno que no, es lo que hacés con lo que aprendiste.
Llevo un tiempo con agentes que codean por mí: programas que reciben una tarea y escriben el código solos. Y hay algo que me molesta cada vez que reviso un PR, el paquete de cambios que el agente propone y que alguien tiene que aprobar antes de que entre al proyecto. Corrijo lo mismo otra vez. Le saco el any, un tipo comodín de TypeScript que apaga los chequeos del lenguaje. Le renombro variables y le pido tests para el edge case que faltó, el caso raro que nadie pensó. Se lo devuelvo para que lo arregle (a eso le decimos kickback) y en el siguiente vuelven las mismas correcciones. El agente produce, yo reviso, y la próxima tarea arranca como si nada de eso hubiera pasado.
El problema no me parece el agente: el que no está cerrando es el workflow, el circuito de pasos que va de la tarea al código aprobado.
El ciclo que dejamos a medias
El flujo típico que veo es así. Le das un prompt, la instrucción escrita con la tarea. El agente produce. Vos revisás. Si algo está mal, lo mandás de vuelta. Si está bien, shipeás. Parece un ciclo cerrado.
Pero me parece que se cierra antes de tiempo. Falta lo que pasa después de la review: volver a alimentar el sistema con lo que aprendiste.
Yo lo pienso como cuatro pasos: observar, producir, revisar, mejorar. Ese cuarto es el que casi nunca veo armado. Sin él, el sistema repite los mismos errores con la misma confianza y no converge: nunca llega al punto en que deja de cometerlos. O al menos yo todavía no vi que llegue solo.
La pregunta que me hago después de cada review es qué aprendió el sistema cuando una persona le corrigió el resultado. Si la respuesta es “nada”, el workflow sigue incompleto.
Lo que armé en Bille (y qué falta)
En Bille, el proyecto en el que vengo laburando, intenté cerrar ese hueco. No digo que esté resuelto. Todavía estoy viendo qué funciona.
El flujo base ya lo conté en otro post. Las tareas viven en Linear, la herramienta donde llevo los tickets, con la etiqueta “Ready For Claw”. Un coder agent, el agente que escribe el código, toma la tarea, codea, corre lint y typecheck (dos chequeos automáticos, uno de estilo y otro de tipos) y los tests, y si todo pasa abre el PR. Un reviewer, otro agente, lee el diff, que es la lista de líneas que cambiaron, busca bugs y problemas de arquitectura, y si encuentra algo kickbackea al coder. Tres kickbacks sin resolución y me avisa. Eso ya estaba.
Lo que agregué después es distinto. Cada intento queda en una nota de Obsidian, la app donde guardo mis apuntes: qué se hizo, qué falló, qué decidió el reviewer, cuántos kickbacks van. El agente arranca cada tarea sin memoria. La nota es lo que se la devuelve.
Y hay un paso más que para mí es el que importa. Después de que yo reviso un PR, corre un Learning Flow, un proceso automático que toma mis comentarios de la review, los analiza y actualiza CODING_PREFERENCES.md, el archivo con mis preferencias de código. No es una lista cruda de comentarios sino un intento de convertir “otra vez le saqué el any” en algo que el próximo coder lee antes de escribir una línea.
¿Baja la cantidad de kickbacks? A veces. A veces no. Cuando no baja, el límite de tres me obliga a entrar yo. Me parece bien. Prefiero eso a un loop que gira en círculos sin avisar.
Los documentos de gusto
Las notas de Obsidian son memoria de tarea. Los taste documents son otra cosa. Yo les digo así a los style guides, las guías que dicen cómo se escribe o se codea en un lugar, cuando evolucionan con el laburo real.
En código, CODING_PREFERENCES.md no es un copy-paste de reglas genéricas de TypeScript. Se alimenta de mis reviews. Si siempre le saco el any, eso debería quedar escrito para el próximo agente. Si siempre pido tests para edge cases, también.
En escritura hago lo mismo con este blog. Tengo un style guide que actualizo después de cada merge, cada vez que un post entra al sitio. Comparo lo que el agente escribió con lo que terminé publicando. Si siempre reescribo los párrafos que arrancan con “Además”, eso entra al guide. La próxima vez, con suerte, el agente ya lo sabe.
Un style guide estático te sirve para arrancar. Uno vivo, creo, es lo que hace que el loop deje de sentirse como automatización pura.
La analogía que uso con amigos: es como un intern que de a poco aprende cómo te gusta el café, en vez de uno que te trae cortado todos los meses cuando querés lágrima. El feedback tiene que ir a algún lado que persista. Si no, estás gastando el mismo esfuerzo en cada review.
No es automático
Lo que me interesa de esto no es solo el mecanismo, sino que el paso de mejora no te lo da ninguna herramienta. No vi un feature de Cursor, el editor de código con IA, que actualice tus preferencias después de cada kickback. No hay un checkbox en Linear que diga “aprender de este comentario”. Es algo que tenés que construir encima de las herramientas que ya usás.
Y es fácil dejarlo afuera porque las otras tres partes ya funcionan. Producir, revisar y shipear es una rueda que gira sola. El problema es que puede girar sin avanzar. Cada vuelta parece igual a la anterior si nadie escribe la lección en un lugar que el próximo agente lea.
Y no es solo código: cualquier workflow donde una persona corrige lo que produjo una IA tiene el mismo hueco. Textos de marketing, diseño, especificaciones de producto. Si la corrección no vuelve al sistema, el sistema no aprende.
Lo que me queda por resolver
Todavía estoy viendo qué funciona y qué no. El sistema de Bille es joven. Los taste documents cambian con cada iteración. A veces el Learning Flow propone algo que no quiero en el guide y lo edito a mano. A veces actualizo el guide yo directamente porque fue más rápido.
Todavía no descubrí cuándo conviene automatizar el paso de mejora y cuándo hacerlo a mano. Por ahora uso esta regla: si lo corregí dos veces en reviews distintas, lo escribo en algún lado. Si pasó una sola vez, capaz no.
Si estás usando agentes y sentís que corregís lo mismo una y otra vez, fijate a dónde van a parar esas correcciones. Si cada review es un evento aislado, el loop no está cerrando.
Yo voy a seguir iterando el flujo en Bille: escribir las lecciones en CODING_PREFERENCES.md, en las notas de Obsidian, en los guides del blog, y ver si con el tiempo dejo de sacar el mismo any en el PR número doce. No sé si alcanza, pero es el único paso que no puedo saltear si quiero que esto escale sin convertirme en el cuello de botella eterno.