Objetivo da Aula
Descrever a estrutura de três padrões nomeados de loop autônomo: ReAct, Plan-Execute e Ralph Loop
Escolher o padrão de loop certo com base no tipo de tarefa, não por preferência ou hype
Explicar o papel do critério de parada em cada padrão e por que loop sem critério de parada é um risco arquitetural
Combinar padrões de loop com as camadas já vistas (contexto, permissões, estado, resolução de ferramentas)
Reconhecer os modos de falha característicos de cada padrão e como o harness os mitiga
Por que isso importa
"Fazer um agente" não é uma decisão única — é a escolha de um padrão de controle de fluxo específico, com trade-offs específicos, tão real quanto escolher entre processamento síncrono e assíncrono num sistema distribuído tradicional. Um agente que responde uma pergunta simples de uma vez, um agente que decompõe uma tarefa complexa em subtarefas antes de agir, e um agente que itera indefinidamente sobre o mesmo objetivo até um critério de qualidade ser satisfeito são três arquiteturas de controle de fluxo diferentes — mesmo que todos usem o mesmo LLM por baixo.
Escolher o padrão errado tem consequência prática direta: usar um loop simples de "pensa e age" (ReAct) para uma tarefa que exige planejamento antecipado leva a decisões míopes, corrigidas tarde demais. Usar um loop de planejamento rígido para uma tarefa exploratória, onde a informação necessária só aparece durante a execução, leva a planos que ficam obsoletos no primeiro passo. E usar um loop que itera indefinidamente (Ralph Loop) sem um critério de parada bem definido não é autonomia — é um processo que consome orçamento de tokens sem garantia de convergência.
Impacto direto no seu trabalho: antes de escrever a primeira linha do harness de um agente novo, a pergunta de arquiteto é "qual é a forma do problema — é uma pergunta e resposta, é uma tarefa decomponível em plano fixo, ou é uma tarefa que só se resolve por tentativa, avaliação e repetição?". A resposta a essa pergunta determina o padrão de loop, e o padrão de loop determina praticamente todo o resto do desenho do harness para aquele agente.
Conceitos Fundamentais
ReAct: raciocinar e agir, um passo de cada vez
ReAct (Reason + Act) é o padrão mais simples e mais amplamente usado: a cada iteração, o modelo raciocina sobre o estado atual, decide uma única próxima ação, o harness executa essa ação, o resultado volta para o contexto, e o ciclo se repete até o modelo decidir que a tarefa está completa.
Loop ReAct:
enquanto tarefa não concluída E dentro do limite de passos:
pensamento = modelo.raciocinar(contexto_atual)
acao = modelo.decidir_proxima_acao(pensamento)
resultado = harness.executar(acao) # cap. 1.3, 1.5
contexto_atual = atualizar(contexto_atual, resultado)
if modelo.avalia_tarefa_concluida(contexto_atual):
parar()
Exemplo de traço de execução (agente de suporte técnico):
Pensamento: "preciso saber o status do pedido antes de
responder"
Ação: consultar_pedido(id=4521)
Resultado: {status: "em transporte", previsao: "3 dias"}
Pensamento: "tenho a informação, posso responder"
Ação: responder_usuario("Seu pedido está em transporte...")
→ tarefa concluídaO ponto forte de ReAct é a adaptabilidade passo a passo: cada ação leva em conta o resultado real da ação anterior, então o agente reage a informação nova (um erro inesperado, um dado que muda o plano) sem precisar replanejar formalmente. O ponto fraco é justamente a ausência de visão de conjunto: como o modelo decide uma ação de cada vez, ele pode tomar decisões localmente razoáveis que, somadas, levam a um caminho ineficiente ou a um beco sem saída que só um plano antecipado teria evitado.
Plan-Execute: separar "o que fazer" de "fazer"
Plan-Execute resolve a fraqueza estrutural do ReAct dividindo o trabalho em duas fases distintas: primeiro o modelo gera um plano completo (uma sequência de passos, decidida antes de qualquer execução), depois o harness executa esse plano — passo a passo, mas sem replanejar a cada micro-decisão, só quando o plano encontra um obstáculo que o invalida.
Loop Plan-Execute:
plano = modelo.gerar_plano(objetivo, contexto_inicial)
# plano = [passo_1, passo_2, ..., passo_n]
para cada passo in plano:
resultado = harness.executar(passo)
if resultado.invalida_plano_restante():
plano = modelo.replanejar(objetivo, resultado,
passos_restantes(plano))
registrar_progresso(passo, resultado) # cap. 1.4
verificar_objetivo_atingido(objetivo, resultados_acumulados)
Exemplo (agente de migração de dados):
Plano gerado:
1. Ler schema da tabela de origem
2. Validar compatibilidade com schema de destino
3. Gerar script de transformação
4. Rodar migração em ambiente de staging
5. Validar contagem de registros migrados
6. Solicitar aprovação humana para produção (cap. 1.3)
→ cada passo executa na ordem planejada; só o passo 2
(validação de compatibilidade), se falhar, dispara
replanejamento antes de prosseguir.Plan-Execute é mais previsível e mais auditável — o plano inteiro pode ser revisado por um humano antes da execução começar, o que é valioso justamente para tarefas de raio de impacto mais alto (capítulo 1.3). O custo é rigidez: se a tarefa é genuinamente exploratória (a informação necessária para decidir o passo 3 só aparece durante o passo 1), gerar um plano completo antecipadamente é prematuro, e o sistema vai gastar ciclos de replanejamento que um loop ReAct simples teria evitado por nunca ter se comprometido com um plano rígido em primeiro lugar.
Fundamento: Padrão de Loop como Escolha de Controle de Fluxo
Em engenharia de software tradicional, controle de fluxo síncrono, assíncrono orientado a eventos, e pipeline em lote são escolhas arquiteturais distintas, cada uma certa para uma classe diferente de problema — ninguém escolhe "por padrão", escolhe pelo formato do problema. Padrões de loop de agente ocupam o mesmo lugar na arquitetura de sistemas de IA: ReAct é o equivalente a um loop reativo síncrono (decide e age, um passo de cada vez, reagindo ao resultado); Plan-Execute é o equivalente a um pipeline planejado (decompõe antes de executar); Ralph Loop, visto a seguir, é o equivalente a um processo de convergência iterativa (repete até um critério de qualidade ser satisfeito). Nenhum é estrategicamente superior — cada um resolve uma forma diferente de problema.
Ralph Loop: iteração até critério de parada, sobre o mesmo objetivo
O terceiro padrão — chamado neste livro de Ralph Loop — descreve um agente que roda repetidamente sobre o mesmo objetivo, avaliando seu próprio progresso a cada rodada, até que um critério de parada explícito seja satisfeito (qualidade atingida, limite de tentativas esgotado, ou revisão humana solicitada). Diferente de ReAct (que avança passo a passo dentro de uma única execução) e de Plan-Execute (que decompõe o objetivo em subtarefas sequenciais), o Ralph Loop trata cada rodada como uma tentativa completa e independente de resolver o objetivo inteiro, usando o resultado da rodada anterior como ponto de partida da próxima.
Loop Ralph:
tentativa = 0
resultado_atual = estado_inicial
enquanto NAO criterio_de_parada(resultado_atual)
E tentativa < limite_maximo:
tentativa += 1
resultado_atual = modelo.tentar_objetivo_completo(
objetivo,
resultado_anterior=resultado_atual)
avaliacao = avaliar_qualidade(resultado_atual, objetivo)
registrar_tentativa(tentativa, resultado_atual, avaliacao) # 1.4
if criterio_de_parada(resultado_atual):
finalizar_com_sucesso(resultado_atual)
else:
escalar_para_revisao_humana(resultado_atual, tentativa) # 1.3
Exemplo (agente que corrige uma suíte de testes quebrada):
Tentativa 1: aplica correção, roda testes → 12 de 20 passam
Tentativa 2: analisa falhas restantes, ajusta → 18 de 20 passam
Tentativa 3: ajusta os 2 casos restantes → 20 de 20 passam
→ critério de parada satisfeito (100% dos testes passam),
loop encerra com sucesso na tentativa 3O Ralph Loop é o padrão certo quando o objetivo é claro e verificável (existe uma forma objetiva de medir "isso está pronto"), mas o caminho até lá não é conhecido de antemão e se beneficia de tentativas sucessivas com aprendizado entre elas — diferente de ReAct, que avança em passos discretos dentro de uma única tentativa, o Ralph Loop trata cada rodada completa como uma nova tentativa informada pela anterior.
Aprofundamento Técnico
O critério de parada é a parte mais crítica do Ralph Loop — e a mais frequentemente mal desenhada
Um Ralph Loop sem critério de parada objetivo e verificável não é um sistema autônomo — é um processo que roda até estourar o limite de tentativas ou o orçamento de tokens, sem garantia de ter convergido para algo útil no meio do caminho. O critério de parada precisa ser, sempre que possível, verificável por um mecanismo externo ao próprio modelo — não uma autoavaliação do modelo dizendo "acho que terminei":
Critério de parada FRACO (autoavaliação do modelo):
parar_se(modelo.acha_que_terminou() == verdadeiro)
→ o mesmo componente que executou a tarefa também avalia
se ela está correta — nenhuma verificação independente,
viés de confirmação estrutural.
Critério de parada FORTE (verificação externa e objetiva):
parar_se(suite_de_testes.passou() == 100%)
parar_se(schema_validator.validar(saida) == sem_erros)
parar_se(metrica_de_negocio(saida) >= limiar_aceitavel)
→ verificação roda FORA do modelo, sobre o resultado real
produzido — o modelo não pode "se convencer" de sucesso
que não aconteceu de fato.Esse é o mesmo princípio do capítulo 1.1 aplicado ao controle de loop: decisões com consequência real (quando parar de iterar, quando declarar sucesso) não deveriam ser propriedade exclusiva do componente probabilístico. O harness precisa de um verificador externo e determinístico sempre que a natureza da tarefa permitir — testes automatizados, validação de schema, métricas de negócio calculadas de forma independente do modelo que gerou o resultado.
Limite de tentativas e custo: o Ralph Loop não é gratuito
Cada rodada de um Ralph Loop é uma chamada completa ao motor de inferência — o custo cresce linearmente (ou pior, se o contexto acumulado de tentativas anteriores cresce a cada rodada) com o número de tentativas. Um limite máximo de tentativas não é apenas proteção contra loop infinito; é uma decisão de orçamento (aprofundada na Parte 5 deste livro, sobre FinOps de IA). Um harness bem desenhado trata o limite de tentativas como um parâmetro configurável por raio de impacto e criticidade da tarefa, não como uma constante arbitrária copiada de um exemplo — tarefas baratas de corrigir manualmente se erradas podem ter limites generosos; tarefas caras (em tempo de máquina ou em risco) devem escalar para revisão humana mais cedo.
Combinando padrões: eles não são mutuamente exclusivos
Na prática, sistemas de produção frequentemente combinam os três padrões em camadas, não escolhem um único padrão para o sistema inteiro:
Sistema composto (exemplo real de arquitetura):
Nível externo: Plan-Execute
→ decompõe "migrar o módulo de pagamentos" em passos:
[1. mapear dependências, 2. escrever testes de
regressão, 3. refatorar, 4. validar, 5. deploy
assistido]
Nível intermediário (dentro do passo 3 "refatorar"):
Ralph Loop
→ itera sobre o mesmo objetivo ("refatorar mantendo
testes verdes") até o critério de parada (suíte de
testes 100% verde) ser satisfeito, ou escalar para
humano após N tentativas
Nível interno (dentro de cada tentativa do Ralph Loop):
ReAct
→ a cada tentativa, o modelo raciocina e age passo a
passo (ler arquivo, editar, rodar teste, reagir ao
resultado) até considerar aquela tentativa concluídaEssa composição em camadas — plano no nível macro, iteração de convergência no nível intermediário, reação passo a passo no nível micro — é frequentemente a arquitetura real de sistemas agentic maduros. A escolha de padrão de loop, portanto, não é uma decisão única e global do sistema; é uma decisão que se repete em cada nível de granularidade da tarefa, sempre guiada pela mesma pergunta central: o problema neste nível é mais bem resolvido por decomposição antecipada, por reação passo a passo, ou por convergência iterativa sobre um critério verificável?
Padrões e Armadilhas
Padrões recomendados
Padrão 1: torne o padrão de loop uma escolha explícita de configuração, não um acidente de implementação. Um agente deveria declarar, de forma legível, qual padrão está usando em cada camada de granularidade — não deixar que a escolha emerja implicitamente de como o código foi escrito na primeira versão. Isso facilita tanto a revisão arquitetural quanto a troca de padrão quando o tipo de tarefa muda.
Padrão 2: limite o crescimento de contexto entre tentativas do Ralph Loop. Se cada tentativa reinjeta o histórico completo de todas as tentativas anteriores sem resumo, o custo por rodada cresce e a janela de contexto se aproxima do limite rapidamente. Resumir o essencial de cada tentativa (o que foi tentado, por que falhou) antes de iniciar a próxima mantém o loop sustentável por mais rodadas.
Padrão 3: defina, antes de começar, o que "escalar para humano" significa operacionalmente. Um limite de tentativas esgotado não deveria terminar em silêncio ou em erro genérico — deveria produzir um resumo estruturado do que foi tentado, por que cada tentativa falhou, e qual é o estado atual, para que a pessoa que assume a tarefa não precise reconstruir esse histórico do zero.
Armadilhas comuns
⚠️ Armadilha 1: usar ReAct para uma tarefa que precisa de aprovação prévia do caminho inteiro. O que acontece: um agente com ReAct começa a executar ações de raio de impacto crescente sem que exista, em nenhum momento, uma visão consolidada do plano completo para um humano revisar antes da primeira ação irreversível. Para tarefas de alto risco, isso significa que a primeira oportunidade de intervenção humana chega tarde demais. Versão correta: quando a tarefa envolve ações de Nível 2-3 (capítulo 1.3), Plan-Execute com aprovação do plano antes da execução é geralmente mais seguro que ReAct puro.
⚠️ Armadilha 2: Ralph Loop sem limite de tentativas explícito. O que acontece: o loop itera "até dar certo", sem um teto configurado — em cenários onde o objetivo é mal especificado ou inatingível com as ferramentas disponíveis, isso consome tempo e orçamento de tokens indefinidamente, sem sinalizar falha a ninguém. Versão correta: todo Ralph Loop tem um limite máximo de tentativas como parte obrigatória de sua configuração, nunca opcional.
⚠️ Armadilha 3: replanejamento excessivo em Plan-Execute por sensibilidade exagerada a desvios. O que acontece: o critério que decide "este resultado invalida o plano restante" é calibrado de forma tão sensível que qualquer pequena variação (um aviso não crítico, um dado levemente diferente do esperado) dispara replanejamento completo, tornando o padrão tão caro e imprevisível quanto ReAct puro — anulando a vantagem de previsibilidade que motivou a escolha de Plan-Execute em primeiro lugar. Versão correta: calibrar o gatilho de replanejamento para desvios que de fato comprometem o objetivo, não qualquer ruído operacional.