O loop livre começa simples: envie o pedido ao modelo, execute a ferramenta que ele escolher e devolva o resultado para a próxima rodada. O problema aparece quando o agente precisa pausar para aprovação, repetir só uma etapa, impedir uma escrita ou explicar por que chegou a um estado terminal.

Uma máquina de estados ajuda quando o fluxo tem fases que precisam ser visíveis e transições que podem ser rejeitadas. Ela não torna o modelo determinístico. Ela coloca o modelo em lugares específicos do processo e deixa o runtime controlar o que pode acontecer antes e depois de cada chamada.

Se a primeira dúvida é onde guardar checkpoints e retomar uma execução, comece pela comparação entre fila e workflow para agentes de IA. Este post trata de outra camada: como representar o fluxo que o checkpoint precisa salvar.

Diagrama compara um loop livre de agente com uma máquina de estados que passa por planejar, ferramenta, revisão e conclusão.

Resposta curta

  • Mantenha o loop livre quando o caminho é exploratório e o efeito externo é pequeno.
  • Modele estados quando existem fases, pausas, permissões ou transições inválidas.
  • Deixe o modelo decidir onde há incerteza. Deixe o código decidir o que já tem contrato.
  • Persista o estado e teste as transições. O diagrama sozinho não protege a execução.

O que uma máquina de estados acrescenta ao agente?

Uma máquina de estados descreve um conjunto finito de estados e as transições permitidas entre eles. No vocabulário do AWS Step Functions, "Learn about state machines in Step Functions", estados podem executar tarefas, tomar decisões, esperar, criar ramificações ou encerrar a execução. O próximo passo não é uma sugestão escondida no prompt. É parte do contrato do workflow.

Para um agente, pense em cinco peças:

  • Estado: o que o runtime sabe sobre a execução agora.
  • Transição: o evento que pode mover a execução para outro estado.
  • Guarda: a condição que autoriza ou rejeita a transição.
  • Efeito: a chamada de ferramenta, gravação ou pedido de aprovação.
  • Terminal: o estado de sucesso, falha ou bloqueio que encerra o fluxo.

O ganho arquitetural está nessa fronteira. O modelo pode classificar uma intenção, propor parâmetros ou resumir um resultado. O runtime ainda precisa decidir se aquele resultado autoriza uma mudança de estado e se a ferramenta correspondente está disponível naquela fase.

Quais sinais mostram que o loop livre ficou frágil?

Troque o loop por estados explícitos quando o mesmo tipo de erro precisa ser impedido de forma mecânica, e não apenas descrito no system prompt. Quatro sinais aparecem com frequência: o loop repete uma etapa sem limite claro, uma tool call tem efeito externo, uma pessoa precisa aprovar o próximo passo, ou o suporte precisa reconstruir o caminho depois de uma falha.

O guia de workflows e agentes do LangGraph separa workflows, com caminhos predeterminados, de agentes, que definem dinamicamente o processo e o uso de ferramentas. A escolha não é moral nem binária. Um mesmo sistema pode usar um agente para interpretar uma entrada e um workflow explícito para aplicar o resultado.

Use este teste prático:

Pergunta Se a resposta for sim
Uma etapa pode cobrar, apagar, publicar ou alterar dados? Coloque uma guarda antes do efeito.
O fluxo precisa esperar uma pessoa ou evento externo? Modele um estado de espera.
Uma falha deve retomar de um ponto conhecido? Persista estado e checkpoint.
O caminho válido depende de uma regra já conhecida? Faça a transição no código.
A tarefa ainda não tem caminho conhecido? Preserve um trecho agentic, com limite.

Não transforme toda conversa em um grafo. Um classificador simples, uma busca e uma resposta final podem ser mais fáceis de operar como uma função. A máquina vale o custo quando torna um risco ou uma obrigação visível.

Como modelar estados e transições em TypeScript?

Use um campo discriminante para que cada estado carregue apenas os dados que fazem sentido nele. O Handbook do TypeScript, "Narrowing" explica que uma união discriminada pode ser refinada por uma propriedade literal. Isso não valida o valor recebido do modelo sozinho, mas impede que o código trate um estado de revisão como se ele já tivesse um resultado final.

