Un agente que responde a una persona y otro que pasa minutos consumiendo tareas no tienen el mismo contrato de ejecución. Ponerlos detrás de una ruta HTTP puede funcionar en un prototipo y crear un problema operativo cuando el loop debe sobrevivir al final de la petición.

Este artículo compara los tres recursos de Cloud Run para tomar esa decisión: Service, Job y worker pool. La pregunta no es qué nombre suena más moderno. Es cómo llega el trabajo, cuándo termina, dónde vive el estado y qué evidencia permite recuperar una ejecución interrumpida.

Diagrama compara un agente de IA con un servicio HTTP, un Job y un worker pool con una cola.

Resultado de la decisión

  • Usa un Service cuando el agente necesita un endpoint, streaming o una respuesta a una petición.
  • Usa un Job cuando cada ejecución tiene un inicio, un final y entradas claras.
  • Usa un worker pool cuando el contenedor debe consumir una cola de forma continua sin atender HTTP.
  • En cualquier opción, persiste el estado y la evidencia fuera del proceso del agente.

La primera pregunta es si el trabajo tiene endpoint

La documentación Qué es Cloud Run separa Service, Job y worker pool por su modelo de ejecución. La primera decisión es directa: si un cliente debe llamar al agente y recibir una respuesta, empieza con Service; si el trabajo se extrae de una cola sin endpoint, evalúa un worker pool.

Esta distinción evita un error habitual en aplicaciones agentic. El agente comienza dentro de una petición, llama a herramientas, espera una respuesta externa y continúa razonando. Si el progreso depende de memoria local o de una conexión HTTP abierta, un reinicio puede dejar la tarea sin dueño.

El agente debe devolver al cliente solo lo que forma parte de la interacción. El resto debe convertirse en una tarea con identificador, estado y evidencia. La orquestación multiagente con TypeScript aplica la misma separación cuando el trabajo ya no cabe en una conversación. La introducción a Google Cloud Run explica el modelo general de la plataforma antes de tomar esta decisión.

¿Qué cambia entre Service, Job y worker pool?

El documento de Google Cloud describe Service como un recurso para endpoints HTTPS y eventos, Job como una ejecución de tareas que termina y worker pool como procesamiento continuo basado en pull, por ejemplo consumidores de Pub/Sub, Kafka o RabbitMQ (Google Cloud, "Qué es Cloud Run"). La tabla convierte esa diferencia en una decisión operativa.

Recurso Entrada principal Final esperado Estado operativo Elección para agentes
Service Petición HTTP o evento Respuesta o entrega del evento Estado fuera de la instancia Chat, API, streaming y creación de tareas
Job Ejecución manual, agenda o workflow Tarea terminada Resultado persistido por ejecución Evals, lotes, migraciones y trabajo finito
Worker pool Cola consumida por el contenedor Trabajo continuo Estado y checkpoint de la tarea Consumidor agentic de larga duración

Un worker pool no es una versión más lenta de un Service. No tiene un endpoint balanceado y no escala automáticamente por sí solo. El equipo debe decidir cuántas instancias permanecen activas y, si hace falta, crear un autoscaler a partir de las métricas de la cola, como explica la documentación de despliegue de worker pools.

Ese coste operativo puede ser correcto si la cola es la frontera que realmente necesitas. Un Service puede escalar con las peticiones, un Job puede esperar otra ejecución y un worker pool necesita una política explícita cuando la cola está vacía. La elección debe hacer visible ese comportamiento.

Cápsula citable: En Cloud Run, Service atiende HTTP y eventos, Job ejecuta tareas hasta terminar y worker pool procesa trabajo continuo sin endpoint. La elección define cómo recibe trabajo el agente, cómo termina una ejecución el sistema y quién controla el escalado, el estado, el retry y la recuperación.

¿Cuándo debe quedarse un agente en un Cloud Run Service?

La documentación Hospedar agentes de IA en Cloud Run incluye streaming HTTP y WebSockets entre las funciones útiles para las interacciones de agentes. Service es la opción adecuada cuando el cliente necesita seguir una respuesta, consultar el estado de una tarea o iniciar una ejecución mediante una API autenticada.

El patrón más seguro separa la petición de la ejecución. La ruta valida la entrada, crea estado duradero y publica un mensaje. Puede devolver el identificador de la tarea sin mantener todo el loop del agente dentro de la conexión del usuario.

type CreateTask = {
  taskId: string;
  prompt: string;
  repository: string;
};

async function createTask(input: CreateTask) {
  await taskStore.create({
    id: input.taskId,
    state: "queued",
    repository: input.repository,
    prompt: input.prompt,
  });

  await queue.publish({ taskId: input.taskId });

  return { taskId: input.taskId, state: "queued" };
}

