Todos se preguntan: "¿Qué rayos es un loop?" Pero hay una pregunta que nadie se hace: ¿qué ejecuta el loop?
El discurso sobre IA ha convergido en los loops como primitiva central de los sistemas agentivos. Matt Van Horn (@mvanhorn) trazó el linaje de los agent loops desde ReAct hasta el uso de herramientas, los loops de orquestación y los loops supervisando loops. Addy Osmani (@addyosmani) desglosó los componentes internos de los loops: automatizaciones, worktrees, skills, conectores, subagentes. Van Horn se centró en la durabilidad, argumentando que los loops que no sobreviven un reinicio no son loops. El hilo clave de Osmani fue la orquestación: diseñar el sistema que le da instrucciones al agente en lugar de hacerlo tú.
Quiero llevar sus ideas más allá. La durabilidad no es solo una propiedad del loop. Es toda la capa de ejecución que lo sostiene. El dato importante es que la orquestación duradera es fundamental para construir tu arquitectura de agent loops. Analicemos esa arquitectura.
Dónde fallan los loops
Los patrones /loop y /goal manejan bien el trabajo de un solo agente y una sola sesión. Un agente itera hasta que la tarea está hecha. Eso cubre mucho terreno. Pero la siguiente etapa (Etapa 5 en el marco de Van Horn) es donde se desmorona:
- Loops supervisando otros loops
- Loops ejecutándose con horarios, no solo activados por un humano
- Loops que sobreviven reinicios de procesos, despliegues y caídas
- Loops que generan subagentes y esperan resultados (a veces horas después)
- Loops que deben ser observables a posteriori
Eso no es un problema de prompting. Es un problema de infraestructura.
Van Horn cita a @runes_leo: "Lo más costoso en la programación con IA ya no es escribir código, sino gestionar el loop del agente." Un while True en una terminal no te da nada de esto. Tampoco lo hace un proceso de larga duración en una máquina virtual o sandbox.
Piensa en lo que sucede cuando ejecutas un loop de agente en un servidor. El proceso morirá o se reiniciará. Un despliegue, un OOM, una reclamación de instancia spot. El loop se reinicia. Pero, ¿qué estaba haciendo? ¿En qué paso iba? ¿Ya envió ese mensaje de Slack? ¿Ya invocó al subagente?
No lo sabes. Empieza de nuevo. Vuelve a obtener datos que ya tenía. Vuelve a llamar al LLM por decisiones que ya tomó. Envía una notificación duplicada. Genera un subagente duplicado. Te despiertas con tres mensajes idénticos de Slack y un equipo confundido.
La solución no es "mejor manejo de errores": es un modelo de ejecución donde cada paso tiene checkpoint, cada decisión se persiste y la recuperación significa retomar desde el último paso exitoso.
La arquitectura del agent loop en tres capas
Tres capas. Cada una se asigna a una primitiva concreta.
Capa 1: El Loop
Un loop es un cron más un tomador de decisiones. Se ejecuta según un horario (o un disparador), evalúa el estado y decide qué hacer a continuación.
Esta es la definición de Van Horn hecha concreta: lo que nunca tuvo cron es la decisión en el medio. El agente decide, no tú. El cron es el latido. El LLM es el tomador de decisiones. Los pasos son la ejecución duradera que checkpointea el progreso.
1export const infraHealthCheck = inngest.createFunction(2 { id: "infra-health-check" },3 { cron: "*/30 * * * *" }, // Cada 30 minutos4 async ({ step }) => {5 const metrics = await step.run("fetch-service-metrics", async () => {6 return await fetchServiceMetrics(); // tasas de error, latencia, memoria, CPU7 });89 const assessment = await step.run("assess-health", async () => {10 return await callLLM({11 prompt: `Dadas estas métricas de servicio, clasifica la salud general del sistema12 como "normal", "degradada" o "crítica". Explica tu razonamiento.13 Métricas: ${JSON.stringify(metrics)}`,14 });15 });1617 if (assessment.status === "degraded" || assessment.status === "critical") {18 await step.invoke("triage-incident", {19 function: incidentTriage,20 data: { metrics, assessment, services: assessment.affectedServices },21 });22 }23 }24);
Cada lunes a las 9 a.m., el loop se activa. Obtiene datos, pregunta al LLM si vale la pena generar un informe e invoca una skill si es así. Si el proceso se reinicia entre pasos, los pasos ya completados no se reejecutan. Eso es el loop. No el LLM, el loop alrededor del LLM.
Capa 2: La Skill
En este contexto, una skill no es un prompt. Es un flujo de trabajo duradero. Multietapa, reintentable, componible, desplegable de forma independiente.
Van Horn: "El loop es la tubería. El activo es la skill a la que llama." Esta es la parte que se acumula. Cada nueva skill que el sistema aprende hace que cada loop sea más capaz.
1export const incidentTriage = inngest.createFunction(2 { id: "incident-triage", retries: 3 },3 { event: "infra.incident.triage" },4 async ({ event, step }) => {5 const details = await step.run("fetch-detailed-metrics", async () => {6 return await fetchDetailedMetrics({ services: event.data.services });7 });89 const deploys = await step.run("fetch-deploy-history", async () => {10 return await fetchRecentDeploys({ since: hoursAgo(2) });11 });1213 const analysis = await step.run("correlate-incident", async () => {14 return await callLLM({15 prompt: `Correlaciona estas métricas de servicio con los despliegues recientes.16 Identifica la causa raíz probable y la gravedad.17 Métricas: ${JSON.stringify(details)}18 Despliegues recientes: ${JSON.stringify(deploys)}`,19 });20 });2122 await step.run("post-triage-summary", async () => {23 await slack.postMessage({24 channel: "#incidents",25 text: formatTriageSummary({26 analysis,27 affectedServices: event.data.services,28 recommendedActions: analysis.recommendations,29 }),30 });31 });3233 return analysis;34 }35);
Esta skill obtiene, clasifica y enruta. Es una unidad de trabajo con tolerancia a fallos incorporada. La skill puede ser un flujo de trabajo de IA con un LLM en medio o código determinista.
Capa 3: El Orquestador
El orquestador es el motor que lo ejecuta todo: programa crons, ejecuta pasos, gestiona reintentos, impone límites de concurrencia, almacena el historial de ejecuciones y despliega en caliente nuevas funciones/flujos de trabajo sin interrumpir los que están en ejecución.
Esta es la capa de la que nadie habla porque se supone que debe ser invisible. Pero es fundamental.
La mayoría piensa en los agentes como "LLM + herramientas". La arquitectura del agent loop replantea esto: los agentes son "loops + skills + orquestación". El LLM y las herramientas están dentro de los loops. Los LLM y las herramientas se pueden intercambiar o modificar mientras la arquitectura permanece. La orquestación permite la arquitectura.
Qué sucede cuando las cosas fallan
El camino feliz es fácil. Pero esto es software en producción: ¿acaso las cosas siempre salen según lo planeado?
Tu skill de triaje de incidentes se dispara y la API de métricas se agota. La lectura tuvo que ir a disco y la caché en memoria no tenía los datos. El paso que llama a esta API ahora reintenta y vuelve a llamar a la API. Los datos ahora están parcialmente en caché y la API se completa. La skill continúa con el siguiente paso como si nada hubiera pasado.
A veces, no es tan simple. ¿Qué pasa si una clave API expira o tu proveedor de hosting está caído durante 30 minutos? Todos tus reintentos se agotan. ¿Y ahora qué? También tienes que manejar los fallos.
1export const incidentTriage = inngest.createFunction(2 {3 id: "incident-triage",4 retries: 3,5 onFailure: async ({ error, event, step }) => {6 // La función falló después de agotar los reintentos.7 // Aún tenemos los datos del evento original. No se pierde nada.8 await step.run("notify-failure", async () => {9 await slack.postMessage({10 channel: "#agent-ops",11 text: `⚠️ El triaje de incidentes falló: ${error.message}. ` +12 `Se reintentará en el próximo ciclo de verificación de salud. ` +13 `Servicios afectados: ${event.data.services.join(", ")}`,14 });15 });16 },17 },18 { event: "infra.incident.triage" },19 async ({ event, step }) => {20 /* la misma lógica que la skill anterior */21 }22);
El manejador onFailure se dispara después de que se agoten todos los reintentos. Publica en un canal de operaciones para que alguien se entere. El evento se conserva, no se pierde nada. La siguiente ejecución programada retoma donde la fallida no pudo.
La orquestación duradera debe darte reintentos a nivel de paso para errores transitorios y ganchos de manejo de fallos para errores no recuperables. Sin esto, las cosas fallan (como sucede) y te enteras horas o días después.
Los errores transitorios también son costosos. Si tu skill o agente reintenta desde el principio, estás llamando a los LLM varias veces y quemando tokens innecesariamente. La llamada al LLM se puede checkpointear. Ahora multiplica esto por 10 o 30 agentes en todo tu sistema. Es costoso.
El checkpointing a nivel de paso no es solo una característica de corrección. Es un ahorro de dinero.
El agente que construye sus propias skills
Aquí es donde se pone más interesante. El sistema no es estático; está diseñado para evolucionar y extenderse a sí mismo.
El agente no solo se ejecuta dentro de loops: crea nuevos loops y los registra en el motor de orquestación. Cada función desplegada es una skill duradera que se ejecuta de forma independiente, se puede activar desde un loop o agente o ejecutar con un horario, con su propia lógica de reintento. Las skills se acumulan.
Es un agente consciente de la orquestación.
Así es como funciona. Un agente de IA tiene acceso al SDK de orquestación como herramienta. Puede escribir nuevas funciones, registrarlas en el motor y comienzan a ejecutarse de inmediato. El proceso del agente recarga en caliente nuevas funciones sin reiniciar ni interrumpir las ejecuciones en curso.
Veamos un ejemplo concreto:
1. Un humano expresa una necesidad. Un ingeniero dice: "Nuestros servicios siguen teniendo picos de latencia durante la noche y nadie se da cuenta hasta la mañana." Eso es el disparador. El agente no necesita inferir un patrón vago a partir de datos ambientales. Tiene instrucciones claras.
2. El agente escribe una skill. Dos funciones multietapa: un loop de verificación de salud que se ejecuta cada 30 minutos, obteniendo tasas de error, latencia y uso de recursos, con el LLM clasificando la salud del sistema como normal, degradada o crítica. Y una skill de triaje de incidentes que obtiene métricas detalladas e historial de despliegues recientes, correlaciona causas raíz con un LLM y publica un resumen de triaje en Slack con acciones recomendadas. Manejo de errores: si la API de métricas está caída, espera y reintenta. Si el LLM falla, recurre a una clasificación de gravedad basada en reglas.
3. El agente despliega la skill. El agente escribe el código de la función que un proceso sidecar recoge. Las nuevas funciones se registran automáticamente. Están activas de inmediato, sin canal de despliegue, sin PR.
4. La skill se ejecuta de forma autónoma. Cada 30 minutos, el motor activa la verificación de salud. Si algo está mal, invoca la skill de triaje. Sin humanos en el loop. Totalmente duradero.
5. El agente itera según las señales. Esta es la parte que la gente pasa por alto, así que seamos específicos sobre qué significa "iterar". El agente no nota patrones mágicamente. Tiene un loop de revisión separado: una función activada por cron que se ejecuta semanalmente, lee el historial de ejecuciones del orquestador y evalúa el rendimiento:
1export const reviewSkillPerformance = inngest.createFunction(2 { id: "review-skill-performance" },3 { cron: "0 10 * * 5" }, // Cada viernes a las 10 a.m.4 async ({ step }) => {5 const runs = await step.run("fetch-run-history", async () => {6 return await getInngestRuns({7 functionId: "incident-triage",8 since: daysAgo(7),9 });10 });1112 const analysis = await step.run("analyze-performance", async () => {13 const successRate = runs.filter(r => r.status === "completed").length / runs.length;14 const avgDuration = average(runs.map(r => r.duration));15 const incidents = await fetchIncidentOutcomes(); // ¿Los incidentes se correlacionaron con caídas reales?1617 return await callLLM({18 prompt: `Revisa el rendimiento de esta skill durante la última semana.19 Tasa de éxito: ${successRate}20 Duración promedio: ${avgDuration}ms21 Incidentes correlacionados con caídas reales: ${incidents.confirmed}/${incidents.total}22 Falsos positivos: ${incidents.falsePositives}23 El equipo actuó sobre las alertas: ${incidents.actedOn}/${incidents.total}2425 ¿Deberíamos ajustar los umbrales o la clasificación? ¿Qué cambios específicos?`,26 });27 });2829 if (analysis.shouldModify) {30 await step.invoke("update-skill", {31 function: coreAgent,32 data: { prompt: `Actualiza las skills de triaje de incidentes según los siguientes cambios propuestos: ${analysis.proposedChanges}` },33 });34 }35 }36);
La "revisión" es una función. Lee el historial de ejecuciones, verifica si los incidentes se correlacionaron con caídas reales y alimenta esa señal al LLM. Si la verificación de salud sigue marcando un servicio como degradado pero el equipo lo ignora porque los umbrales son demasiado sensibles, el loop de revisión lo detecta y la skill se actualiza para ajustar la clasificación. No es magia. Es un cron job con un LLM en el asiento de la decisión.
¿Qué pasa con la validación? El agente que escribe código es tan bueno como las barreras de seguridad que lo rodean. El código se puede verificar con tipos. El agente puede invocar la función él mismo para probarla, ya que puede interactuar con el propio motor de orquestación. Aunque no es infalible, le estás dando al agente central la capacidad de depurar las skills que escribe de forma nativa dentro del sistema en el que opera. El loop de revisión detecta problemas que no se detectan en la depuración inicial.
Llevando esto un paso más allá, el agente puede usar hooks onFailure para activarse a sí mismo y evaluar un fallo determinado. Es un bucle de retroalimentación que mejora continuamente.
¿Qué pasa con los conflictos? Los controles de flujo, específicamente los controles de concurrencia o singleton, manejan el caso simple (concurrency: { limit: 1, key: "[event.data.service" }]), lo que significa que solo se ejecuta un triaje de incidentes a la vez por servicio. Pero la pregunta más profunda es: ¿qué pasa si dos verificaciones de salud detectan problemas en el mismo servicio simultáneamente? El orquestador los pone en cola. El segundo triaje espera hasta que el primero termine. Sin alertas duplicadas, sin condiciones de carrera. Esto no es teórico. Es la misma primitiva de concurrencia que usarías en cualquier cola de trabajos.
El agente no solo está ejecutando tareas. Está construyendo infraestructura para sí mismo. Cada skill duradera persiste más allá de la conversación que la creó. Mata el proceso del agente y reinícialo. Las skills siguen ejecutándose. Cambia el modelo subyacente. Las skills siguen ejecutándose. El agente es efímero; su resultado es duradero.

Descripción general del sistema de arquitectura del agent loop
La perspectiva del desarrollador
Esto es importante porque si el desarrollador no puede ver lo que el agente desplegó, depurar lo que falló y auditar lo que se ejecutó a las 3 a.m., toda la arquitectura es un gran lastre.
El motor de orquestación almacena cada ejecución, cada paso, cada entrada, cada salida, cada reintento. ¿Una skill que el agente desplegó el martes pasado falló a las 4 a.m.? Puedes ver exactamente qué paso falló, cuál fue la entrada, qué error lanzó y cuántas veces reintentó antes de rendirse. Trazas completas hasta el nivel de paso son la salida del propio motor de orquestación.
Esto no es un panel añadido a posteriori. Es inherente a la ejecución duradera. Cada step.run() es un checkpoint. Cada checkpoint es observable. Cuando quien escribió el código no es un humano, la observabilidad no es un lujo: es la capa de confianza.
En el día a día, el flujo de trabajo del desarrollador es así: revisa el panel de ejecuciones por la mañana. Ve qué skills se ejecutaron durante la noche, cuáles tuvieron éxito, cuáles fallaron. Si una skill que escribió el agente se comporta mal, puedes leer el código directamente, editarlo, eliminarlo o decirle al agente que lo arregle. El agente lo creó, pero tú lo posees. El agente y sus skills siguen siendo un jardín que debes cuidar.
Por qué la durabilidad es fundamental
Van Horn: "Estas cosas tienen que sobrevivir a un reinicio."
Esto es lo que significa la durabilidad en la práctica:
Requisito
Qué significa
Por qué falla un while loop básico
Reintento independiente de pasos
Si el paso 3 de 5 falla, reintenta el paso 3, no los pasos 1 y 2
Un reinicio del loop reejecuta todo desde cero
Ciclo de vida de subagentes
Generar una tarea hija, esperarla (quizás horas), cancelarla si el padre se cancela
No hay gestión incorporada del ciclo de vida padre-hijo
Entrega garantizada de eventos
Si un evento se dispara mientras el agente está caído, debe procesarse igual
Los eventos se pierden si el proceso no está ejecutándose
Observabilidad a posteriori
Ver lo que sucedió después: cada paso, cada decisión, cada reintento
Los logs son tu única opción y son efímeros
Despliegue en caliente sin tiempo de inactividad
Desplegar una nueva versión de la función sin matar las ejecuciones en curso
El reinicio del proceso lo mata todo
Control de concurrencia
Ejecutar solo N instancias de una skill a la vez
No hay primitivas de concurrencia incorporadas
"Ejecútalo en un contenedor" te da tiempo de actividad. No te da corrección. Un contenedor que se reinicia después de un fallo trae el proceso de vuelta, pero cada loop en curso empieza de nuevo. Cada paso se reejecuta. Cada llamada al LLM se rehace. El loop parece estar ejecutándose, pero lo hace a ciegas.
Comparación con herramientas existentes
Algunas herramientas pueden ofrecerte una solución "bonita" llave en mano para este tipo de sistema, o quizás prefieras combinar herramientas de nivel más bajo y crear tu propio sistema. Ninguna opción es incorrecta, pero la capa de arquitectura adecuada debería permitirte a ti, y a tu agente, evolucionar con el tiempo. Flexible, dinámica, duradera.
Primitivas de ejecución duradera que encajan bien para un agente, que un agente puede escribir fácilmente, y la observabilidad y API para observar y permitir que el propio agente sea consciente de la orquestación.
Un ejemplo funcional
Estamos probando estos patrones internamente en Inngest y puedes ver un concepto de esto en el repositorio del proyecto "utah" aquí: https://github.com/inngest/utah: Es un harness de agente construido sobre la orquestación duradera de Inngest que también es consciente de la orquestación.
El sistema tiene un proceso sidecar que permite al agente principal escribir y editar funciones de Inngest en su propio espacio de trabajo, extendiéndose a sí mismo con "skills" (en el contexto de este artículo). Pronto planeamos proporcionar un sistema completo con loops de inicio como ejemplos, pero las ideas allí pueden demostrar las ideas de este artículo de forma más clara.
El loop que se acumula
La publicación reciente de Satya Nadella nombró algo que la industria venía sintiendo: el foso no es el modelo, es el loop.
Su planteamiento: hay dos tipos de capital. Capital humano, el conocimiento y juicio que tu equipo ha construido durante años. Y lo que llama capital de tokens, los flujos de trabajo de IA, patrones de decisión y skills aprendidas que una empresa construye sobre modelos fundacionales.
La tesis: estos se combinan. Cada flujo de trabajo mejorado genera mejores señales. Mejores señales producen un comportamiento de IA más preciso. Un comportamiento más preciso libera atención humana para trabajo de mayor juicio. Una máquina de escalada de colinas.
Esto es lo que la arquitectura del agent loop permite de forma concreta:
- Cada skill duradera que el agente despliega es conocimiento institucional codificado como infraestructura ejecutable. Persiste. Se ejecuta haya o no un humano observando.
- Un loop de revisión activado por cron que evalúa el rendimiento de la skill e itera. Esa es la máquina de escalada de colinas hecha realidad. No un diagrama de volante en una presentación. Una función con un disparador cron.
- Si tus skills mueren al reiniciar el proceso, la acumulación se reinicia a cero. La durabilidad es lo que hace que la inversión persista.
El punto clave de Nadella: "Una empresa debería poder cambiar un modelo 'generalista' sin perder la experiencia de 'veterano de la empresa' incorporada en su sistema de aprendizaje." Ese es el patrón de la biblioteca de skills. Las funciones duraderas no se preocupan de qué LLM las llama.
Construye en consecuencia
La conversación ha girado en torno a lo que hacen los agentes: loops, herramientas, razonamiento, ingeniería de contexto. La próxima conversación es sobre qué ejecuta los agentes.
Tres capas: loop, skill, orquestador. El loop es la unidad de trabajo. La skill es el activo. El motor de orquestación es lo que hace que ambos sean duraderos. El patrón sidecar es el modelo: un agente escribe sus propias skills duraderas, las despliega, revisa cómo funcionan e itera. No es un experimento mental. Es un modelo funcional.
Construimos Inngest para que sea el motor de orquestación para esto: step.run(), step.invoke(), disparadores cron, flujo de control basado en eventos, controles de concurrencia y observabilidad completa a nivel de paso. Pero el patrón de arquitectura es más grande que cualquier herramienta individual. Si estás construyendo agent loops en producción, define las tres capas.
Las primitivas existen hoy. Construye en consecuencia.





