Design de máquina de estados para agentes de IA: por que workflows complexos não podem depender só do prompt

"A documentação de LangGraph Persistence descreve checkpoints como graph state snapshots com escopo de thread e explica que eles dão suporte a conversation continuity, human-in-the-loop, time travel e fault tolerance."
Um agente de relatórios falhou logo antes de enviar o e-mail no passo 5. A operação relançou a tarefa. O agente começou de novo no passo 1, gerou um novo relatório e sobrescreveu a versão que já tinha sido aprovada. O estado de aprovação se perdeu. O registro assinado pelo aprovador foi substituído pelo novo resultado, e nenhum log conseguia provar que a primeira versão do relatório tinha sido aprovada.
Isso não era rollback de banco de dados nem retry de fila de mensagens. No prompt só restava a frase “continuar o processamento”. O modelo inferiu o fluxo inteiro de novo, sem saber que os passos 1 a 4 já tinham produzido efeitos externos: chamada à API de aprovação, geração de relatório e escrita de arquivo temporário. O ponto de falha foi o passo 5, mas os efeitos começaram no passo 2.
O problema real não era a capacidade do modelo. O progresso da tarefa estava escondido em linguagem natural dentro do prompt, sem um state snapshot recuperável. Os messages carregados pelo prompt são contexto do modelo, não fatos de execução.
Para corrigir um incidente desse tipo, não basta colocar no prompt uma frase como “verifique o progresso antes de continuar”. O caminho mais robusto é escrever o nó atual, os efeitos já produzidos, a próxima action e a compensação de falha em uma tabela de estados recuperável.
Pontos-chave do incidente
Fluxo de execução do agente de relatórios:
| Passo | Operação | Efeito externo | Idempotência |
|---|---|---|---|
| Passo 1 | Consulta de dados | Chama o banco de dados e consulta dados de usuário | Idempotente (leitura) |
| Passo 2 | Geração de relatório | Chama a ferramenta de relatórios e gera um PDF | Não idempotente (sobrescreve arquivo) |
| Passo 3 | Espera de aprovação | Envia solicitação de aprovação e espera uma pessoa aprovar | Idempotente (API dá suporte) |
| Passo 4 | Aprovação recebida | Recebe o event approve | Idempotente (consulta de status) |
| Passo 5 | Enviar e-mail | Chama a API de e-mail e envia o relatório | Falha (timeout) |
Causa da falha: o envio de e-mail no passo 5 sofreu timeout por rate limiting da API externa, e a tarefa foi marcada como FAILED.
Lógica de relançamento: ler o “progresso atual” do prompt. O prompt só dizia “aprovado, continuar”. Execução real: começar de novo no passo 1 -> gerar o relatório novamente no passo 2 (sobrescrevendo a versão aprovada) -> pedir aprovação outra vez no passo 3 -> enviar com sucesso no passo 5.
Impacto no negócio: o relatório aprovado foi substituído, o registro de aprovação deixou de bater com o relatório entregue, o usuário reclamou que o relatório aprovado era diferente do recebido, e o fluxo de aprovação foi desperdiçado: duas versões aprovadas, só uma enviada.
Tabela de anti-padrões
Veja se seu agente cai em algum destes anti-padrões:
| Anti-padrão | Como aparece | Risco oculto | Correção |
|---|---|---|---|
| Progresso escrito no Prompt | Resumo em linguagem natural como “atualmente no passo 3” | Perde após reinício, não recupera | Registrar o nó atual em um campo State |
| Trace tratado como State | Ter um Trace completo parece suficiente | Trace não decide o próximo passo | State registra o que deve acontecer em seguida |
| Retry sem checagem de idempotência | Falhou, recomeça tudo | Efeitos externos se repetem | Chave de idempotência + verificação de já executado |
| Resume após approval sem validação | Continua direto | Não volta ao ponto correto | checkpoint + thread_id |
1. Fundamentos de máquina de estados: State, Event, Transition, Guard, Action
Máquina de estados não é obrigatória para todo agente. Um Q&A simples de suporte pode funcionar com um array de messages. Mas uma tarefa complexa, com múltiplos passos, approval, chamadas a sistemas externos e recuperação após falha, precisa tornar o progresso explícito.
1.1 Tabela de termos centrais
Os termos básicos vêm da documentação da Stately:
| Termo | Definição | Exemplo em Agent | Fonte |
|---|---|---|---|
| State | Modo em que a máquina está, com uma intenção semântica única | INIT, PLAN_READY, TOOL_RUNNING, APPROVAL_PENDING, FAILED, COMPLETED | Stately state machines |
| Event | Sinal externo que dispara mudança de estado | timeout, approve, reject, retry, resume, task_received | Stately state machines |
| Transition | Caminho permitido entre estados, com mapeamento determinístico | INIT -> PLAN_READY (event: task_received) | Stately state machines |
| Guard/Condition | Pré-condição para entrar em um estado | Só entrar em TOOL_RUNNING quando o orçamento for suficiente | Stately state machines |
| Action | Operação executada durante uma transição | Chamar uma ferramenta ao entrar em TOOL_RUNNING | Stately state machines |
| Checkpoint | State snapshot usado para recuperação | LangGraph checkpointer salva graph state | LangGraph Persistence |
Princípio de determinismo: a mesma combinação State + Event deve apontar para um único next state, evitando ambiguidade. Conjunto finito de estados: uma máquina de estados não é um fluxograma infinito, mas um conjunto finito de estados alcançáveis com regras explícitas de transição.
1.2 Comparativo Trace vs State vs Audit
Trace, Audit Log e State Snapshot resolvem problemas diferentes:
| Conceito | Que problema resolve | É estado de negócio? | Decide o próximo passo? | Exemplo em Agent |
|---|---|---|---|---|
| Trace | Observabilidade e diagnóstico | Não | Não | OpenAI Agents SDK trace (workflow_name, trace_id) |
| Audit Log | Registro de conformidade e auditoria | Não | Não | Campos de auditoria do modelo de permissões (actor, traceId, action, result) |
| State Snapshot | Estado atual que decide o próximo passo | Sim | Sim | LangGraph checkpoint (nó atual, passos executados, próxima ação) |
A distinção é central: Trace ajuda a observar o que aconteceu, mas não é o estado de negócio. Audit Log registra histórico para auditoria. State Snapshot decide o que deve acontecer em seguida e é o núcleo da recuperação. Eles não se substituem: ter Trace não é ter State; ter Audit não é conseguir recuperar.
2. Como o LangGraph faz persistência de estado
Checkpoint não é um resumo em linguagem natural dentro do prompt. É um state snapshot recuperável, inspecionável e reproduzível. A documentação de LangGraph persistence define checkpoint como graph state snapshot, incluindo estado completo e próximos nós a executar.
2.1 Checkpointer e Thread State
Mecanismos centrais (documentação LangGraph Persistence):
- Checkpointer: salva snapshots de estado com escopo de thread (graph state snapshots)
- Store: salva dados de longo prazo entre threads (application-defined store)
- Thread_id: entrada única para recuperar o estado de um thread específico
- Quatro usos: conversation continuity, human-in-the-loop, time travel, fault tolerance
LangGraph persistence coloca estado de curto prazo com escopo de thread em checkpointers e dados de longo prazo entre threads em stores. Um checkpoint inclui state snapshot e application-defined store. Thread_id é a entrada de recuperação; com a mesma thread_id, dá para continuar do ponto de pausa.
Um checkpoint do LangGraph contém graph state, lista dos próximos nós, checkpoint_id, timestamp e versão. Dados sensíveis não devem entrar automaticamente no checkpoint: alguns campos de graph state podem conter informações sensíveis e precisam de configuração explícita para não serem persistidos.
2.2 Interrupts e mecanismo de recuperação
Mecanismos centrais (documentação LangGraph Interrupts):
- interrupt(): pausa dinamicamente a execução dentro de um nó do grafo, salva graph state e espera input externo
- Método de recuperação: usar a mesma thread_id e Command(resume=…)
- Padrões comuns: approval, review/edit, tool call review, human input validation
- Alerta de efeitos idempotentes: efeitos antes do interrupt precisam ser idempotentes, porque ao retomar o nó reexecuta desde o início do nó que chamou interrupt
Uma pausa de aprovação deve ser um estado de pausa na máquina de estados, não uma esperança de que o modelo “lembre de esperar aprovação”. A recuperação precisa do mesmo thread cursor.
Na recuperação, usa-se a mesma thread_id e Command(resume=…). Efeitos idempotentes são pré-requisito. Se houver um efeito antes da aprovação, como chamada a uma API externa, ele precisa ser idempotente; caso contrário, o nó retomado chamará a API de novo.
3. Analogia de engenharia: Temporal Durable Execution
Confiabilidade de tarefas longas não é um problema novo. Temporal durable execution oferece uma analogia madura.
3.1 Definição de Durable Execution
Conceitos centrais (documentação Temporal Durable Execution):
- Durable Execution: workflow execution preserva state/progress em falhas, crashes ou interrupções de serviço
- Event History: registra o estado de cada passo para recuperar do último evento registrado após falha
- Três propriedades: Resumable, Recoverable, Reactive
A confiabilidade de tarefas longas vem de event history e execução recuperável, não da memória de um único processo nem do contexto do prompt. Uma máquina de estados de agente precisa de algo parecido: checkpoint/event log + estado de negócio, não só nova inferência do modelo.
O Event History do Temporal e o checkpoint do LangGraph são próximos conceitualmente: ambos registram histórico de execução e dão suporte à recuperação a partir do ponto de falha. A diferença é que Temporal é um motor completo de workflow, enquanto LangGraph é um framework de gestão de estado para agentes. A lição: durable execution precisa de histórico de estado estruturado, não de memória de processo ou contexto do modelo.
4. Modelo de tabela de estados: uma Agent State Table reutilizável
Conceitos de máquina de estados são abstratos. Para usar na prática, você precisa de um modelo concreto de estado. Aqui vão três modelos: tabela de estados, tabela de eventos e exemplo derivado do incidente.
4.1 Modelo de tabela de estados (bloco executável)
Estrutura:
| State | Event | Guard | Action obrigatória | Next |
|---|---|---|---|---|
| INIT | task_received | Nenhum | Inicializar contexto e registrar hora de início | PLAN_READY |
| PLAN_READY | plan_generated | plan_valid | Gerar plano de execução e registrar sequência de ferramentas | TOOL_RUNNING |
| TOOL_RUNNING | tool_completed | budget_sufficient | Chamar ferramenta, registrar resultado e atualizar orçamento | APPROVAL_PENDING ou COMPLETED |
| APPROVAL_PENDING | approve | approval_required | Enviar solicitação de aprovação e registrar aprovador | COMPLETED |
| APPROVAL_PENDING | reject | Nenhum | Registrar motivo da rejeição e notificar usuário | FAILED |
| FAILED | retry | retry_count < max | Verificar idempotência e voltar ao checkpoint anterior | TOOL_RUNNING ou APPROVAL_PENDING |
| COMPLETED | Nenhum | Nenhum | Registrar hora de conclusão e limpar recursos | Terminal |
Notas: a coluna State define todos os estados alcançáveis (INIT, PLAN_READY, TOOL_RUNNING, APPROVAL_PENDING, FAILED, COMPLETED). Event define os eventos que disparam transitions (task_received, approve, reject, retry). Guard define pré-condições (budget_sufficient, retry_count < max). Action define a operação obrigatória durante a transição. Next define o próximo estado de forma determinística.
4.2 Modelo de tabela de eventos (complemento da tabela de estados)
Estrutura:
| Event | Condição de disparo | Estado anterior exigido | Estado posterior | Produz efeito externo? |
|---|---|---|---|---|
| task_received | Usuário envia a tarefa | INIT | PLAN_READY | Não |
| plan_generated | LLM gera plano de execução | PLAN_READY | TOOL_RUNNING | Não |
| tool_completed | Ferramenta conclui execução | TOOL_RUNNING | APPROVAL_PENDING ou COMPLETED | Sim (chamada a API externa) |
| approve | Aprovador aceita | APPROVAL_PENDING | COMPLETED | Sim (envia e-mail, desconta orçamento) |
| reject | Aprovador rejeita | APPROVAL_PENDING | FAILED | Não |
| retry | Solicitação de retry após falha | FAILED | TOOL_RUNNING ou APPROVAL_PENDING | Exige verificação de idempotência |
| timeout | Timeout de execução | TOOL_RUNNING | FAILED | Não |
Notas: o estado anterior exigido deixa explícito em quais estados cada event pode ser recebido. A coluna de efeitos externos marca quais events precisam de idempotência ou compensação.
4.3 Exemplo de tabela de estados a partir do incidente de relatório sobrescrito
Exemplo completo: tabela de estados do agente de relatórios derivada do incidente inicial
| State | Event | Guard | Action | Next | Verificação de idempotência/compensação |
|---|---|---|---|---|---|
| INIT | task_received | Nenhum | Inicializar thread_id e registrar hora de início | QUERY_RUNNING | Não precisa |
| QUERY_RUNNING | query_completed | Nenhum | Consultar dados e salvar resultado em state | REPORT_GENERATING | Não precisa |
| REPORT_GENERATING | report_generated | Nenhum | Gerar relatório e salvar report ID em state | APPROVAL_PENDING | Idempotência: se relatório já existe, pular geração |
| APPROVAL_PENDING | approve | Nenhum | Registrar aprovador e hora de aprovação | EMAIL_SENDING | Não precisa |
| APPROVAL_PENDING | reject | Nenhum | Registrar motivo da rejeição | FAILED | Não precisa |
| EMAIL_SENDING | email_sent | Nenhum | Enviar e-mail e registrar email ID | COMPLETED | Idempotência: se e-mail já foi enviado, pular |
| EMAIL_SENDING | timeout | retry_count < 3 | Registrar falha e verificar idempotência | EMAIL_SENDING (retry) ou FAILED | Chave de idempotência: email_id + thread_id |
| FAILED | retry | retry_count < max | Verificar idempotência e recuperar do checkpoint anterior | QUERY_RUNNING ou REPORT_GENERATING ou EMAIL_SENDING | Decidir ponto de recuperação pelo checkpoint |
| COMPLETED | Nenhum | Nenhum | Registrar hora de conclusão e limpar recursos | Terminal | Não precisa |
Correção do incidente: quando o passo 5 falha (EMAIL_SENDING -> timeout), a recuperação deve partir de EMAIL_SENDING, não de QUERY_RUNNING. O checkpoint precisa registrar o nó atual (EMAIL_SENDING), passos concluídos (QUERY, REPORT_GENERATED, APPROVAL_APPROVED) e o que vem a seguir (EMAIL_SENDING). Geração de relatório e envio de e-mail precisam de chaves de idempotência para evitar duplicidade.
5. Idempotência e compensação: recuperação não é só checkpoint
Ter checkpoint não significa que todos os efeitos externos podem ser recuperados com segurança. Recuperação também precisa de idempotência, transações, compensação e verificação do estado do sistema externo.
5.1 Conceitos de idempotência e compensação
Definições:
- Idempotente: várias execuções produzem o mesmo resultado e não criam efeitos externos duplicados
- Compensação: desfazer um efeito externo já ocorrido e restaurar consistência
- Rollback de transação: operação atômica que volta automaticamente em caso de falha
- Verificação de estado externo: verificar o sistema externo antes da recuperação para evitar operações duplicadas
Três pilares da consistência de estado: identidade de idempotência (action_id + schema_hash), cadeia de state snapshots (snapshot + prev_hash + delta) e action de compensação registrada (undo_op).
5.2 Checklist de idempotência e compensação
Como decidir quais operações precisam de idempotência e quais precisam de compensação:
| Tipo de operação | Precisa de idempotência? | Precisa de compensação? | Design da chave de idempotência | Plano de compensação |
|---|---|---|---|---|
| Consulta de dados (sem efeito externo) | Não | Não | - | - |
| Geração de relatório (sobrescreve arquivo) | Sim | Sim | report_id + thread_id | Excluir relatório novo e restaurar versão aprovada |
| Envio de e-mail (API externa) | Sim | Difícil | email_id + thread_id | Enviar e-mail de correção ou cancelamento em alguns cenários |
| Desconto de estoque (banco de dados) | Sim | Sim | inventory_id + order_id | Repor estoque |
| Criação de ticket (sistema externo) | Sim | Sim | ticket_id + thread_id | Fechar ticket |
| Desconto de orçamento (estado interno) | Sim | Sim | budget_id + thread_id | Repor orçamento |
| Envio de solicitação de aprovação (sem efeito durável) | Não | Não | - | - |
Lógica de decisão: se a operação cria efeito externo, ela precisa de idempotência. Operações reversíveis precisam de compensação. Em chamadas entre sistemas, a chave de idempotência deve incluir identificador do sistema externo. Operações atômicas podem usar rollback de transação.
Recuperação não é só checkpoint. Ela precisa de idempotência, transações, compensação e verificação de estado externo. Dizer que checkpoint recupera todos os efeitos com segurança é impreciso.
6. Checklist de estados de tarefa Agent: recuperável vs irrecuperável
Nem todo checkpoint permite recuperar. Terminal state é o estado final de uma workflow execution: concluído, falho, timeout ou cancelado. Um terminal state não pode ser retomado; só pode ser reexecutado ou compensado.
6.1 Tabela de classificação de estados
| Tipo de estado | Recuperável? | Condição de recuperação | Método de recuperação | Exemplo |
|---|---|---|---|---|
| Failed | Sim | retry_count < max | Recuperar do checkpoint anterior | Timeout de chamada de ferramenta |
| Retry | Sim | Verificação de idempotência passa | Reexecutar a partir do nó que falhou | Falha no envio de e-mail |
| Compensation | Parcialmente | Existe plano de compensação | Executar undo_op | Falha ao descontar estoque |
| Approval Pause | Sim | event approve/reject | Command(resume=…) | Espera de aprovação |
| Terminal | Não | Nenhuma | Sem caminho de recuperação | COMPLETED, FAILED (retry_count = max) |
Notas: estado Failed pode recuperar via retry se retry_count < max. Estado Retry exige verificação de idempotência e reexecuta a partir do nó com falha. Estado Compensation é parcialmente recuperável se houver plano de compensação. Approval Pause recupera com event approve/reject. Terminal State não é recuperável, como COMPLETED ou FAILED após o máximo de retries.
7. Próximas leituras
Design de máquina de estados é só o começo. Modelagem de estado precisa combinar com o cenário de negócio; tarefas diferentes exigem granularidade de estado e estratégia de recuperação diferentes.
Navegação da série
| Artigo | Relação | Link |
|---|---|---|
| Human-in-the-loop Agent: quais passos exigem aprovação humana | Detalhes da pausa de aprovação | /blog/pt/posts/ai/20260707-human-in-the-loop-agent-approval-design/ |
| Controle de custos de Agent: model routing, orçamento de ferramentas e retry de falhas | Estratégia de orçamento e retry | /blog/pt/posts/ai/20260707-agent-cost-control-model-routing-tool-budget-cache-retry/ |
| Gestão de estado com LangGraph na prática: melhores práticas de arquitetura Agent em 2026 | Gestão de estado no LangGraph | /blog/pt/posts/ai/20260424-langgraph-agent-architecture/ |
| Monitoramento, alertas e recuperação de falhas para AI Agent: de logs a máquinas de estados | Monitoramento e recuperação | /blog/pt/posts/ai/20260527-ai-agent-monitoring-recovery/ |
| LangGraph vs AutoGen State Tracking | Comparação de frameworks | /blog/pt/posts/ai/20260526-langgraph-autogen-state-tracking/ |
| Datasets de avaliação de Agent e testes de regressão: como evitar quebrar tudo com uma mudança | Avaliação e testes de regressão | Próximo artigo da série |
Referências externas
Fontes de alta confiança:
| Fonte | Confiança | Tema | Link |
|---|---|---|---|
| Documentação LangGraph Persistence | high | Checkpointer, Store, Thread State, Checkpoint | https://docs.langchain.com/oss/python/langgraph/persistence |
| Documentação LangGraph Interrupts | high | interrupt(), Command(resume=…), thread_id | https://docs.langchain.com/oss/python/langgraph/interrupts |
| Documentação Temporal Durable Execution | high | Event History, Durable Execution, Resumable/Recoverable | https://docs.temporal.io/temporal |
| Documentação OpenAI Agents SDK Tracing | high | Trace, Span, workflow_name, trace_id | https://openai.github.io/openai-agents-python/tracing/ |
| Documentação AWS Step Functions State Machines | high | State Machine, Flow State, Task State, StartAt, Next | https://docs.aws.amazon.com/step-functions/latest/dg/concepts-statemachines.html |
| Stately: State machines and statecharts | medium | State, Event, Transition, Guard, Action, Hierarchy | https://stately.ai/docs/state-machines-and-statecharts |
Máquina de estados não é necessária para todo agente, mas tarefas complexas precisam explicitar o progresso. O próximo passo não é adicionar mais frameworks. É projetar State, Event, Transition, Guard e Action adequados ao seu cenário de negócio e mover o progresso da tarefa da linguagem natural do prompt para um estado estruturado.
Projetar uma máquina de estados para um agente de IA complexo
Divida uma tarefa complexa de agente de IA em state, event, guard, action, checkpoint, retry, compensation e terminal state, para que o progresso não fique escondido apenas no prompt.
⏱️ Estimated time: 45 min
- 1
Step 1: Liste os pontos de risco
Liste os efeitos externos, pontos de pausa humana, pontos de falha e condições terminais da tarefa. - 2
Step 2: Defina o conjunto mínimo de estados
Defina o menor conjunto útil de states, como pending, running, waiting_approval, retrying, compensating, succeeded, failed e cancelled. - 3
Step 3: Associe events a next states
Para cada state, escreva quais events ele pode receber e para qual next state cada event leva. - 4
Step 4: Adicione condições de guard
Adicione guards a transitions perigosas, incluindo permissão, orçamento, approval, chave de idempotência e verificação de estado de recurso externo. - 5
Step 5: Isole as actions de ferramentas
Coloque chamadas de ferramentas na camada action e registre resumo de input, resumo de output, traceId e resultado do efeito externo. - 6
Step 6: Defina políticas de falha
Defina retry policy, terminal state e compensation policy para cada caminho de falha. - 7
Step 7: Persista a base de recuperação
Defina um checkpoint ou event log para recuperação e trate o prompt como contexto temporário, não como única fonte da verdade.
FAQ
Se o agente falha no passo 5, devo voltar ao passo 1 ou continuar de um checkpoint?
O estado da tarefa deve ficar no prompt, no banco de dados, em um checkpoint do LangGraph ou em um job de fila?
Qual é a diferença entre máquina de estados e workflow/fluxograma?
Como garantir que o agente volte ao mesmo ponto de execução depois do approval?
Retry e compensation devem ficar no prompt ou nas regras de transição de estado?
Um agente simples de atendimento ao cliente precisa de máquina de estados?
14 min de leitura · Publicado em: 17 set 2026
Guia de engenharia de AI Agents
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Modelo de permissões para agentes de IA: identidade do usuário, permissões de ferramentas, auditoria e isolamento de secrets
Antes de conectar um agente de IA a ferramentas reais, desenhe o modelo de permissões: mapeamento de identidade, service accounts, per-tool permission, scopes, secret vault, rotação de chaves, approval policy, data boundary e audit log.
Parte 12 de 13
Próximo
Este é o post mais recente da série até agora.



Comentários
Entre com GitHub para comentar