Orkas Orkas
Início Blog Arquitetura
Arquitetura

Detecção de loop não é detecção de estagnação: capturando agentes que giram sem repetir

O Orkas tem três proteções contra loop. Nenhuma delas captura um modelo capaz que estagna, porque as três perguntam se ele está se repetindo — e um modelo travado nunca se repete. Aqui está o ponto cego, a definição de progresso do lado da saída que tomamos emprestada do BEACON, e o que pretendemos medir antes de mudar qualquer coisa.

Esta é a primeira de uma série de notas de design sobre agentes de longo horizonte, motivada por uma leitura atenta do BEACON (Universidade de Zhejiang, arXiv:2605.06078).

Para que um agente aguente uma tarefa longa, achamos que duas coisas precisam estar certas:

  • Ele continua progredindo rumo ao objetivo. Isso se divide em compactação de contexto (o que é seguro esquecer), design de marcos (como saber que um passo realmente terminou) e prevenção de estagnação (quando ele trava, algo precisa perceber).
  • Ele consegue refletir e melhorar.

Este post cobre a prevenção de estagnação, porque foi a que mais nos custou.

Em resumo Um agente que gira sem repetir ainda precisa ser pego A detecção de travamento vai no Orkas: uma execução longa avisa que travou em vez de gastar o resto do orçamento em silêncio.
Baixar o Orkas — grátis

O sintoma

Tivemos relatos de usuários e também observamos internamente: algumas tarefas muito longas param de avançar no meio do caminho.

Olhe os logs e o agente está ocupado — lendo arquivos, pesquisando, rodando comandos, sem parar. Mas meia hora depois nada avançou.

Nossa primeira explicação foi perda de contexto: a compactação descartou o registro de que um caminho já havia sido tentado, então o agente foi tentar de novo. Lendo o código e os logs juntos, isso se revelou apenas metade da história.

Já tínhamos proteções — três camadas delas

CamadaCritérioLimiares
Repetição exataNome da ferramenta + argumentos canonizados, idênticos byte a byteLOOP_WARN=3 aviso / LOOP_HARD=5 parada forçada
Quase-duplicataIdênticos exceto por campos voláteis de id / timestampNEAR_DUP_LOOP_WARN=6 / NEAR_DUP_LOOP_HARD=12
Convergência de giro≥2 compactações e ≥75% do orçamento de loop de ferramentas consumidoSPIN_CONVERGENCE_MIN_COMPACTIONS=2
SPIN_CONVERGENCE_TOOL_LOOP_RATIO=0.75

O comentário nessa terceira camada diz, literalmente: Compound "may be spinning after context loss" signal. Alguém já tinha previsto isso. Então o problema nunca foi não ter construído nada — foi que o que construímos não conseguia capturá-lo.

O ponto cego: as três são detectores do lado da entrada

A assinatura em que todas as camadas se baseiam é nome da ferramenta + argumentos canonizados. Isso responde exatamente uma pergunta: você está fazendo a mesma coisa duas vezes?

Mas um modelo capaz que está travado não repete chamadas. Ele faz assim:

ler arquivo A → grep X → reler A com outro intervalo de linhas
  → rodar um comando ligeiramente diferente → ler arquivo B → grep de novo …

Cada chamada tem assinatura distinta. As três camadas ficam em silêncio. E ao longo de todo esse trecho, o número de mudanças de estado verificáveis é zero: nenhum arquivo de fato reescrito, nenhum comando produzindo resultado novo, nada de irreversível acontecendo.

Detecção de loop não é detecção de estagnação. A primeira olha entradas. A segunda tem que olhar saídas.

O artigo fornece exatamente essa definição do lado da saída

A recompensa dentro do segmento no BEACON:

r_t = R_ms · γ^(t_k − t)    se o segmento termina em um marco
    = 0                     caso contrário

Um segmento que não termina em um marco ganha exatamente zero, independentemente de quantas ações continha. A contagem de ações nunca entra na fórmula. É a formalização mais limpa de ocupado ≠ progredindo que já vimos.

A camada da baseline é ainda mais dura. A baseline é o retorno médio por passo do grupo, então um segmento que levou 8 passos onde o grupo fez em média 5 tem o advantage inteiro puxado para o negativo, e a punição escala com o excesso. Girar em falso não é só não recompensado; é ativa e proporcionalmente punido.

A Figura 8 do artigo mostra uma trajetória que falhou onde as duas últimas ações recebem um idêntico −2,20. Essa cauda — o trecho após o último marco que nunca alcança outro — é a forma matemática do giro em falso. E é comum: trajetórias que concluem ao menos um subobjetivo mas falham na tarefa se mantêm em 39–47% das amostras.

Uma ablação descarta gatilhos por contagem de passos