O exemplo abaixo é ilustrativo. Ele não chama um provedor, não persiste dados e não substitui validação de entrada. O ponto é tornar transições ilegais impossíveis de esconder dentro de um while.

type AgentState =
  | { kind: "planning"; request: string }
  | { kind: "tool"; request: string; toolName: "lookup"; input: string }
  | { kind: "review"; request: string; result: string }
  | { kind: "done"; request: string; result: string }
  | { kind: "blocked"; request: string; reason: string };

type Event =
  | { kind: "plan-ready"; toolName: "lookup"; input: string }
  | { kind: "tool-finished"; result: string }
  | { kind: "approved" }
  | { kind: "rejected"; reason: string };

function transition(state: AgentState, event: Event): AgentState {
  switch (state.kind) {
    case "planning":
      if (event.kind !== "plan-ready") throw new Error("invalid transition");
      return { ...state, kind: "tool", toolName: event.toolName, input: event.input };

    case "tool":
      if (event.kind !== "tool-finished") throw new Error("invalid transition");
      return { kind: "review", request: state.request, result: event.result };

    case "review":
      if (event.kind === "approved") {
        return { kind: "done", request: state.request, result: state.result };
      }
      if (event.kind === "rejected") {
        return { kind: "blocked", request: state.request, reason: event.reason };
      }
      throw new Error("invalid transition");

    case "done":
    case "blocked":
      throw new Error("terminal state cannot advance");
  }
}

O código separa a resposta do modelo da transição. Uma camada agentic pode produzir plan-ready, mas o runtime precisa validar o nome e os argumentos da ferramenta antes de executar. A validação de tool calls em TypeScript é o próximo nível dessa fronteira: o estado controla a sequência; o contrato da ferramenta controla a forma dos dados.

Onde o modelo entra em uma arquitetura híbrida?

O modelo deve entrar onde existe incerteza útil, não em cada mudança de estado. Ele pode extrair intenção, escolher entre caminhos permitidos ou interpretar o resultado de uma ferramenta. O código pode executar uma sequência conhecida, contar tentativas, bloquear um efeito e encaminhar uma aprovação.

O Graph API do LangGraph expressa essa divisão com State, Nodes e Edges: nós recebem o estado e produzem atualizações; arestas fixas ou condicionais escolhem o próximo nó. A ideia é independente da biblioteca. Você pode implementá-la com uma função TypeScript, uma fila, Step Functions ou um runtime de agentes.

Um desenho comum fica assim:

  1. Classify: o modelo transforma o pedido em uma intenção estruturada.
  2. Plan: o runtime confere se a intenção tem um caminho suportado.
  3. Execute: código determinístico chama a ferramenta permitida.
  4. Review: uma regra ou pessoa aprova o efeito.
  5. Finish: o sistema registra o resultado e encerra.

Se a classificação vier inválida, não crie uma transição por aproximação. Envie para blocked ou peça esclarecimento. Se a ferramenta falhar, registre a falha no estado e escolha entre retry limitado, compensação ou revisão humana. O modelo não deve decidir sozinho se uma escrita externa já ocorreu.

Como persistência, retry e aprovação mudam o desenho?

Estados só ajudam depois que sobrevivem ao processo que os executa. O overview do LangGraph posiciona o runtime para workflows e agentes stateful de longa duração, com execução durável, human-in-the-loop e memória. Esses recursos não eliminam a necessidade de escolher o que entra no checkpoint.

Persista pelo menos o identificador da execução, a versão do schema, o estado atual, o número de tentativas, os eventos relevantes e a referência dos efeitos externos. Não salve apenas a última mensagem do modelo. Para retomar uma aprovação, o sistema precisa saber qual efeito estava aguardando e qual evento encerra a espera.

O retry também pertence ao desenho de transição. Uma chamada idempotente pode ser repetida com segurança. Uma cobrança, publicação ou envio de mensagem precisa de uma chave de operação, uma confirmação observável ou um estado de compensação. O post sobre execução durável, filas e workflows aprofundará a infraestrutura de retomada; aqui, o foco é não esconder esse contrato dentro de um loop genérico.

