Cómo reemplacé un daemon de polling con Trigger.dev para orquestar agentes de IA

Tengo un problema recurrente: paso demasiado tiempo supervisando agentes de IA.
No me refiero a corregir sus errores — eso es esperado. Me refiero al trabajo operativo de mantenerlos corriendo: verificar que el proceso sigue activo, revisar logs dispersos en archivos, reiniciar servicios que se cayeron sin aviso.
Es irónico: automatizo para no hacer trabajo manual, y termino haciendo trabajo manual para mantener las automatizaciones.
La inspiración: agent-worker
Hace unas semanas encontré un proyecto open source que me voló la cabeza: agent-worker de Owain Lewis.
La tesis es elegante: defines el trabajo en tu issue tracker (el gestor de tareas que uses), el agente lo toma automáticamente, lo ejecuta con Claude Code o Codex, y abre el PR cuando termina. Tú no intervienes.
Es exactamente lo que quería. Un sistema donde yo defino qué hay que hacer, y el agente se encarga del cómo.
Pero agent-worker tiene un problema de arquitectura.
Para detectar tickets nuevos, implementa un polling loop propio — un proceso daemon corriendo 24/7, preguntando cada N segundos: "¿hay algo nuevo en el tracker?". Si lo hay, dispara el agente.
Eso implica:
- Hostear el proceso en algún servidor
- Monitorearlo para saber si sigue vivo
- Configurar alertas manuales si se cae
- Manejar reintentos cuando falla una tarea
Es infraestructura de background jobs. Funciona, pero es infraestructura que tengo que mantener yo.
El insight: el polling loop ya existe
Entonces me di cuenta: esa infraestructura ya existe. Se llama Trigger.dev.
Trigger.dev es una plataforma de background jobs y task scheduling para TypeScript. En lugar de escribir tu propio loop de polling, usas su scheduler nativo. En lugar de configurar reintentos manuales, activas el backoff automático. En lugar de parsear logs en archivos, tienes un dashboard con historial completo.
La comparación es directa:
| Aspecto | Daemon propio | Con Trigger.dev |
|---|---|---|
| Scheduling | Loop manual con setTimeout | Cron nativo en el dashboard |
| Reintentos | Configuración manual | Automático con backoff |
| Observabilidad | Logs en archivo | Dashboard con historial |
| Alertas de fallo | Ninguna por defecto | Slack/email integrado |
| Deploy | Proceso siempre activo | Serverless, sin infra |
| Múltiples repos | Un proceso por repo | Un proyecto, múltiples jobs |
En lugar de construir esa infraestructura, la uso — y me enfoco solo en la lógica del agente.
La arquitectura de GNB Labs
Así quedó el sistema que estoy construyendo:
El repo principal de GNB Labs contiene Trigger.dev. Desde ahí, un router de contexto decide qué tipo de job ejecutar:
- Jobs internos (GNB): diario técnico, posts de LinkedIn, sincronización de documentación
- Shared jobs: webhooks, notificaciones, sincronizaciones genéricas
- Jobs de clientes: cada cliente tiene su propio contexto, diferenciado por PROJECT_ID
Los repos de clientes no tienen Trigger.dev instalado. El orquestador central los lee vía GitHub API cuando necesita ejecutar trabajo en ellos.
La decisión: repo central vs. distribuido
Antes de llegar a esta arquitectura, tuve que decidir entre dos opciones:
Opción A — Repo central:
- Un solo deploy de Trigger.dev
- Jobs compartidos reutilizables
- Un lugar para ver todo
- Pero: acoplamiento entre proyectos, requiere subtree/submodule
Opción B — Repo por proyecto:
- Aislamiento total por cliente
- Deploy independiente
- Sin side effects cruzados
- Pero: duplicas boilerplate, múltiples deploys a mantener
La recomendación que seguí: Opción A para proyectos internos, Opción B si cada proyecto es de un cliente diferente con requerimientos de aislamiento estricto.
Como la mayoría de mis clientes son proyectos donde tengo acceso al código y no hay restricciones de compliance, opté por el repo central con contexto por PROJECT_ID.
El flujo técnico
Así funciona cada ciclo:
1. Trigger.dev dispara un job según el schedule configurado
2. El job consulta el issue tracker por tickets en estado "Todo"
3. Por cada ticket:
→ Marca "In Progress"
→ Crea worktree git aislado (agent/task-{id})
4. Invoca Claude Code con título + descripción del ticket como prompt
5. Post-hooks: git add → git commit → git push → gh pr create
6. Marca el ticket "Done" o "Failed" con comentario automático
El detalle clave es el worktree aislado. Si tres agentes corren en paralelo en el mismo repo, necesitan branches separados que no se pisen. Git worktrees resuelven eso: cada agente trabaja en su propio directorio con su propio estado de git.
Qué sigue
El sistema está en construcción. Los próximos pasos:
- Extender a otros trackers: GitHub Issues, Airtable, Asana, ClickUp
- Agregar validación pre-merge: correr tests antes de marcar como Done
- Pipeline de review: un segundo agente que revisa el PR antes de notificarme
La promesa es simple: defino el trabajo en el tracker, y cuando vuelvo a mirar, el PR ya está listo para review.
Zero babysitting.
Crédito: La inspiración viene de agent-worker de Owain Lewis. El concepto de "define el trabajo en el tracker, el agente lo ejecuta" es suyo. Lo único que hice fue reemplazar la infraestructura de polling con algo que ya existía.
Recursos
- Trigger.dev — ficha de herramienta
- Mi Primer Empleado de IA — el programa para construir tu primer agente
- Claudia en acción — cómo opera este sitio con IA

Gabriel Neuman
Consultor en Automatización e IA con más de 15 años de experiencia. Ayudo a dueños de negocios a recuperar su tiempo mediante sistemas que trabajan solos. Fundador de GNB Labs y apasionado por el NoCode.
¿Listo para automatizar tu negocio?
Ayudo a empresas a escalar mediante automatización inteligente y estrategias de IA. Sin fricción, sin complicaciones, resultados en semanas.