Este fragmento no convierte el agente en un worker pool. Define una frontera limpia para Service: recibir, validar, persistir y enviar. Otro consumidor se ocupa del loop y actualiza la tarea. Si el agente necesita streaming, Service puede seguir eventos persistidos sin confiar en la memoria de la instancia.

Usa Service cuando el agente funciona como una API de herramientas o como un servidor MCP remoto. Confirma primero el transporte y la autenticación. La documentación de MCP en Cloud Run admite Streamable HTTP, pero no stdio para un servidor que se ejecuta en la nube.

¿Cuándo es Cloud Run Job la opción más limpia?

Job encaja con el modelo descrito en Ejecutar Jobs: una ejecución puede recibir argumentos, variables de entorno, cantidad de tareas y timeout. Úsalo cuando el agente recibe un lote conocido, realiza el trabajo y termina sin quedarse escuchando una cola.

Un eval de agente es un ejemplo claro. El sistema recibe una revisión, un conjunto de casos y una versión del prompt o del código. El Job ejecuta los casos, guarda los resultados y termina. Una nueva ejecución puede usar otro conjunto de entradas sin dejar un proceso permanente esperando trabajo.

gcloud run jobs execute agent-eval \
  --region=REGION \
  --update-env-vars=EVAL_RUN_ID=RUN_ID,INPUT_URI=INPUT_URI \
  --wait

El comando inicia una ejecución del Job y espera a que termine. Sustituye los nombres de ejemplo por valores de tu entorno y concede solo la identidad que necesita ejecutar el recurso. Cuando la duración o las entradas cambian entre ejecuciones, usa los overrides documentados y guarda la configuración junto con el resultado.

No uses un Job para fingir que existe una cola continua. Un scheduler u otro servicio debe iniciar cada ejecución, y el agente debe saber si una tarea ya terminó. Para una cola que recibe trabajo continuamente, esa capa extra indica que conviene evaluar un worker pool.

¿Cuándo compensa el coste operativo de un worker pool?

La documentación de despliegue de worker pools en Cloud Run describe el recurso como una opción para trabajo continuo en segundo plano, sin endpoint balanceado ni escalado automático. Elígelo cuando el contenedor deba extraer trabajo de una cola y seguir procesando mientras existan tareas.

Diagrama muestra una cola, estado persistente, logs y retry como prueba de un loop agentic.

El loop del worker no debe depender de "seguir pensando" dentro de una sola petición. Cada mensaje debe representar una unidad que pueda reservarse, ejecutarse, confirmarse o devolverse para retry.

async function consumeForever() {
  for await (const message of queue.pull()) {
    const lease = await taskStore.claim(message.taskId);

    if (!lease) continue;

    try {
      const result = await runAgent({
        taskId: message.taskId,
        checkpoint: lease.checkpoint,
      });

      await taskStore.complete(message.taskId, {
        result: result.summary,
        evidence: result.evidence,
      });
      await queue.ack(message);
    } catch (error) {
      await taskStore.failAttempt(message.taskId, serializeError(error));
      await queue.nack(message);
    }
  }
}

El código es un contrato de ejecución, no un SDK de colas. claim debe impedir reservas simultáneas, checkpoint debe sobrevivir a un reinicio y complete debe ser idempotente. Sin esas propiedades, un retry del agente puede duplicar un cambio o marcar una tarea como completa después de producir solo texto.

El recurso no escala por sí solo. Google Cloud indica que los worker pools necesitan instancias activas y que el equipo puede crear su propio autoscaler para ajustar la capacidad a la demanda. La profundidad de la cola pasa a formar parte del sistema, no a ser un detalle oculto en el contenedor.

¿Qué debe proteger el despliegue?

La documentación de despliegue exige permisos separados para desarrollar el worker pool, usar su cuenta de servicio y leer la imagen de Artifact Registry (Desplegar worker pools en Cloud Run). La primera barrera es dar al agente solo la identidad que necesita el trabajo.

Diagrama muestra un agente pasando por IAM antes de acceder a una cola, herramientas y logs.

Configura una cuenta de servicio propia para el worker. Si el agente solo lee una cola, concede el permiso de consumo y las lecturas de datos necesarias. Si escribe en un repositorio, base de datos o sistema de despliegue, coloca esa acción detrás de una herramienta estrecha con autorización separada. No concedas acceso administrativo por comodidad.

Mantén separados los secretos y el contexto. Las variables de entorno pueden configurar el proceso, pero el prompt no debe recibir credenciales. La tarea debe cargar solo el contexto necesario para el siguiente paso y guardar logs, checkpoints y evidencias en un sistema apropiado.

Cuando necesito continuidad entre sesiones de Codex y Claude Code sin reenviar el mismo contexto, uso RemoteCode para llevar más lejos los flujos agentic con menos repetición de tokens. Es una herramienta del propio autor, citada porque el presupuesto de contexto forma parte de la arquitectura del loop, no porque sustituya IAM, estado o verificación.