Como verificar uma máquina de estados de agente?

Teste o grafo como código antes de testar a qualidade da resposta do modelo. Uma suíte pequena deve provar que cada transição aceita o evento certo, rejeita eventos fora de fase e alcança um estado terminal. Depois, teste o comportamento da ferramenta e do modelo em camadas separadas.

Inclua pelo menos estes casos:

  • planning aceita um plano válido e rejeita uma aprovação.
  • tool não aceita outro plano antes de terminar a chamada.
  • review chega a done só com aprovação válida.
  • done e blocked não avançam.
  • Um retry não duplica o efeito externo.
  • Um checkpoint restaurado mantém a versão compatível do estado.
  • Um caminho de erro produz um evento investigável.

Registre execution_id, estado anterior, evento, estado seguinte, ferramenta, tentativa e motivo da rejeição. A observabilidade de agentes de código no CI mostra por que eventos estruturados tornam um loop investigável. O mesmo princípio vale aqui: uma narrativa do modelo não substitui o histórico de transições.

Quando uma máquina de estados é a escolha errada?

Não use uma máquina de estados para dar aparência de controle a um processo que continua sem critério de parada. Se os estados mudam a cada prompt, o grafo não está governando o agente; está apenas registrando improvisos. Nesse caso, defina primeiro o contrato do resultado, os efeitos permitidos e a condição de sucesso.

Um loop livre também pode ser a escolha correta para exploração, brainstorming, pesquisa aberta ou tarefas em que a próxima ferramenta depende de uma descoberta que ainda não existe. Mesmo assim, imponha orçamento de passos, timeout, allowlist de ferramentas e um estado de falha. "Autônomo" não significa "sem limites".

Para sistemas maiores, um híbrido costuma ser mais legível: state machine nas fronteiras importantes e um agente local dentro de uma etapa exploratória. A orquestração multiagente pode então ser tratada como um estado ou subworkflow, sem transformar cada mensagem entre agentes em uma nova arquitetura. Veja a orquestração multiagente para coding agents com TypeScript quando o problema for coordenação entre agentes, não apenas o ciclo de vida de um agente.

Perguntas frequentes

Uma máquina de estados torna o agente determinístico?

Não. Ela torna explícitos os estados e as transições que o runtime aceita. A saída do modelo continua variável, e por isso precisa de schema, validação e testes. O benefício é impedir que uma saída plausível pule uma aprovação ou chame uma ferramenta fora da fase permitida.

Preciso usar LangGraph ou Step Functions?

Não. As duas documentações são referências de arquiteturas que modelam estado, trabalho e transições. Você pode começar com uma união discriminada e uma função transition em TypeScript. Adote um runtime quando persistência, retomada, filas, espera ou observabilidade deixarem de ser responsabilidade pequena do seu serviço.

Uma fila substitui uma máquina de estados?

Não. A fila entrega trabalho e pode ajudar a distribuir tentativas. A máquina define qual estado a execução ocupa, quais eventos são válidos e quais efeitos podem ocorrer. Muitas arquiteturas usam as duas: a fila transporta o evento; o workflow valida a transição.

Como começo sem desenhar um grafo enorme?

Escolha um fluxo que já tenha uma pausa, um efeito externo ou uma falha difícil de investigar. Modele quatro estados, escreva as transições inválidas e adicione um teste por regra. Só depois extraia estados comuns. Se o diagrama não muda uma decisão de execução, ele ainda é documentação, não controle.

Conclusão

Uma máquina de estados para agentes de IA vale a pena quando o sistema precisa lembrar onde está, esperar algo, proteger um efeito ou explicar por que não avançou. O modelo pode continuar fazendo o trabalho incerto. O runtime deve guardar o estado, validar eventos, limitar ferramentas e encerrar o fluxo.

Comece pelo menor caminho que contém um risco real. Modele o estado, torne as transições ilegais testáveis e persista o checkpoint antes de adicionar mais autonomia. Em projetos longos de Claude Code e Codex, uso o RemoteCode como ferramenta do autor para continuar fluxos agentic. Ele não substitui o contrato de estados, os limites de ferramenta nem a revisão humana.

Fontes consultadas