investigación

Escalar la programación autónoma de larga duración

Wilson Lin7 min de lectura

Hemos estado experimentando con la ejecución autónoma de agentes de programación durante semanas.

Nuestro objetivo es entender hasta dónde podemos ampliar los límites de la programación con agentes en proyectos que normalmente requieren meses de trabajo de equipos humanos.

En esta publicación describimos lo que hemos aprendido al ejecutar cientos de agentes concurrentes en un solo proyecto, coordinar su trabajo y ver cómo escriben más de un millón de líneas de código y billones de tokens.

Los límites de un solo agente

Los agentes actuales funcionan bien para tareas concretas, pero son lentos en proyectos complejos. El siguiente paso natural es ejecutar varios agentes en paralelo, pero averiguar cómo coordinarlos no es sencillo.

Nuestra primera impresión fue que planificar de antemano sería demasiado rígido. El recorrido de un proyecto grande es ambiguo, y la forma adecuada de dividir el trabajo no resulta obvia al principio. Empezamos con una coordinación dinámica, en la que los agentes deciden qué hacer en función de lo que otros están haciendo actualmente.

Aprendiendo a coordinarse

Nuestro enfoque inicial daba a los agentes el mismo nivel y les permitía coordinarse entre sí mediante un archivo compartido. Cada agente comprobaba lo que estaban haciendo los demás, asumía una tarea y actualizaba su estado. Para evitar que dos agentes tomaran la misma tarea, usamos un mecanismo de bloqueo.

Esto falló de formas interesantes:

  1. Los agentes mantenían los bloqueos durante demasiado tiempo, o se olvidaban por completo de liberarlos. Incluso cuando el bloqueo funcionaba correctamente, se convertía en un cuello de botella. Veinte agentes acababan funcionando con el rendimiento efectivo de dos o tres, y la mayor parte del tiempo se perdía esperando.

  2. El sistema era frágil: los agentes podían fallar mientras mantenían bloqueos, intentar adquirir bloqueos que ya tenían o actualizar el archivo de coordinación sin siquiera adquirir el bloqueo.

Intentamos sustituir los bloqueos por control de concurrencia optimista. Los agentes podían leer el estado libremente, pero las escrituras fallaban si el estado había cambiado desde la última vez que lo habían leído. Esto era más simple y robusto, pero seguía habiendo problemas más profundos.

Sin jerarquía, los agentes se volvieron reacios a asumir riesgos. Evitaban las tareas difíciles y, en su lugar, hacían cambios pequeños y seguros. Ningún agente asumía la responsabilidad de los problemas difíciles ni de la implementación de principio a fin. Esto hacía que el trabajo diera vueltas durante largos períodos de tiempo sin avanzar.

Planificadores y trabajadores

Nuestro siguiente enfoque fue separar los roles. En lugar de una estructura plana en la que cada agente hace de todo, creamos un pipeline con responsabilidades diferenciadas.

  • Planificadores exploran continuamente la base de código y crean tareas. Pueden crear subplanificadores para áreas específicas, lo que hace que la propia planificación sea paralela y recursiva.

  • Trabajadores recogen tareas y se centran por completo en completarlas. No se coordinan con otros trabajadores ni se preocupan por la visión general. Simplemente se dedican a su tarea asignada hasta que está hecha y luego envían sus cambios.

Al final de cada ciclo, un agente evaluador determinaba si había que continuar, y la siguiente iteración comenzaba desde cero. Esto resolvió la mayoría de nuestros problemas de coordinación y nos permitió escalar a proyectos muy grandes sin que ningún agente perdiera la perspectiva.

En ejecución durante semanas

Para probar este sistema, nos propusimos una meta ambiciosa: crear un navegador web desde cero. Los agentes trabajaron durante casi una semana y escribieron más de 1 millón de líneas de código en 1.000 archivos. Puedes explorar el código fuente en GitHub.

A pesar del tamaño de la base de código, los nuevos agentes aún pueden entenderla y avanzar de forma significativa. Cientos de workers se ejecutan de forma concurrente y hacen push a la misma rama con conflictos mínimos.

Aunque pueda parecer una simple captura de pantalla, crear un navegador desde cero es extremadamente difícil.

Otro experimento consistió en hacer una migración in-place de Solid a React en la base de código de Cursor. Llevó más de tres semanas, con +266K/-193K ediciones. Aún necesita una revisión cuidadosa, pero ya pasaba nuestra CI y las comprobaciones iniciales.

PR que muestra la migración de Solid a React

Otro experimento fue mejorar un producto próximo. Un agente de larga ejecución hizo que el renderizado de video fuera 25 veces más rápido con una versión eficiente en Rust. También agregó compatibilidad con zoom y desplazamiento suaves, con transiciones elásticas naturales y desenfoques de movimiento que siguen el cursor. Este código se fusionó y pronto estará en producción.

Tenemos algunos otros ejemplos interesantes que siguen ejecutándose:

Lo que hemos aprendido

Hemos desplegado billones de tokens en estos agentes con un único objetivo. El sistema no es perfectamente eficiente, pero es mucho más eficaz de lo que esperábamos.

La elección del modelo importa en tareas de muy larga duración. Descubrimos que los modelos GPT-5.2 son mucho mejores para el trabajo autónomo prolongado: seguir instrucciones, mantener el foco, evitar desviaciones e implementar las cosas con precisión y de forma completa.

Opus 4.5 tiende a detenerse antes y a tomar atajos cuando le conviene, devolviendo el control rápidamente. También descubrimos que distintos modelos destacan en distintos roles. GPT-5.2 planifica mejor que GPT-5.1-Codex, aunque este último está entrenado específicamente para programación. Ahora usamos el modelo más adecuado para cada rol en lugar de un único modelo universal.

Muchas de nuestras mejoras vinieron de eliminar complejidad en lugar de añadirla. Al principio creamos un rol de integrador para el control de calidad y la resolución de conflictos, pero descubrimos que generaba más cuellos de botella de los que resolvía. Los workers ya eran capaces de gestionar los conflictos por sí mismos.

El mejor sistema suele ser más simple de lo que cabría esperar. Al principio intentamos modelar sistemas basados en la computación distribuida y el diseño organizativo. Sin embargo, no todos funcionan para los agentes.

La cantidad adecuada de estructura está en algún punto intermedio. Con muy poca estructura, los agentes entran en conflicto, duplican trabajo y se desvían. Demasiada estructura crea fragilidad.

Una parte sorprendentemente grande del comportamiento del sistema depende de cómo hacemos prompt a los agentes. Conseguir que se coordinen bien, eviten comportamientos patológicos y mantengan el foco durante largos periodos requirió una amplia experimentación. El harness y los modelos importan, pero los prompts importan más.

Qué sigue

La coordinación multiagente sigue siendo un problema difícil. Nuestro sistema actual funciona, pero está lejos de ser óptimo. Los agentes planificadores deberían activarse cuando sus tareas terminan para planificar el siguiente paso. A veces, los agentes se ejecutan durante demasiado tiempo. Seguimos necesitando reinicios periódicos para combatir la deriva y la visión de túnel.

Pero la pregunta clave —si podemos escalar la programación autónoma asignando más agentes a un problema— tiene una respuesta más optimista de lo que esperábamos. Cientos de agentes pueden trabajar juntos en una sola base de código durante semanas, logrando avances reales en proyectos ambiciosos.

Las técnicas que estamos desarrollando aquí acabarán influyendo en las capacidades del Agente de Cursor. Si te interesa trabajar en los problemas más difíciles del desarrollo de software asistido por IA, nos encantaría saber de ti en hiring@cursor.com.