Agente caiu no meio da tarefa? Persista o estado no LangGraph ou CrewAI

|Autor: Equipe editorial da QUASA|7 min de leitura
Agente caiu no meio da tarefa? Persista o estado no LangGraph ou CrewAI

Para retomar um agente depois de uma queda, associe cada trabalho a um identificador estável e grave seu progresso em armazenamento durável. No LangGraph, os checkpointers por thread guardam o estado e a próxima etapa do grafo; no CrewAI, os checkpoints de execução permitem restaurar um Flow, Crew ou Agent após uma interrupção.

Na retomada, reutilize o identificador do trabalho e o mesmo armazenamento, ou restaure o checkpoint salvo. O progresso registrado pode ser recuperado, mas a etapa interrompida pode rodar novamente. Se ela chamou um serviço externo antes da queda, a aplicação também precisa impedir que uma nova tentativa produza um segundo envio, pagamento ou registro.

Escolha um identificador que sobreviva ao processo

Crie um ID para cada trabalho, como a solicitação de atendimento ou o job que processa um pedido, e conserve-o em todas as tentativas de concluir aquela execução. Guarde a relação entre esse ID e o identificador usado pelo framework em um registro acessível ao processo que fará a recuperação. Assim, um novo worker consegue localizar o progresso salvo sem depender da memória do worker anterior.

O ID deve distinguir uma nova solicitação de uma nova tentativa da mesma solicitação. Se um cliente pedir outra ação sobre o mesmo pedido, pode ser necessário criar outro job; se o processo apenas caiu durante o job existente, reutilize o ID anterior. Evite também iniciar dois workers ao mesmo tempo com o mesmo trabalho: o checkpoint conserva o progresso, mas a aplicação ainda precisa coordenar quem pode executar a próxima ação.

Inclua no estado os dados necessários para continuar: entrada validada, resultado de etapas concluídas e referência à operação externa. Uma variável local que desaparece com o processo não serve como único registro de um resultado caro de reproduzir. Para uma operação externa, mantenha uma chave derivada do trabalho e da ação, estável entre tentativas.

LangGraph: salve entre as etapas do grafo

No LangGraph, o checkpoint preserva o estado do thread entre um nó concluído e o próximo.

Uma implementação mínima separa o preparo de uma ação externa. Defina um StateGraph cujo estado contenha a entrada, o resultado preparado e uma referência ao envio. Adicione um nó preparar, seguido de um nó enviar, com as arestas START → preparar → enviar → END. O nó preparar devolve sua atualização de estado; o nó enviar usa a chave estável da ação ao chamar o serviço externo.

  1. Compile o grafo com um checkpointer persistente, como SqliteSaver apontando para um arquivo que continuará disponível após o reinício. InMemorySaver é útil para desenvolvimento, mas perde os dados quando o processo termina.
  2. Crie config = {"configurable": {"thread_id": id_do_job}} e inicie com graph.invoke(entrada, config, durability="sync"). Nesse modo, a gravação de cada checkpoint termina antes de o grafo avançar para a etapa seguinte.
  3. Depois da falha, recrie o grafo com acesso ao mesmo banco. Consulte graph.get_state(config): o campo next indica a etapa pendente. Se houver trabalho pendente, use graph.invoke(None, config, durability="sync") para continuar sem reenviar a entrada inicial.

O limite de recuperação é o último ponto salvo, não a última linha de código executada. Se o processo cair dentro do nó enviar, esse nó poderá ser executado outra vez. Separar preparo e envio evita refazer o preparo já registrado, mas a chave de idempotência continua necessária para proteger o efeito produzido fora do grafo. Uma pausa criada para receber intervenção humana segue outro caminho de retomada: ela precisa do valor fornecido em Command(resume=...).

CrewAI: diferencie dados do Flow e progresso da execução

No CrewAI, um checkpoint de execução permite continuar o Flow após um método concluído.

No CrewAI, o decorador @persist em Flows salva o estado da classe ou de métodos selecionados; SQLite é o armazenamento padrão desse mecanismo. Uma nova instância pode carregar o estado associado ao mesmo ID por meio de kickoff(inputs={"id": id_do_job}). Isso recupera valores, mas iniciar o Flow novamente não significa, por si só, pular os métodos que já terminaram.

