Replay determinístico em workflows de agentes de IA
Entenda como manter workflows de agentes de IA compatíveis com replay, separar atividades externas e testar mudanças antes do deploy em produção.
O workflow acordou com um código que conta outra história
Um agente inicia o onboarding de um cliente, valida documentos e aguarda uma aprovação. Enquanto a execução está parada, a equipe publica uma versão nova. O novo código adiciona uma atividade antes do timer que já havia sido registrado.
Quando a aprovação chega, o runtime tenta reconstruir o estado. O histórico diz que o próximo comando era o timer. O código atual produz uma nova atividade. A sequência deixa de corresponder ao que já aconteceu.
Replay determinístico é a capacidade de executar novamente a lógica de orquestração sobre o mesmo histórico e produzir a mesma sequência de comandos. Essa propriedade permite que outro worker recupere o workflow depois de reinício, falha, espera longa ou deploy.
O artigo sobre versionamento de workers decide qual versão pode receber cada execução. Este guia aprofunda outra fronteira: o que torna o código do workflow compatível com um histórico já gravado e como testar isso antes da produção.
Replay reconstrói estado a partir do histórico
Um workflow durável pode permanecer aberto por horas, dias ou meses. Manter toda a memória viva durante esse período seria frágil. Plataformas como Temporal registram eventos e comandos relevantes e usam o histórico para reconstruir o estado quando a execução precisa continuar.
Durante o replay, o código do workflow roda novamente. Resultados já registrados são reutilizados. Atividades concluídas não deveriam chamar o mundo externo outra vez. Timers presentes no histórico não esperam de novo. O runtime compara os comandos produzidos pelo código com a sequência existente.
A reconstrução funciona quando o workflow toma as mesmas decisões diante do mesmo histórico.
Exemplos de comandos relevantes incluem:
- agendar ou cancelar timer;
- iniciar ou cancelar atividade;
- iniciar workflow filho;
- enviar sinal para outra execução;
- registrar marcador de versão;
- continuar como nova execução;
- concluir, falhar ou cancelar o workflow.
Se o código reordenar, inserir ou remover um comando sem estratégia de compatibilidade, o replay pode encontrar uma divergência.
Determinismo se aplica à orquestração
Um agente precisa consultar banco, chamar modelo, acessar API, ler arquivo e produzir efeitos. Essas operações variam com o tempo e podem falhar. Colocá-las diretamente no caminho de replay faria a mesma execução enxergar respostas diferentes.
A separação recomendada usa dois tipos de código.
Workflow coordena
O workflow decide sequência, espera, ramificação, timeout, política de tentativas, aprovação e encerramento. Ele trabalha com valores registrados no histórico ou fornecidos por APIs seguras do runtime.
Activity interage com o mundo externo
A activity consulta banco, chama API, executa modelo, lê arquivo, envia pedido ou grava em outro sistema. Seu resultado volta ao histórico e pode ser reutilizado durante replay.
A documentação atual do Temporal cita explicitamente chamadas de API, invocações de LLM e consultas de banco como operações que devem ficar em Activities, fora do caminho determinístico.
Essa divisão também melhora a responsabilidade. O workflow coordena o processo. A activity assume timeout, retentativa, idempotência e efeito externo.
Fontes comuns de não determinismo
Alguns erros aparecem sem mudança de versão.
Hora do sistema
Uma chamada direta ao relógio pode devolver outro instante durante replay e alterar uma condição.
se agora > prazo:
cancelar
senão:
continuar
Use a API de tempo do runtime, capaz de reproduzir o valor coerente com o histórico. O prazo empresarial deve permanecer explícito e versionado quando necessário.
Aleatoriedade local
Um sorteio novo pode escolher outro ramo. Use mecanismo determinístico oferecido pelo SDK ou capture o valor uma vez como evento do histórico.
Consulta externa dentro do workflow
Banco, API, arquivo, variável mutável e resposta de modelo podem mudar entre execuções. A consulta pertence a uma activity. O histórico registra o resultado usado naquela decisão.
Estado global ou cache local
Outro worker pode não possuir o mesmo conteúdo. Reinício e escala também removem memória. Estado necessário para decisão precisa estar no histórico ou em uma fonte consultada por activity.
Ordem dependente de coleção instável
Percorrer um conjunto sem ordem garantida pode produzir comandos em sequência diferente entre ambientes ou versões. Ordene por chave estável antes de agendar trabalho.
Concorrência fora das APIs do runtime
Threads, callbacks e tarefas assíncronas não coordenadas podem alterar a ordem em que comandos aparecem. Use primitivas suportadas pelo SDK e teste interações simultâneas.
Dependência implícita de ambiente
Locale, timezone, versão de biblioteca, feature flag e configuração podem mudar a ramificação. Valores que influenciam a sequência precisam de contrato, versão e captura reproduzível.
Mudança de código também altera o replay
Um workflow pode ser determinístico hoje e incompatível com o histórico antigo depois de uma edição.
Mudanças sensíveis incluem:
- inserir uma atividade antes de outra já registrada;
- remover um timer;
- trocar a ordem entre timer e activity;
- renomear tipo ou ID usado no histórico;
- substituir conclusão por Continue-As-New;
- mudar uma condição que decide quais comandos são emitidos;
- adicionar workflow filho em um ramo antigo;
- apagar um marcador de patch cedo demais;
- alterar serialização sem leitor compatível;
- mudar a interpretação de um evento persistido.
Uma alteração visualmente pequena pode ser estrutural para o histórico. Mover uma linha que agenda uma atividade já muda a sequência observada pelo runtime.
Mudanças em texto de log ou cálculo puramente local podem ser seguras quando não alteram comandos. A classificação depende do SDK e da plataforma. O gate deve usar documentação e replay real, não intuição sobre o tamanho do diff.
Separe compatibilidade de replay e correção empresarial
Um replay pode passar e o novo comportamento continuar inadequado.
O teste de replay responde se o código produz comandos compatíveis com o histórico. Ele não comprova, sozinho, que:
- a atividade externa continua correta;
- o novo modelo atende ao critério de qualidade;
- a permissão é adequada;
- o prazo empresarial ainda é válido;
- a política aprovada não mudou;
- o efeito externo é idempotente;
- o processo entrega o resultado esperado.
Dois gates são necessários:
- compatibilidade técnica: o histórico pode ser reconstruído sem divergência;
- validade operacional: a execução retomada ainda deve continuar sob as regras atuais.
Um onboarding que aguardou documento por 90 dias pode passar no replay e precisar ser encerrado por validade. A reconstrução do estado não autoriza automaticamente a próxima consequência.
Use patching ou worker versioning para mudanças incompatíveis
Quando a nova sequência não pode interpretar o histórico antigo diretamente, existem dois caminhos comuns.
Worker versioning
Execuções fixadas continuam no build compatível. Novas execuções usam a versão promovida. Esse caminho reduz a necessidade de ramificações internas, mas exige manter capacidade antiga até o trabalho drenar.
Patching
O workflow registra um marcador de versão no histórico. Execuções anteriores seguem o caminho antigo. Execuções novas usam o comportamento novo. Depois que os históricos antigos deixam de depender do ramo, o patch pode ser retirado por etapas.
Patching exige inventário. Um marcador abandonado conserva código antigo indefinidamente. Remover cedo quebra execuções abertas ou ainda retidas.
A escolha depende de duração, capacidade de manter builds, frequência de mudança e política da plataforma. O versionamento de workers detalha execuções Pinned, Auto-Upgrade, ramp-up e retirada.
Replay testing transforma histórico em gate
Testes unitários exercitam entradas escolhidas. Replay testing usa históricos que representam decisões já registradas.
A documentação do Temporal recomenda reproduzir históricos de workflows antigos com o código novo e bloquear o deploy quando aparece erro de determinismo.
Um gate de replay precisa definir:
- tipos de workflow cobertos;
- filas afetadas pela mudança;
- históricos abertos e concluídos;
- estados de espera importantes;
- versões de schema presentes;
- patches ativos e em retirada;
- payloads protegidos ou anonimizados;
- tamanho e critérios da amostra;
- erro que bloqueia promoção;
- responsável pela exceção.
A amostra deve cobrir variedade de trajetória, não somente volume recente.
Inclua execuções que:
- aguardam timer;
- aguardam aprovação;
- possuem activity em retentativa;
- receberam sinais concorrentes;
- passaram por patch anterior;
- iniciaram workflow filho;
- fizeram Continue-As-New;
- estão perto de prazo;
- usam schema legado;
- terminaram por sucesso, cancelamento e falha.
Monte uma suíte representativa de históricos
Baixar os cem workflows mais recentes pode deixar de fora casos raros que carregam o maior risco.
Estratifique por:
workflow_type
worker_version
state
waiting_reason
age_band
schema_version
patch_markers
terminal_status
risk_class
tenant_boundary
Para cada estrato, selecione históricos capazes de exercitar comandos diferentes. Uma execução que nunca entrou no ramo de aprovação não prova compatibilidade desse ramo.
Históricos produtivos podem conter dados pessoais, segredos ou payloads criptografados. A documentação de safe deployments alerta para esse cuidado. Use ambiente autorizado, acesso mínimo e política explícita. Quando houver exportação para CI, remova ou substitua conteúdo sensível sem alterar a estrutura necessária para o replay.
Também mantenha fixtures sintéticas para caminhos conhecidos. Elas garantem cobertura rápida durante desenvolvimento. Históricos reais ou representativos acrescentam formatos e sequências que a equipe não previu.
Exemplo local de divergência
Em 9 de outubro de 2026, a Júpiter executou uma simulação local com histórico sintético de onboarding.
O histórico representava:
started:onboarding-77
activity_result:documento_valido
timer_fired:2026-10-10T12:00:00Z
A sequência esperada de comandos era:
schedule:validar_documento
timer:2026-10-10T12:00:00Z
schedule:solicitar_aprovacao
O código compatível reproduziu a sequência. Uma versão alterada inseriu schedule:enriquecer_cadastro antes do timer e falhou na comparação:
stable_replay=pass
changed_replay=fail
A simulação verifica a lógica do exemplo. Ela não substitui o replayer do SDK, histórico real, teste de integração ou gate de deploy da plataforma utilizada.
O valor do exercício está em tornar a divergência visível: o código novo pode ser válido para novas execuções e incompatível com uma trajetória já registrada.
Teste a mesma mudança em três momentos
Uma disciplina prática distribui o replay pelo ciclo de entrega.
Durante o desenvolvimento
Fixtures versionadas oferecem feedback rápido. Cada correção que envolve histórico adiciona um caso de regressão.
Antes do deploy
O pipeline reproduz amostra representativa de históricos com o artefato que será publicado. Qualquer divergência bloqueia a promoção.
Durante a implantação
Uma instância em modo de verificação pode reproduzir históricos recentes e encerrar sem consumir trabalho real. Depois do gate, as instâncias de execução recebem tráfego.
Essa terceira camada não elimina canário, modo sombra ou monitoramento. Ela reduz a chance de enviar tarefas a um build que já contradiz o histórico conhecido.
Faça o deploy com evidência de compatibilidade
Um fluxo de promoção pode seguir:
- identificar workflows e filas afetados pelo diff;
- executar testes unitários e de integração;
- reproduzir fixtures sintéticas;
- reproduzir históricos representativos autorizados;
- confirmar patches e versões esperados;
- publicar o build sem tráfego;
- executar verificação no ambiente de destino;
- liberar pequena coorte de novas execuções;
- observar replay, backlog, qualidade e efeitos;
- ampliar tráfego por critério;
- manter versão anterior enquanto houver dependência;
- retirar somente depois do gate de drenagem.
O rollback precisa considerar execuções que já receberam comandos da versão nova. Voltar o roteamento ajuda novas tarefas e pode não tornar o estado anterior compatível. Releia histórico, schema e efeitos antes de mover uma execução entre builds.
Trate activities como operações repetíveis
O replay do workflow reutiliza resultados registrados, mas uma activity pode ser executada novamente quando falha, perde confirmação ou ultrapassa timeout.
Cada activity precisa declarar:
- unidade de trabalho;
- chave de idempotência;
- timeout;
- política de retentativa;
- falhas não retentáveis;
- efeito externo esperado;
- confirmação do destino;
- tratamento de resultado incerto;
- heartbeat quando o trabalho é longo;
- compensação ou reconciliação;
- dados permitidos;
- responsável operacional.
A orquestração determinística impede divergência de comandos. Ela não impede duas cobranças se a activity repete uma chamada sem idempotência.
Para ações externas, combine replay seguro com idempotência, heartbeat e reconciliação.
Evite esconder LLM dentro do workflow
Uma invocação de modelo pode variar por versão, temperatura, contexto, disponibilidade e política do fornecedor. Mesmo com parâmetros fixos, tratá-la como função pura dentro do replay é uma premissa frágil.
Coloque a chamada em uma activity e registre:
- modelo e versão quando disponível;
- instrução versionada;
- fontes e referências;
- ferramentas autorizadas;
- entrada minimizada;
- saída usada pela decisão;
- critério de validação;
- quantidade de tentativas;
- bloqueios e revisão humana.
Durante replay, o workflow recebe o resultado já registrado. Uma reavaliação com modelo novo deve ocorrer como nova atividade autorizada ou migração explícita, não como consequência invisível da reconstrução.
Se a resposta antiga deixou de ser válida, o processo precisa de regra de freshness. O runtime não consegue inferir sozinho que uma classificação de três meses atrás merece nova análise.
Monitore sinais de replay e não determinismo
Acompanhe:
- falhas de replay por workflow e build;
- comandos divergentes por tipo;
- workflow tasks repetindo sem progresso;
- versões com históricos incompatíveis;
- patches ativos e idade;
- execuções fixadas por build;
- histórias ainda dependentes de código antigo;
- tempo e custo do replay;
- tamanho extremo de histórico;
- backlog depois de deploy;
- activities repetidas;
- ações externas em estado incerto;
- workflows pausados por validade empresarial;
- exceções manuais de compatibilidade.
Um alerta útil liga o problema ao processo: “27 onboardings iniciados no build 2.4 falharam no replay depois da alteração do timer; novas execuções continuam no build anterior; o time de plataforma possui rollback e correção até 14h”.
“Erro de não determinismo” sem objeto, volume, consequência e dono entrega um diagnóstico técnico pela metade.
Checklist de replay determinístico
Antes de promover uma mudança, confirme:
- [ ] A lógica do workflow usa somente valores reproduzíveis?
- [ ] Relógio, aleatoriedade e concorrência usam APIs seguras do runtime?
- [ ] Banco, API, arquivo e LLM ficam fora do caminho de replay?
- [ ] Activities possuem idempotência e tratamento de resultado incerto?
- [ ] O diff altera a ordem ou a presença de comandos?
- [ ] Mudanças incompatíveis usam patching ou worker versioning?
- [ ] Históricos abertos e concluídos entram na suíte?
- [ ] Estados raros e schemas antigos estão representados?
- [ ] Dados produtivos usados no teste seguem acesso e minimização?
- [ ] O pipeline falha fechado diante de divergência?
- [ ] A verificação usa o mesmo artefato do deploy?
- [ ] Validade empresarial é reavaliada depois de esperas longas?
- [ ] Rollback considera estado e efeitos já produzidos?
- [ ] Patches e builds antigos possuem plano de retirada?
- [ ] Alertas mostram processo afetado, contenção, dono e prazo?
O histórico precisa continuar legível para o código
Workflows duráveis sobrevivem porque conseguem reconstruir estado depois de falhas e esperas. Essa capacidade depende de um contrato: diante do mesmo histórico, a lógica de orquestração produz comandos compatíveis.
O desenho seguro mantém operações externas em activities, usa APIs determinísticas do runtime, versiona mudanças estruturais e transforma históricos em testes de replay. A promoção falha quando o código novo contradiz trajetórias existentes.
Esse gate protege a retomada técnica. Idempotência, validade, permissão e critério de negócio protegem a consequência. Juntos, eles permitem que um agente acorde depois de um deploy sem reinterpretar silenciosamente o que já aconteceu.
Fontes oficiais verificadas em 9 de outubro de 2026:
- Temporal: Workflow Definition, para restrições determinísticas, comandos, fontes de não determinismo, Activities e estratégias de versionamento.
- Temporal: Workflows e replay, para reconstrução de estado pelo Event History, reutilização de resultados e APIs seguras de tempo e aleatoriedade.
- Temporal: safe deployments, para replay testing em desenvolvimento, pré-deploy e implantação, além dos cuidados com históricos produtivos.
- Temporal TypeScript SDK: testing, para replay individual e em lote, seleção por Task Queue e falha do CI diante de incompatibilidade.
- Temporal: Worker Versioning, para Pinned, Auto-Upgrade, Current, Ramping e relação entre versionamento e replay seguro.