El artículo sobre observabilidad de agentes en CI ayuda a definir los eventos que deben salir del worker: tarea recibida, reserva, llamada de herramienta, checkpoint, error, retry y conclusión. Los logs sin identificador de tarea son difíciles de usar cuando varias instancias trabajan en paralelo.

¿Cómo comprobar que la elección funciona?

El inicio rápido oficial de worker pools verifica el resultado mediante los logs del contenedor, y la documentación de Cloud Run señala Cloud Logging y Error Reporting como integraciones operativas. La verificación debe demostrar algo más que el despliegue: debe probar que el mensaje se procesó y que el estado puede recuperarse.

Haz una prueba pequeña con una tarea descartable y comprueba esta secuencia:

  1. Service o el productor crea una tarea con identificador único.
  2. La cola entrega el mensaje al worker.
  3. El almacenamiento registra la reserva y el checkpoint.
  4. El agente produce evidencia breve; el resumen por sí solo no basta.
  5. El estado cambia a completado y el mensaje se confirma.
  6. Un fallo entre el checkpoint y la confirmación permite un retry sin duplicar el efecto.

Después, interrumpe una ejecución en un punto conocido. El worker debe reiniciarse, encontrar la tarea incompleta y continuar desde un estado explícito. Si la única prueba es un log de una instancia que murió, la arquitectura todavía no está lista.

Usa gcloud run worker-pools list para comprobar que existe el recurso y consulta los logs por identificador de tarea. Para Jobs, guarda el identificador de la ejecución y sus resultados. Para Services, prueba por separado el endpoint y el camino asíncrono. La validación de tool calls en TypeScript aplica la misma disciplina en la frontera entre agente y código.

Cápsula citable: Un agente de larga duración solo está verificado operacionalmente cuando la tarea tiene identificador, el worker registra un checkpoint, la salida contiene evidencia y un retry puede continuar sin duplicar el efecto. Un despliegue correcto demuestra que el contenedor arrancó. No demuestra que el loop sobreviva a un fallo, redelivery o reinicio.

Errores comunes y límites de la comparación

El primer error es elegir worker pool porque el agente parece autónomo. La autonomía del modelo no define el contrato de ejecución. Si existe una petición HTTP clara y una respuesta breve, Service es más sencillo. Si la entrada es finita, Job reduce la superficie operativa.

El segundo es asumir que worker pool incluye escalado automático. La documentación actual dice lo contrario. Debes definir instancias, métricas, política de aumento y reducción y comportamiento cuando la cola está vacía. Si no quieres mantener ese mecanismo, usa Service, Pub/Sub push, Cloud Tasks o Jobs en un flujo que corresponda al trabajo.

El tercero es guardar el estado en el disco local o en memoria. Las instancias son descartables y una revisión nueva puede reemplazar a la anterior. Guarda el progreso en una base de datos, una cola, un almacenamiento de objetos u otro sistema que la recuperación pueda leer.

También existe un límite de producto. Worker pools son una capacidad reciente y la documentación puede cambiar mientras maduran los comandos y las integraciones. Fija la revisión de la imagen, prueba la configuración en un proyecto descartable y confirma región, permisos y condiciones de disponibilidad antes de conectarlo a una operación crítica.

Preguntas frecuentes sobre agentes de IA en Cloud Run

¿Un agente de IA de larga duración necesita un worker pool?

No. Un Service puede iniciar la tarea y devolver un identificador, mientras que un Job puede ejecutar un lote hasta el final. Worker pool encaja cuando el contenedor debe consumir una cola continuamente sin endpoint. La decisión depende de cómo llega el trabajo y de cómo funciona la recuperación, no de medir únicamente la duración del prompt.

¿Un worker pool de Cloud Run tiene una URL pública?

No. La documentación de worker pools describe el recurso sin endpoint balanceado. Eso reduce la superficie HTTP, pero exige otra forma de entregar trabajo, como una cola pull. El agente aún necesita identidad de servicio, permisos estrechos, logs y un mecanismo para actualizar el estado de la tarea.

¿Cuándo es mejor Cloud Run Job que worker pool?

Job es mejor cuando la entrada se puede definir al comienzo y la ejecución debe terminar. Evals, lotes y migraciones son ejemplos. Worker pool es mejor cuando el proceso debe seguir consumiendo una cola. Si un scheduler tiene que lanzar Jobs continuamente para imitar un consumidor, vuelve a evaluar el diseño.

¿Cómo evitar que un retry del agente duplique efectos?

Usa un identificador idempotente por tarea, reserva el mensaje con un lease y escribe un checkpoint antes de repetir una llamada que produzca un efecto. La confirmación debe ocurrir después del estado persistente. Para herramientas de escritura, incluye una clave de idempotencia o una aprobación antes de una operación irreversible.

Fuentes consultadas