Para preservar também o andamento, monte um Flow mínimo com @start() em preparar e @listen(preparar) em enviar. Faça preparar registrar no estado a saída de que enviar precisa. Instancie o Flow com checkpoint=CheckpointConfig(location="./flow_cp", on_events=["method_execution_finished"]) e chame kickoff(). O evento escolhido grava um checkpoint após a conclusão de cada método; com o provedor padrão de checkpointing, cada ponto salvo fica em um arquivo JSON.

Após a interrupção, localize o último arquivo concluído do job e crie outra instância do mesmo Flow. Chame kickoff(from_checkpoint=CheckpointConfig(restore_from=caminho_do_arquivo)) para restaurar a execução. Registre o caminho do checkpoint junto ao ID do job e disponibilize o diretório ao worker de recuperação. Esse arquivo pertence ao checkpointing de execução; o banco SQLite usado por @persist guarda o estado do Flow por outro mecanismo.

Se você precisa apenas reutilizar valores em uma nova execução, @persist e o mesmo ID atendem a esse objetivo. Se precisa continuar uma execução interrompida a partir do progresso registrado, configure checkpoints e escolha um evento que corresponda ao limite de recuperação desejado. A carga por ID pode iniciar um estado novo quando não encontra o anterior; por isso, confirme que há um registro salvo antes de tratar a operação como retomada.

Impeça que uma tentativa repetida duplique o efeito

Há uma janela entre a aceitação de uma chamada externa e a gravação do checkpoint seguinte. O serviço pode ter concluído a ação quando o worker cai sem registrar a resposta. Na retomada, o mesmo nó ou método tenta de novo. Marcar “concluído” no estado depois da chamada deixa essa janela aberta; marcar antes pode fazer a recuperação omitir uma ação que nunca ocorreu.

  • Mensagens e notificações: use uma chave por trabalho, destinatário e evento. Consulte o registro de entregas ou a deduplicação oferecida pelo serviço antes de produzir outro envio.
  • Pagamentos, pedidos e reservas: reapresente a mesma chave de idempotência em todas as tentativas e consulte o resultado no sistema responsável quando a resposta da primeira tentativa for incerta.
  • Gravações e publicações: use uma restrição de unicidade, uma atualização condicionada ou uma operação de substituição identificada pelo trabalho, conforme o sistema de destino permitir.

Essas chaves identificam a ação pretendida, não a tentativa de executá-la. Se o destino não oferece deduplicação, mantenha um registro durável da intenção e do resultado e defina como conciliar uma resposta perdida. O checkpoint do agente informa onde retomar; o registro do sistema externo informa se a ação já aconteceu.

Teste a queda antes e depois da chamada externa

Use o mesmo fluxo lógico nos dois frameworks: preparar um resultado verificável e, em seguida, chamar um serviço simulado que registre requisições e efeitos efetivos separadamente. Execute primeiro sem falha para conhecer o resultado esperado. Nos testes de recuperação, mantenha o mesmo ID e o mesmo armazenamento; um ID novo testaria outra execução.

  1. Interrompa o worker depois que preparar terminar e antes de enviar começar. Reinicie o processo e recupere o thread do LangGraph ou o arquivo de checkpoint do CrewAI. Verifique se o resultado preparado foi preservado e se a etapa pendente chegou ao fim.
  2. Interrompa depois que o serviço simulado aceitar a chamada, mas antes do próximo checkpoint. Retome com a mesma chave de idempotência. O registro pode mostrar outra tentativa de requisição, mas deve mostrar apenas um efeito efetivo.
  3. Repita com o armazenamento de checkpoints indisponível. O processo de recuperação deve sinalizar a falta do estado e interromper a retomada até que ela possa ser resolvida, em vez de iniciar silenciosamente outro trabalho capaz de repetir o efeito.

Registre em cada execução o ID do job, o último ponto salvo, a chave da operação, as tentativas e o resultado no destino. Essa sequência permite localizar a falha com precisão: um checkpoint pode preservar o preparo enquanto a proteção do serviço externo decide se reenviar a chamada é seguro.

Leia também:

Compartilhar:

Assine nossa newsletter

Receba as últimas notícias sobre Web3, IA e cripto diretamente no seu e-mail.

0