Workflow SDK 5: los trabajos largos de IA necesitan un contrato de cancelación

Tech

El problema de un trabajo de IA largo no es solo la espera. El problema aparece cuando nadie puede explicar qué siguió ejecutándose después de cancelar. Un usuario cancela, pero la llamada al modelo continúa; gana un timeout, pero una subida termina igual; una cuota se excede y el retry vuelve a gastar.

El 16 de junio de 2026 Vercel anunció que Workflow SDK 5 beta soporta AbortController y AbortSignal a través de workflows y steps. Con sandboxes de hasta 24 horas, el mensaje es claro: los agentes duran más, por lo tanto deben poder detenerse mejor.

Diagrama de un workflow que pasa señales AbortController a pasos y se cancela por timeout, usuario o cuota
La novedad importante es el contrato operativo: qué paso escucha qué señal, qué devuelve y qué limpieza queda registrada.

Qué cambió

Un workflow puede crear un AbortController, pasar la señal a steps y llamar abort() cuando gana un timeout, un race, un hook externo o una regla de cuota. La documentación indica que la señal sobrevive a suspensiones, replay determinista e invocaciones separadas.

La cancelación es cooperativa: el step debe pasar la señal a fetch, llamar signal.throwIfAborted(), revisar signal.aborted o escuchar el evento.

Por qué importa

OCR, generación de reportes, automatización de navegador, agentes multi-modelo y pruebas E2E necesitan ejecuciones largas. Sin contrato de cancelación, aparecen tokens desperdiciados, APIs llamadas de más y estados ambiguos.

Las preguntas de comunidad sobre producción y cleanup muestran que el punto difícil es operativo.

Impacto operativo

Los timeouts se vuelven política de producto. Los trabajos paralelos pueden cancelar perdedores. Los errores por abort evitan retries, lo que separa cancelación intencional de fallo real.

Checklist

Nombra cada fuente: usuario, timeout, admin, cuota, request padre.

Haz que cada step caro acepte signal y lo use en APIs compatibles.

Distingue run.cancel() de AbortSignal.

Guarda estados cancelled_by_user, timed_out o quota_exceeded.

Prueba limpieza de uploads, jobs externos, correos y webhooks.

Riesgos

Workflow SDK 5 sigue siendo beta/pre-release; úsalo primero en flujos internos y con rollback.

Una señal no deshace efectos remotos ni detiene código que la ignora.

Qué hacer ahora

Dibuja las fronteras de cancelación antes de añadir el botón: costo, side effects y acciones no idempotentes.

Revisión de 30 minutos

Los motivos de cancelación tienen nombre de producto

Cada paso costoso recibe o revisa una señal

Abort y retry no se contradicen

Los efectos externos tienen idempotency keys

La observabilidad separa cancelled de failed

const controller = new AbortController();
const result = await Promise.race([
  expensiveStep(controller.signal),
  sleep("30s").then(() => null),
]);
if (result === null) controller.abort();

Fuentes y lecturas