ParticionamentoPontuaçãovs. baseline (72,8)
Divisão aleatória em 574,2+1,4
Marcos reais91,4+17,2

Dividir por contagens arbitrárias de passos vale quase nada. Dividir pela estrutura real vale muito.

Agora reveja nosso critério de terceira camada — 75% do orçamento de loop consumido. É um gatilho de contagem arbitrária de passos. Ele pergunta quanto você queimou, não o que você alcançou. A forma correta é:

✗  se passos > N                          → intervir
✓  se passos > N E zero marcos verificados → intervir

O segundo não dispara indevidamente em uma tarefa longa que está progredindo, porque tal tarefa atinge marcos pelo caminho. O primeiro dispara.

Há também um laço de realimentação positiva

Coloque as constantes lado a lado. A compactação dispara em 82% da janela de contexto. A convergência de giro exige duas compactações mais 75% do orçamento de loop antes de acionar.

giro → contexto enche → compactação dispara → estado durável some no resumo
     → re-deduzir o que se perdeu → mais giro

O detector de giro infere o giro observando que a compactação aconteceu repetidamente — mas a compactação é justamente o passo que causa a amnésia. Ele detecta um sintoma a jusante e ainda precisa esperar o laço dar duas voltas.

Pior: sua intervenção é induzir o modelo a se reancorar no próprio estado durável. Se o estado durável é precisamente o que foi compactado, não sobrou nada em que se reancorar. Isso é um remendo na camada de prompt para um problema na camada de estado.

O que vamos acrescentar: detecção de estagnação do lado da saída

Uma quarta camada, construída sobre dois contadores. Ambos derivados mecanicamente de observações de ferramentas que o host já registra; nenhum precisa de julgamento do modelo.

Passos desde o último marco verificado. A métrica de progresso mais simples possível, usada no critério composto acima e não isoladamente.

Mudanças de estado novas, desduplicadas. A mais útil das duas:

  • Uma leitura de arquivo cujo hash de conteúdo bate com uma leitura anterior não é informação nova — reler o mesmo arquivo em outro intervalo de linhas deixa o hash inalterado.
  • Um comando cujo nome, código de saída e hash de saída batem com uma execução anterior não é informação nova.
  • Uma escrita em que o after-hash é igual ao before-hash significa que nada foi de fato escrito.

Esse contador mira exatamente o caso que a correspondência por assinatura perde: toda ação diferente, ganho de informação zero. O critério é mecânico e não exige compreensão semântica.

Depois, a pressão deve ser contínua em vez de um único empurrão:

exponha o contador no contexto para o modelo enxergar
  → force uma revisão do plano (admita que este caminho morreu)
    → pergunte ao usuário
      → aborte, mas preserve os marcos já alcançados

Esse último degrau importa. Se a execução vai parar, deve parar segurando o que conquistou — que é exatamente aquele 39–47% de progresso parcial que o artigo mediu sendo jogado fora.

O que o artigo não nos dá

BEACON é um método de treinamento. Ele molda gradientes para que a política treinada fique menos propensa a vagar, mas não tem nenhum mecanismo próprio de detecção ou intervenção em tempo de execução. Fornece uma definição de progresso, não um controlador. Limiares, escadas de escalonamento e condições de aborto são nossos para projetar.

Sua baseline por passo também precisa de um comprimento médio de segmento do grupo como referência. Em produção, uma dada tarefa de usuário costuma rodar exatamente uma vez, então não há grupo. O melhor substituto disponível são estatísticas históricas de tarefas similares, consideravelmente mais ruidosas e sem nenhuma das garantias de isolamento de variância do artigo.

O primeiro movimento é medir, não corrigir

Antes de mudar qualquer lógica de decisão, queremos instrumentar e responder a uma pergunta que hoje não conseguimos: das estagnações que ocorrem em produção, quantas são do tipo amnésia e quantas do tipo sem-gradiente?

  • Majoritariamente acompanhadas de ganho de informação zero enquanto as assinaturas de chamada diferem todas → tipo sem-gradiente. As três camadas atuais estruturalmente não conseguem capturá-lo, e detecção do lado da saída é a correção.
  • Majoritariamente acompanhadas de releitura de conteúdo já compactado → tipo amnésia. O que precisa ser corrigido é o que a compactação preserva.

Essas duas conclusões exigem investimentos completamente diferentes. Medir primeiro é mais barato que projetar primeiro, e a instrumentação é quase gratuita porque as observações já existem.

Tudo acima se apoia em uma noção que esta nota vem usando sem definir: um marco verificado. A próxima nota trata disso. Por que uma etapa declarada concluída não é evidência de que ela esteja, quais duas metades já existem no produto sem nunca terem sido conectadas, e um critério que o artigo não tem: olhar irreversibilidade, não importância.