O que é Mover para Execução Durável?
Mover para Execução Durável (Move to Durable Execution) é uma refatoração de IA para sistemas com LLM, do grupo Operação. Salvar o estado a cada etapa para retomar depois de queda, espera ou aprovação.
Move to Durable Execution
Mover para Execução Durável (Move to Durable Execution) é uma refatoração de IA para sistemas com LLM, do grupo Operação. Salvar o estado a cada etapa para retomar depois de queda, espera ou aprovação.
Um processo que dura horas ou dias (esperando documentos, aprovações, respostas de outros sistemas) vive na memória de um processo ou num histórico de conversa. Uma queda, um deploy ou uma espera longa fazem perder o estado. É o smell Prompt Máquina de Estados, na sua forma de longa duração.
Rode o processo num mecanismo de execução durável: cada passo é registrado, o estado é persistido entre passos, esperas viram eventos que retomam a execução, e uma falha retoma do último passo concluído, sem repetir o que já foi feito.
-def onboarding(customer_id):
- data = ask_for_documents(customer_id) # pode levar dias; processo em memória
- if not validate(data):
- ask_again(customer_id)
- approval = wait_for_compliance(customer_id) # se o servidor reiniciar, perdeu
- create_account(customer_id)
+@workflow
+def onboarding(customer_id):
+ docs = workflow.wait_for_signal("documents_received", timeout=days(7))
+ result = workflow.step(validate_documents, docs) # resultado gravado
+ while not result.ok:
+ workflow.step(send_whatsapp, customer_id, result.missing)
+ docs = workflow.wait_for_signal("documents_received", timeout=days(7))
+ result = workflow.step(validate_documents, docs)
+ approval = workflow.wait_for_signal("compliance_decision", timeout=days(3))
+ if approval.approved:
+ workflow.step(create_account, customer_id, idempotency_key=workflow.id)
Antes: o estado vive na memória.
flowchart LR
S(["1. Início"]):::io --> W["2. Espera dias por documento"]:::tool
W --> X{"3. Servidor reiniciou?"}
X -->|sim| L(["4. Estado perdido"]):::io
Depois: cada passo gravado, esperas como eventos.
flowchart LR
S(["1. Início"]):::io --> P1["2. Passo gravado"]:::tool
P1 --> J[("3. Histórico do workflow")]:::store
J --> W{"4. Espera por sinal"}
W -->|"documento chegou"| P2["5. Próximo passo"]:::tool
P2 --> J
J -->|"falha ou deploy"| R["6. Retoma do último passo"]:::tool
Uma fintech abre conta PJ pelo WhatsApp. O cliente manda o contrato social, o comprovante e uma selfie. Compliance leva até três dias úteis. No desenho antigo, um processo Node fica em await esperando. Um deploy na sexta apaga quem estava no meio. Na segunda, o cliente ouve “pode mandar os documentos de novo”.
No desenho durável, o identificador do workflow é o customer_id. O passo validate_documents grava um resultado com ok falso e a lista do que falta, por exemplo o comprovante. O passo send_whatsapp manda essa lista, com chave wf.id + ":ask:" + n. A espera vira um sinal documents_received com prazo de 7 dias.
Na terça o comprovante chega. O motor acorda o workflow, lê o resultado já gravado da validação anterior e roda a validação de novo. Ninguém pergunta o CNPJ outra vez. Se o servidor cair no meio da criação da conta, a chave de idempotência workflow.id impede uma conta duplicada.
O modelo continua no lugar certo: ler o PDF, dizer o que falta, escrever a mensagem no tom da fintech. Ele não guarda “já estamos na etapa 4”. Isso mora no histórico do workflow.
Um processo longo tem dois inimigos: o tempo e as falhas. Processos em memória não sobrevivem a nenhum dos dois. Um mecanismo de execução durável grava o resultado de cada passo e reconstrói o estado a partir desse registro, então uma queda ou um deploy viram uma pausa, não uma perda.
O modelo continua com o papel dele: entender mensagens, extrair dados, escrever respostas. O fluxo (o que vem depois, o que espera o quê) fica no código do workflow, testável e visível. E o identificador do workflow serve como chave de idempotência natural para as ações com efeito. Os padrões de destino são o Workflow Durável e o Checkpoint e Retomada.
Motores como Temporal reexecutam o código do workflow do começo para reconstruir o estado. Eles não “continuam da linha 47”. Eles replayam os passos gravados e só então rodam o que ainda não rodou.
Se você chama o modelo no corpo do workflow, cada replay dispara uma chamada nova. A resposta muda, o ramo do if muda, e o histórico gravado deixa de bater com o código. O motor acusa não determinismo.
A regra é simples. Tudo que não é determinístico (modelo, relógio, aleatório, HTTP) entra num workflow.step. O corpo do workflow só lê resultados já gravados e decide o próximo passo.
Um motor de workflow é peça a mais: versão de fluxo, replay, visibilidade. Para um job de 20 minutos com três passos e sem espera humana, um registro em banco com status, step e idempotency_key pode ser suficiente.
A linha que pede o motor é a espera longa (horas ou dias), o volume de processos parados, e a necessidade de ver cada um. Se você tem mil onboarding abertos esperando documento, um sleep em mil processos não escala. Um sinal por processo escala.
O time descreve as etapas no system prompt (“não pule a etapa 3”) e acha que o histórico da conversa é o checkpoint. O smell Prompt Máquina de Estados é exatamente isso. O cliente manda CPF e comprovante na mesma mensagem, o modelo perde a conta, e o fluxo pula.
Execução durável não substitui o modelo. Ela tira dele a obrigação de lembrar em que etapa o processo está. O código sabe. O modelo só preenche o passo atual.
Um processo de cobrança envia um lembrete, espera 3 dias, envia outro, espera mais 3 dias e, se não houver pagamento, abre um chamado para o time financeiro. Hoje isso é um script com sleep. O que pode dar errado, e como fica a versão durável?
Com sleep, qualquer reinício perde todos os processos em espera; um retry do script pode mandar o mesmo lembrete duas vezes; e não dá para ver em que etapa cada cobrança está. Na versão durável:
workflow cobranca(invoice_id):
step send_reminder(invoice_id, n=1, key=wf.id+":1")
paid = wait_for_signal("paid", timeout=days(3))
if paid: return
step send_reminder(invoice_id, n=2, key=wf.id+":2")
paid = wait_for_signal("paid", timeout=days(3))
if not paid: step open_finance_ticket(invoice_id, key=wf.id+":ticket")O pagamento envia o sinal paid, e cada passo tem chave própria.
Mover para Execução Durável (Move to Durable Execution) é uma refatoração de IA para sistemas com LLM, do grupo Operação. Salvar o estado a cada etapa para retomar depois de queda, espera ou aprovação.
Trata Prompt Máquina de Estados.
Ao padrão de projeto Workflow Durável e Checkpoint e Retomada.