---
title: "Loops de agentes: o que sobrou depois do hype do Ralph loop"
description: "O while-true em cima de um agente virou meme e virou hype. Passado o entusiasmo, sobrou o que importa: loop com critério de parada, loop com verificação e loop com orçamento. Loop burro queima dinheiro; loop com estrutura converge."
date: 2026-08-11
canonical: https://arvor.co/noticias/loops-de-agentes-depois-do-ralph-loop
---

Em 2025, Geoffrey Huntley batizou de [Ralph loop](https://ghuntley.com/loop/) uma ideia constrangedoramente simples: colocar um agente de código dentro de um `while true` de bash e deixar rodando. O nome vem do Ralph Wiggum, dos Simpsons — persistência alegre e ingênua. Ele provou o ponto deixando um agente construir uma linguagem de programação, compilador incluído, numa corrida longa sem supervisão.

O truque pegou. Virou post, virou palestra, virou pacote — a Vercel Labs chegou a publicar um [ralph-loop-agent](https://github.com/vercel-labs/ralph-loop-agent) para o AI SDK. E, como todo truque que pega, passou por aquela fase em que virou resposta para tudo: "não precisa orquestrar nada, é só rodar em loop".

Minha leitura, um ano depois: o hype esfriou, e ainda bem. Porque o que sobrou é a parte boa — e a parte boa não é o `while true`. É o que você coloca dentro dele.

## O que o Ralph loop acertou de verdade

Três coisas, e todas continuam certas.

A primeira: **contexto fresco a cada iteração**. Cada volta abre um processo novo, com janela limpa. Isso ataca de frente a degradação de contexto longo, que é o modo de falha mais comum de agente de código. Foi exatamente o princípio que usamos ao construir o [Relentless](/relentless): a memória entre iterações não vive numa conversa infinita, vive no git.

A segunda: **memória externa em disco**. O estado sai da cabeça do agente e vai para arquivos, commits, artefatos — coisas que sobrevivem ao fim do processo e que um humano consegue ler.

A terceira: **persistência barata bate genialidade cara**. Vinte tentativas medianas com verificação entre elas costumam vencer uma tentativa brilhante sem verificação nenhuma. Isso é estatística, não filosofia.

## Onde o loop burro queima dinheiro

O problema nunca foi o loop. Foi o loop sem nenhuma das três perguntas que importam: quando eu paro, como eu sei que melhorou, e quanto isso pode custar.

Sem critério de parada, o agente entra em oscilação. Já vi um loop passar a madrugada trocando uma abstração por outra e voltando para a primeira — commit A, commit B, commit A de novo — cada volta com contexto limpo, cada volta convencida de que estava consertando algo. Contexto fresco é uma faca de dois gumes: o agente não lembra que já tentou isso.

Sem verificação, o loop otimiza aparência. O agente "termina" a tarefa, o loop pergunta se acabou, o agente responde que sim porque o texto que ele escreveu parece uma conclusão. Autoavaliação em loop é uma máquina de gerar confiança sem gerar acerto.

Sem orçamento, o loop transforma um erro de julgamento em fatura. Deixar um agente rodando sem teto de tokens, tempo ou iterações é a versão 2026 de esquecer um cluster ligado no fim de semana. A diferença é que o cluster pelo menos não commita.

## Loop com critério de parada: loop-until-dry

O padrão que mais uso é o que chamo de loop-until-dry. Você não roda até "estar pronto" — você roda até o loop ficar seco.

Uma rodada é seca quando ela não produz mudança material: nenhum arquivo relevante alterado, nenhuma tarefa fechada, nenhum teste novo passando. Uma rodada seca sozinha não decide nada, porque pode ser azar. Duas ou três rodadas secas seguidas — o K do critério — significam que a fonte de trabalho acabou de verdade. Aí você para.

O detalhe que faz diferença é medir secura no artefato, não na narrativa do agente. Diff vazio é seco. "Acredito que a implementação está completa" não é.

## Loop com verificação: gerar, refutar, aceitar o que sobreviver

Loop bom não é gerar-e-repetir, é gerar-e-tentar-derrubar. A iteração vira um mini-processo adversarial: um passo produz o artefato, outro passo — com contexto próprio e objetivo invertido — tenta refutar. Só entra no repositório o que sobreviveu à tentativa de refutação.

<div style="overflow-x:auto;max-width:640px;margin:26px auto 10px">
<svg viewBox="0 0 640 274" role="img" aria-labelledby="al1-t" style="width:100%;height:auto;min-width:560px;display:block;margin:0 auto" font-family="ui-monospace, SFMono-Regular, Menlo, monospace">
  <title id="al1-t">Ciclo de iteração: gerar, refutar e a pergunta “sobreviveu?”. O que sobrevive é aceito, o que não volta para o início, e o loop inteiro para quando K rodadas seguidas saem secas.</title>
  <defs>
    <marker id="al1-c" viewBox="0 0 8 8" refX="7.5" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="#27e3ff"/></marker>
    <marker id="al1-g" viewBox="0 0 8 8" refX="7.5" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="#d4af37"/></marker>
  </defs>
  <text x="16" y="22" font-size="13" letter-spacing="1.2" fill="#27e3ff">LOOP COM VERIFICAÇÃO</text>
  <rect x="16" y="74" width="110" height="36" rx="7" fill="#0a1828" stroke="#4a6785"/>
  <text x="71" y="96.5" text-anchor="middle" font-size="13" fill="#f0ede6">gerar</text>
  <path d="M126 92 H166" fill="none" stroke="#27e3ff" stroke-width="1.5" marker-end="url(#al1-c)"/>
  <rect x="166" y="74" width="124" height="36" rx="7" fill="#0a1828" stroke="#4a6785"/>
  <text x="228" y="96.5" text-anchor="middle" font-size="13" fill="#f0ede6">refutar</text>
  <path d="M290 92 H326" fill="none" stroke="#27e3ff" stroke-width="1.5" marker-end="url(#al1-c)"/>
  <path d="M390 52 L454 92 L390 132 L326 92 Z" fill="#0a1828" stroke="#27e3ff"/>
  <text x="390" y="96" text-anchor="middle" font-size="13" fill="#f0ede6">sobreviveu?</text>
  <path d="M454 92 H490" fill="none" stroke="#27e3ff" stroke-width="1.5" marker-end="url(#al1-c)"/>
  <text x="472" y="84" text-anchor="middle" font-size="13" fill="#7a9ab8">sim</text>
  <rect x="490" y="74" width="110" height="36" rx="7" fill="#0a1828" stroke="#3ddc97"/>
  <text x="545" y="96.5" text-anchor="middle" font-size="13" fill="#f0ede6">aceita</text>
  <path d="M390 132 V180" fill="none" stroke="#27e3ff" stroke-width="1.5"/>
  <text x="400" y="152" font-size="13" fill="#7a9ab8">não</text>
  <path d="M545 110 V180 H71 V110" fill="none" stroke="#27e3ff" stroke-width="1.5" marker-end="url(#al1-c)"/>
  <text x="196" y="172" text-anchor="middle" font-size="13" fill="#7a9ab8">próxima rodada</text>
  <circle cx="300" cy="180" r="3.5" fill="#27e3ff"/>
  <path d="M300 180 V222" fill="none" stroke="#d4af37" stroke-width="1.5" marker-end="url(#al1-g)"/>
  <text x="312" y="204" font-size="13" fill="#d4af37">K rodadas secas</text>
  <rect x="245" y="222" width="110" height="36" rx="7" fill="#0a1828" stroke="#d4af37"/>
  <text x="300" y="244.5" text-anchor="middle" font-size="13" fill="#d4af37">para</text>
</svg>
</div>

*A iteração só entrega o que sobrevive à tentativa de refutação — e o loop inteiro para quando K rodadas seguidas saem secas.*

Isso muda o que o loop otimiza. Sem refutação, ele converge para o que parece pronto. Com refutação, ele converge para o que resiste. E o refutador mais barato quase nunca é um LLM: teste, compilador, type checker, linter e schema derrubam mais coisa por real gasto do que qualquer prompt de revisão.

É a mesma ideia de verificação adversarial que descrevi em [grafos de agentes](/noticias/grafos-de-agentes-orquestracao-2026), só que aplicada no tempo em vez de no espaço.

## Loop com orçamento: teto antes de começar

Todo loop que roda sem supervisão precisa de três tetos declarados antes da primeira volta: máximo de iterações, máximo de tokens (ou custo) e máximo de tempo de parede. E precisa de uma regra de saída para quando bater no teto — abrir um relatório do estado, não sumir no meio.

<div style="overflow-x:auto;max-width:640px;margin:26px auto 10px">
<svg viewBox="0 0 640 244" role="img" aria-labelledby="al2-t" style="width:100%;height:auto;min-width:560px;display:block;margin:0 auto" font-family="ui-monospace, SFMono-Regular, Menlo, monospace">
  <title id="al2-t">Três medidores de orçamento do loop: iterações, tokens e tempo, com um teto comum tracejado. Ao bater no teto, o loop escreve um relatório do estado e para.</title>
  <defs>
    <marker id="al2-c" viewBox="0 0 8 8" refX="7.5" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="#27e3ff"/></marker>
    <marker id="al2-g" viewBox="0 0 8 8" refX="7.5" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="#d4af37"/></marker>
  </defs>
  <text x="16" y="22" font-size="13" letter-spacing="1.2" fill="#d4af37">ORÇAMENTO DO LOOP</text>
  <text x="16" y="64.5" font-size="13" fill="#7a9ab8">iterações</text>
  <rect x="120" y="51" width="380" height="18" rx="9" fill="#0a1828" stroke="#24405a"/>
  <rect x="120" y="51" width="220" height="18" rx="9" fill="#27e3ff" opacity="0.6"/>
  <text x="510" y="64.5" font-size="13" fill="#7a9ab8">12 / 20</text>
  <text x="16" y="108.5" font-size="13" fill="#7a9ab8">tokens</text>
  <rect x="120" y="95" width="380" height="18" rx="9" fill="#0a1828" stroke="#24405a"/>
  <rect x="120" y="95" width="318" height="18" rx="9" fill="#27e3ff" opacity="0.6"/>
  <text x="510" y="108.5" font-size="13" fill="#7a9ab8">1.2M / 2M</text>
  <text x="16" y="152.5" font-size="13" fill="#7a9ab8">tempo</text>
  <rect x="120" y="139" width="380" height="18" rx="9" fill="#0a1828" stroke="#24405a"/>
  <rect x="120" y="139" width="160" height="18" rx="9" fill="#27e3ff" opacity="0.6"/>
  <text x="510" y="152.5" font-size="13" fill="#7a9ab8">38m / 60m</text>
  <line x1="452" y1="38" x2="452" y2="170" stroke="#d4af37" stroke-dasharray="4 4"/>
  <text x="452" y="30" text-anchor="middle" font-size="13" fill="#d4af37">teto</text>
  <path d="M452 170 V196" fill="none" stroke="#d4af37" stroke-width="1.5" marker-end="url(#al2-g)"/>
  <text x="357" y="216" text-anchor="end" font-size="13" fill="#7a9ab8">ao bater no teto:</text>
  <rect x="367" y="196" width="170" height="32" rx="7" fill="#0a1828" stroke="#d4af37"/>
  <text x="452" y="216.5" text-anchor="middle" font-size="13" fill="#d4af37">relatório e para</text>
</svg>
</div>

*Três tetos declarados antes da primeira volta. Ao bater em qualquer um deles, o loop escreve o estado e para — não some no meio.*

Orçamento também é uma decisão de arquitetura, não só de contabilidade. Quando você sabe quanto uma tarefa pode custar, você decide o modelo por nó em vez de usar o mais caro em tudo. Foi isso que virou o Smart Auto Mode do Relentless: escolher o modelo pela complexidade real da tarefa, não pelo medo de errar. A economia não vem de usar modelo pior — vem de parar de usar modelo caro para renomear variável.

## Loop é o motor, grafo é o mapa

A discussão "loop ou grafo?" é falsa, e ela atrasou muita gente boa em 2025.

Grafo é topologia: quem depende de quem, o que pode rodar em paralelo, onde ficam as barreiras e os verificadores. Loop é dinâmica: quantas vezes um nó tenta antes de desistir, e o que faz o conjunto avançar até secar.

Eles se compõem em dois níveis. Dentro do nó, o loop é local — tenta, verifica, tenta de novo, com orçamento próprio e critério de parada próprio. Fora, o loop é global: o grafo inteiro roda de novo enquanto houver trabalho, e para quando K rodadas seguidas saem secas. Loop sem grafo é força bruta cara. Grafo sem loop é uma esteira que trava no primeiro nó teimoso e espera um humano.

Um ano depois do meme, é isso que sobrou do Ralph loop — e é bastante. Não a promessa de que persistência substitui arquitetura, mas a prova de que persistência estruturada é surpreendentemente forte. O `while true` era a parte fácil. Critério de parada, refutação e orçamento são o trabalho.

Se você já deixou um agente rodando a noite inteira e acordou com uma fatura e nenhum progresso, o problema não foi o loop. Foi a ausência das três perguntas. [Fale com a gente](/contato) ou conheça nossa [consultoria agêntica](/consultoria) — e se quiser ver o motor rodando, o [Relentless](/relentless) é open source.
