Hace tiempo que vengo trabajando en GalopApp, mi pet project. Para ponernos en contexto, GalopApp es una plataforma integral para el seguimiento del turf (hípica) en España. Su gracia reside en combinar un dataset histórico relacional complejo (carreras, pedigríes, entrenadores) con Inteligencia Artificial (LightGBM y Gemini) para generar crónicas previas y predecir la probabilidad de victoria de cada caballo.
Es un proyecto con backend en FastAPI, frontend en React, bases de datos en MySQL y despliegues automáticos. Construir y mantener todo esto requiere tiempo, así que decidí experimentar delegando el desarrollo a agentes de IA.
He reescrito la app varias veces, usando diferentes harness (OpenCode, Claude, Antigravity)… Sin embargo, trabajar con agentes «en crudo» es un proceso caótico: les pides algo, se pierden en su propio contexto, sobreescriben cosas sin querer o simplemente alucinan sobre el estado del código.
Para solucionar esto, decidí montar mi propia «factoría de software» local usando pi (pi.dev) como arnés. El objetivo: crear un equipo de agentes especializados que trabajen de forma asíncrona, robusta y coordinada.
La topología del equipo y la diversidad de LLMs
Mi setup consiste en una sesión de tmux dividida en varios paneles. Cada panel está habitado por un agente con un rol hiper-especializado.
Aquí hay una decisión de diseño fundamental: no todos los agentes usan el mismo LLM. La experiencia me ha enseñado que si le pides a un LLM que analice el código que él mismo acaba de escribir, suele ser mucho más beningno (y ciego a sus propios fallos) que si se lo pides a un modelo distinto. Por eso, el equipo intercala diferentes modelos (suscripciones):
- Panel 1 – El Planificador (Claude): Es el analista funcional. Convierte mis peticiones en Issues de GitHub estructuradas, con criterios de aceptación claros.
- Panel 2 – El Programador (GLM): Es el obrero. Toma una Issue, crea un
git worktreecon una rama nueva (nunca tocamain), escribe el código, pasa los tests locales y abre un Pull Request (PR). No puede aprobar ni hacer merge. - Panel 3 – Revisor de Seguridad (Kimi): Es la Puerta 1. Audita el PR buscando exclusivamente brechas: manejo de JWT, validación de inputs, inyecciones SQL o secretos hardcodeados.
- Panel 4 – Aprobador de Calidad (Kimi): Es la Puerta 2. Actúa como un Senior Developer. Revisa la legibilidad, casos borde y tests. Solo actúa si la Puerta 1 dio luz verde.
Al frente de todos ellos, también dentro de su propio panel en tmux, está el Orquestador. Este agente no escribe código, sino que delega el trabajo enviando instrucciones al resto de paneles mediante comandos bash (tmux send-keys).
La magia de tmux: un equipo que trabaja mientras duermes
Otra de las grandes ventajas de este enfoque es la propia infraestructura subyacente: tmux.
Al orquestar a los agentes dentro de una sesión de tmux, en realidad están corriendo en un proceso servidor independiente de mi terminal gráfica. Esto significa que puedo conectarme a la sesión para ver cómo debaten y trabajan, y luego desconectarme (detach) tranquilamente.
El equipo de IA se queda trabajando en background, resolviendo PRs e iterando el código, incluso cuando yo no estoy mirando la pantalla. Cuando vuelvo, simplemente leo los resultados.
Git y GitHub CLI (gh) como estado global
El mayor problema de los agentes autónomos es que su memoria (el contexto) se corrompe rápido. Si el Orquestador tiene que recordar en qué estado está cada tarea, fallará.
Para evitarlo, impuse una regla dura: El estado del trabajo vive en GIT, no en el contexto del modelo.
Si el Orquestador necesita saber qué está pasando, no lee los paneles de tmux ni tira de memoria. Hace consultas a la API de GitHub usando la CLI (gh):
bash# ¿Qué tareas hay pendientes?gh issue list --state open# ¿Qué código está esperando revisión?gh pr list --state open# ¿Han pasado los tests de integración y las auditorías?gh pr checks <PR_NUMBER>
Las Puertas (Status Checks) y la Intervención Humana
La comunicación entre los agentes de revisión y el resto del sistema ocurre a través de los Check Runs de GitHub. Cuando el Revisor de Seguridad (Panel 3) analiza un PR, ejecuta comandos de la API para dejar constancia de su veredicto de forma programática:
bashSHA=$(gh pr view <PR_NUMBER> --json headRefOid --jq '.headRefOid')gh api repos/{owner}/{repo}/statuses/$SHA \ -f state=success \ -f context=security-review \ -f description="Sin hallazgos bloqueantes"
El Aprobador de Calidad (Panel 4) tiene instrucciones estrictas de no empezar a revisar hasta que el status de security-review sea success. Si todo está verde (incluyendo el CI tradicional), ejecuta el merge automático.
Adaptabilidad: El humano en el bucle
Actualmente, el flujo que he definido para GalopApp es completamente autónomo, culminando en un merge automático sin revisión humana.
Sin embargo, la belleza de basar todo el estado en GitHub PRs es la adaptabilidad. Este flujo se puede modificar trivialmente para cualquier proyecto o nivel de riesgo: bastaría con quitarle los permisos de merge al Panel 4 y dejar el PR abierto. De este modo, los agentes hacen todo el trabajo duro de programación, testeo y code review previo, pero el botón de «Merge» final queda reservado exclusivamente para la mano humana.
Conclusión
Delegar en agentes no significa darles barra libre. Al forzarles a utilizar los mismos flujos de trabajo asíncronos y herramientas que usamos los humanos (Git, Issues, PRs, Status Checks), y combinar distintos LLMs para evitar sesgos de autoevaluación, conseguimos mitigar sus principales debilidades.
Al final, mi factoría local funciona exactamente igual que un equipo asíncrono remoto tradicional. La única diferencia es que el equipo trabaja 24/7 y vive en sesiones de tmux en mi ordenador.