Ejecución duradera de agentes con Temporal
Índice de contenidos
- Puntos clave
- ¿Por qué los agentes largos fallan a mitad?
- ¿Qué es la ejecución duradera?
- Temporal: workflows y actividades
- Un agente que sobrevive a reinicios
- Temporal frente a colas simples
- Preguntas frecuentes
- ¿Necesito un servidor de Temporal para usar la ejecución duradera?
- ¿Sirve Temporal solo con OpenAI o con cualquier modelo?
- ¿Qué diferencia hay entre un workflow y una actividad?
- ¿Puedo ejecutar una actividad de Temporal sin workflow?
- Conclusión
- Fuentes
Probado con Temporal Server 1.32.0 · CLI 1.9.1 · Python SDK 1.33.0 · openai-agents 0.19.4 · verificado
Actualizado: 2026-09-16
La ejecución duradera hace que un agente de IA sobreviva a caídas, reinicios y límites de la API sin perder su progreso. Temporal aplica este modelo: tu lógica vive en un workflow que se reanuda justo donde quedó, y cada llamada al modelo o a una herramienta corre como una actividad que se reintenta sola.
La ejecución duradera hace que un agente de IA termine su tarea aunque el proceso falle a mitad de camino. Ese fallo puede ser una caída, un reinicio o un límite de la API. Temporal[1] es la plataforma de código abierto que más ha popularizado este modelo, y tiene integraciones oficiales con el OpenAI Agents SDK, con el AI SDK de Vercel y con Google ADK.
En esta guía verás por qué los agentes largos fallan a mitad y qué es la ejecución duradera. Luego, cómo Temporal separa el trabajo en workflows y actividades y cómo montar un agente que sobrevive a reinicios. Por último, en qué se diferencia de una cola de mensajes y cuándo te basta una actividad suelta (Standalone Activity). La misma explicación está disponible en inglés.
Puntos clave
- La ejecución duradera garantiza, en palabras de la documentación de Temporal, que un workflow «se ejecuta hasta el final, tarde segundos o meses». Si el worker que lo ejecuta se cae, otro reproduce su historial y sigue en la línea donde se quedó.
- Temporal es software libre con licencia MIT y supera las 23 000 estrellas en GitHub. Su servidor estable es la v1.32.0, del 11 de septiembre de 2026, y con ella hemos probado esta guía, junto a la interfaz de línea de comandos (CLI) v1.9.1 y el SDK de Python 1.33.0.
- El modelo separa dos piezas: los workflows (la lógica de orquestación, determinista y reanudable) y las actividades (cualquier llamada externa: al modelo, a una herramienta o a una API), que Temporal reintenta sola cuando fallan.
- La integración oficial con el OpenAI Agents SDK (
temporalio.contrib.openai_agents) pasó a disponibilidad general el 23 de marzo de 2026, tras un adelanto público en julio de 2025. Necesita Python 3.10 o superior y, con temporalio 1.33.0, se instala conpip install "temporalio[openai-agents,opentelemetry]": sin el extraopentelemetry, falla la importación del módulo. - Desde la v1.32.0 del servidor, las Standalone Activities (actividades sin workflow) tienen disponibilidad general.
- Convierte cada agente en un proceso a prueba de caídas sin reescribir tu código: envuelves la lógica del agente en un workflow y las llamadas al modelo se ejecutan como actividades reintentables.
¿Por qué los agentes largos fallan a mitad?
Un agente de IA no es una sola llamada al modelo: es un bucle. El modelo razona, decide invocar una herramienta, lee el resultado, vuelve a razonar y repite el ciclo hasta terminar. Cada vuelta toca el mundo exterior, y ahí está el problema: las herramientas llaman a APIs que a veces fallan, y los modelos chocan con límites de tasa que obligan a reintentar. Cuanto más largo es el agente, más caro resulta empezar la tarea de cero.
Imagina un agente que procesa una devolución: consulta el pedido, valida la garantía, emite el reembolso y notifica al cliente. Si el proceso se cae después de emitir el reembolso pero antes de notificar, ¿qué pasa al reiniciar? Sin protección, o pierdes el trabajo hecho o lo repites y reembolsas dos veces. La guía de la integración de Temporal con OpenAI lo resume así: los modelos «pueden encontrarse con límites de tasa que exigen reintentos», y cuanto más dura el agente, más duele reiniciarlo.
La respuesta habitual funciona: guardar el estado en una base de datos, montar colas, escribir máquinas de estado a mano. Pero llena tu código de fontanería que no tiene nada que ver con la lógica del agente. Es justo el trabajo pesado que la ejecución duradera te quita de encima. Este problema se agrava cuando el agente ya está desplegado en producción, donde un reinicio del contenedor no puede traducirse en una tarea perdida.
¿Qué es la ejecución duradera?
La ejecución duradera es un modelo de programación en el que, una vez arranca, la función principal de tu aplicación llega hasta el final pase lo que pase por debajo. Si el proceso se cae, la máquina se reinicia o la red se cae, el sistema reconstruye el estado exacto en el que estaba y continúa desde ahí, sin repetir el trabajo ya hecho.
El truco está en cómo se consigue esa memoria. Temporal registra cada paso que da tu programa en un historial de eventos durable. Cuando algo falla y el proceso vuelve a levantarse, Temporal reproduce ese historial para reconstruir el estado en memoria y retoma la ejecución justo donde se quedó. Por eso los pasos deterministas (tu lógica) se separan de los no deterministas (las llamadas externas): los primeros se pueden reproducir sin efectos secundarios, los segundos se registran una sola vez.
La documentación de Temporal describe el reparto así: tú escribes la lógica de negocio («llama a este servicio, espera esa aprobación y cobra la tarjeta») y te ahorras la capa que va por debajo. En la práctica, dejas de escribir bloques try/except con reintentos manuales, temporizadores y tablas de estado. Una actividad recibe sus tiempos límite, sus reintentos con espera exponencial y sus latidos (heartbeats) desde la configuración, no desde tu código.
Temporal: workflows y actividades
Todo en Temporal gira en torno a dos abstracciones. Un workflow es la función que contiene tu lógica de orquestación; debe ser determinista, porque Temporal la reproduce para recuperar el estado.
Una actividad es cualquier operación que toca el mundo exterior y que, por tanto, no es determinista. Por ejemplo: una llamada al modelo de lenguaje, una consulta a una API, una escritura en la base de datos. Temporal guarda el resultado de cada actividad completada, no la repite al reproducir el historial y, si un intento falla, la reintenta con la política que definas. Como cada reintento vuelve a ejecutar la función, su código debe ser idempotente.
Aplicado a un agente, el reparto es natural. La lógica del agente (el bucle de razonamiento) vive en el workflow, y cada llamada al modelo o a una herramienta se convierte en una actividad reintentable. En Python, un workflow se marca con el decorador @workflow.defn y una actividad con @activity.defn. Este ejemplo mínimo define una herramienta del tiempo como actividad durable:
from dataclasses import dataclass
from datetime import timedelta
from temporalio import activity, workflow
from temporalio.contrib import openai_agents
from agents import Agent, Runner
@dataclass
class Tiempo:
ciudad: str
rango_temp: str
condiciones: str
@activity.defn
async def consultar_tiempo(ciudad: str) -> Tiempo:
"""Consulta el tiempo de una ciudad (aqui, un valor fijo)."""
return Tiempo(ciudad=ciudad, rango_temp="14-20C", condiciones="Soleado")
@workflow.defn
class AgenteDelTiempo:
@workflow.run
async def run(self, pregunta: str) -> str:
agente = Agent(
name="Asistente del tiempo",
instructions="Eres un agente del tiempo util y conciso.",
tools=[
openai_agents.workflow.activity_as_tool(
consultar_tiempo,
start_to_close_timeout=timedelta(seconds=10),
)
],
)
resultado = await Runner.run(starting_agent=agente, input=pregunta)
return resultado.final_output
La pieza clave es activity_as_tool: coge una actividad de Temporal y la presenta al agente como una herramienta más del OpenAI Agents SDK. El modelo decide cuándo invocarla, pero por debajo se ejecuta con las garantías de durabilidad y reintento de Temporal. La llamada al propio modelo no la escribes tú: el OpenAIAgentsPlugin registra automáticamente una actividad que envuelve cada invocación del modelo. En cambio, activity_as_tool no registra tu actividad en el worker, así que tienes que pasarla en activities, como en el bloque siguiente.
Un agente que sobrevive a reinicios
Para que ese agente se ejecute con durabilidad hacen falta un servidor de Temporal y un worker, el proceso que aloja workflows y actividades y se conecta a ese servidor. Instala el SDK con la integración y arranca un servidor de desarrollo con la CLI:
pip install "temporalio[openai-agents,opentelemetry]==1.33.0"
temporal --version
temporal server start-dev
La CLI responde temporal version 1.9.1 (Server 1.32.0, UI 2.54.1): su servidor de desarrollo ya es la v1.32.0, guarda los datos en memoria y escucha en localhost:7233. El extra opentelemetry no es opcional: con temporalio[openai-agents] a secas, las versiones 1.32.0 y 1.33.0 fallan al importar la integración con ModuleNotFoundError: No module named 'opentelemetry'.
El worker activa el plugin de OpenAI al conectarse al servidor:
import asyncio
from datetime import timedelta
from temporalio.client import Client
from temporalio.worker import Worker
from temporalio.contrib.openai_agents import (
OpenAIAgentsPlugin,
ModelActivityParameters,
)
from agente_tiempo import AgenteDelTiempo, consultar_tiempo
async def main():
cliente = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(
model_params=ModelActivityParameters(
start_to_close_timeout=timedelta(seconds=30)
)
)
],
)
worker = Worker(
cliente,
task_queue="cola-agente-tiempo",
workflows=[AgenteDelTiempo],
activities=[consultar_tiempo],
)
await worker.run()
asyncio.run(main())
Con el worker en marcha, lanza el workflow desde otra terminal y espera su resultado:
temporal workflow start --type AgenteDelTiempo \
--task-queue cola-agente-tiempo --workflow-id tiempo-madrid \
--input '"¿Qué tiempo hace hoy en Madrid?"'
temporal workflow result --workflow-id tiempo-madrid
Results:
Status COMPLETED
Result "Hoy en Madrid hace 14-20°C bajo condiciones soleadas."
ResultEncoding json/plain
El historial de esa ejecución registra tres actividades: la llamada al modelo que elige la herramienta, consultar_tiempo y la llamada que redacta la respuesta. El modelo de la prueba fue qwen3.5:4b en Ollama 0.34.1, sobre CPU arm64 sin GPU y con 6 hilos. El código no cambia: el worker lee OPENAI_BASE_URL, OPENAI_API_KEY y OPENAI_DEFAULT_MODEL del entorno.
La prueba de fuego es matar el worker a mitad de tarea. Lo hemos hecho con kill -9 cuando el agente esperaba la segunda respuesta del modelo, y lo hemos rearrancado un segundo después. El historial conserva la primera llamada al modelo y consultar_tiempo sin repetirlas, y solo la segunda llamada aparece con el intento 2. En tres pruebas, con una carga media de entre 4,6 y 6,0 en 18 núcleos, el resultado llegó unos 33 s después del kill.
Unos 31 s de esos 33 son espera: el servidor no reprograma la llamada al modelo hasta que vence su start_to_close_timeout de 30 s. El worker nuevo la completó después en menos de 2 s.
El mismo tiempo límite falla en sentido contrario cuando el modelo es lento. En una primera ejecución, con la CPU compartida saturada (carga media entre 11 y 37 en 18 núcleos) y el modelo en 18 hilos, ninguna llamada terminó en 30 s. Temporal cortó la actividad siete veces en menos de cinco minutos. Ajusta ese valor a la latencia de tu modelo, o limita los intentos con retry_policy en ModelActivityParameters, porque la política por defecto no tiene tope.
El mismo patrón habilita agentes de larga duración con humano en el bucle. Un workflow puede quedarse esperando una aprobación durante días sin consumir recursos, porque su estado vive en el historial y no en la memoria del proceso.
Si quieres una base sin dependencia de OpenAI, la integración con el AI SDK de Vercel sigue la misma idea en TypeScript, aunque todavía está en vista previa pública. Usas temporalProvider.languageModel() en lugar de openai(), y cada generateText() se envuelve en una actividad de forma transparente. Y si prefieres construir el agente a mano, el enfoque combina bien con el SDK de Anthropic o con grafos como LangGraph.
Temporal frente a colas simples
Es tentador pensar que una cola de mensajes (RabbitMQ, SQS, Redis) resuelve lo mismo, y para una tarea de un solo paso, sin estado intermedio que conservar, basta. La diferencia aparece cuando el agente encadena decisiones. Una cola te da reintentos por mensaje, pero no conoce el flujo: no sabe que ya emitiste el reembolso y solo falta notificar. Tú tienes que reconstruir ese estado a mano, con tablas, banderas de idempotencia y máquinas de estado que crecen sin control.
Temporal invierte el planteamiento: el flujo completo es el código, y el estado se guarda solo. No gestionas colas ni escribes máquinas de estado; escribes una función y el sistema la hace durable. A cambio, introduces un servidor de Temporal en tu arquitectura y aceptas la restricción de que los workflows sean deterministas.
Para un solo paso, Temporal ya no te obliga a salir de su modelo. Desde la v1.32.0 del servidor, las Standalone Activities[2] tienen disponibilidad general: el cliente lanza una actividad sin workflow, y Temporal la encola, la reintenta y la localiza por su ID. Necesitan la CLI 1.9.1 o superior y, en Python, el SDK 1.33.0 o superior. La misma consultar_tiempo del agente sirve tal cual:
import asyncio
from datetime import timedelta
from temporalio.client import Client
from agente_tiempo import consultar_tiempo
async def main():
cliente = await Client.connect("localhost:7233")
tiempo = await cliente.execute_activity(
consultar_tiempo,
"Madrid",
id="tiempo-madrid-suelta",
task_queue="cola-agente-tiempo",
start_to_close_timeout=timedelta(seconds=10),
)
print(tiempo)
asyncio.run(main())
Con el worker anterior en marcha, el script imprime Tiempo(ciudad='Madrid', rango_temp='14-20C', condiciones='Soleado') y temporal activity describe --activity-id tiempo-madrid-suelta muestra el estado Completed. Con una herramienta de prueba que falla dos veces seguidas, describe mostró el intento 3 y el resultado llegó a los 3,02 s. Una actividad suelta no tiene historial que reproducir: resérvala para llamadas aisladas y vuelve al workflow en cuanto encadenes decisiones.
Para un agente que razona, llama a herramientas y puede tardar horas o días, Temporal elimina justo la complejidad que una cola te deja encima de la mesa. En Replay 2026[3], su conferencia de mayo, Temporal presentó los Serverless Workers, la integración con Google ADK y las propias Standalone Activities, entonces en vista previa pública.
Preguntas frecuentes
¿Necesito un servidor de Temporal para usar la ejecución duradera?
Sí. Temporal es un sistema cliente-servidor: tu worker se conecta a un servidor que guarda el historial de eventos y coordina los reintentos. Para desarrollo, temporal server start-dev levanta desde la CLI 1.9.1 un servidor 1.32.0 en memoria; para producción puedes autoalojarlo o usar Temporal Cloud, el servicio gestionado. Sin ese servidor no hay historial que reproducir, así que la durabilidad no existe; es la contrapartida de no tener que escribir tú la persistencia del estado.
¿Sirve Temporal solo con OpenAI o con cualquier modelo?
Sirve con cualquiera: la integración con el OpenAI Agents SDK es la más pulida y llegó a disponibilidad general el 23 de marzo de 2026. Ese SDK admite otros proveedores vía LiteLLM o una API compatible con OpenAI, como el Ollama de nuestra prueba. También hay integraciones con el AI SDK de Vercel para TypeScript y con Google ADK para Python, y siempre puedes envolver a mano cualquier llamada a un modelo en una actividad de Temporal.
¿Qué diferencia hay entre un workflow y una actividad?
Un workflow contiene la lógica de orquestación y debe ser determinista, porque Temporal lo reproduce para recuperar el estado tras un fallo. Una actividad es cualquier operación no determinista o con efectos secundarios, como llamar al modelo, a una API o a la base de datos. Temporal registra su resultado una vez y la reintenta si falla, así que su código debe ser idempotente. La regla práctica: si toca el mundo exterior, va en una actividad; si solo coordina, va en el workflow.
¿Puedo ejecutar una actividad de Temporal sin workflow?
Sí: desde la v1.32.0 del servidor, las Standalone Activities tienen disponibilidad general. El cliente llama a execute_activity() y Temporal encola la tarea, la reintenta y la deja localizable por su ID, sin historial de workflow. Requieren la CLI 1.9.1 o superior y, en Python, el SDK 1.33.0 o superior. Aún no se pueden lanzar desde una programación recurrente (Schedule), así que el trabajo periódico sigue necesitando un workflow.
Conclusión
La ejecución duradera con Temporal convierte un agente frágil en uno a prueba de caídas sin que tengas que escribir la persistencia del estado, los reintentos ni las máquinas de estado. La idea es simple: tu lógica vive en un workflow determinista y reanudable, y cada llamada al modelo o a una herramienta se ejecuta como una actividad reintentable. Con la integración temporalio.contrib.openai_agents en disponibilidad general, el servidor en la v1.32.0 y las Standalone Activities para las tareas de un solo paso, el patrón puede llevarse a producción con garantías. El siguiente paso es instalarlo con pip install "temporalio[openai-agents,opentelemetry]", levantar un servidor de desarrollo y matar tu primer worker a mitad de tarea para verlo recuperarse.
Fuentes
- Temporal
- Standalone Activities
- Replay 2026
- Documentación oficial de Temporal
- Integración del OpenAI Agents SDK en GitHub
- Anuncio de disponibilidad general en el blog de Temporal
- Metadatos del paquete temporalio en PyPI
- Notas de la versión v1.32.0 del servidor de Temporal
- Notas de la versión v1.9.1 de la CLI de Temporal
- Notas de la versión 1.33.0 del SDK de Python
- Integración de Temporal con el AI SDK de Vercel
Código fuente
Accede a todo el código fuente de este artículo en GitHub.
Ver en GitHub