Executando verificação de segurança...
1

[IA] autoresearch v1.0: um loop autônomo de pesquisa com crítico LLM local

1. A anomalia dos 22%

Buscas por "agente de IA" cresceram 22% no Brasil em 2026, segundo levantamento recente da Locaweb noticiado pela IstoÉ Dinheiro em 23 de abril. O mesmo levantamento mostra que "o que é um agente de IA" e "como construir um agente de IA" permanecem entre os termos mais consultados. O hiato entre intenção de adoção e entendimento operacional é amplo e visível.

Este artigo preenche parte desse hiato. Não com definições copiadas de páginas de produto, mas com um artefato funcional: um loop autônomo de pesquisa que qualquer pessoa com laptop, Ollama e git pode rodar em cinco minutos. O artefato é o autoresearch v1.0, depositado no Zenodo sob DOI 10.5281/zenodo.19772195. Ele generaliza um padrão lançado por Andrej Karpathy, retirando-o de um único repositório de pretraining de LLM e levando-o a um pequeno pacote Python utilizável para qualquer problema de otimização que satisfaça quatro condições.

As condições são simples: uma métrica escalar única, um orçamento de tempo fixo, um único arquivo mutável e uma branch git. O restante do artigo mostra por que essas quatro condições bastam, o que o harness faz entre iterações e como três problemas distintos convergem sob ele.

2. Definição operacional: agente como loop, não como chat

Uma confusão comum trata agentes como chatbots mais inteligentes. O levantamento da Locaweb é consistente com essa confusão: a maioria das consultas é operacional ("agente de IA para WhatsApp", "para atendimento ao cliente"), mas as consultas fundacionais ainda são definicionais ("o que é um agente", "como construir um").

A definição operacional que escala com a tecnologia merece ser declarada com precisão:

Um agente é um loop critique-propose-execute-decide com estado persistente, não uma resposta única a um único prompt.

Cada palavra carrega peso.

  • Critique implica acesso ao resultado da tentativa anterior e uma noção de melhor e pior. Sem medição não há crítica.
  • Propose implica saída estruturada, não texto livre. A proposta deve ser aplicável ao sistema sob mudança.
  • Execute implica que a proposta aterrissa em algum lugar com consequência mensurável (mudança de código, atualização de configuração, chamada de API) e roda sob recursos delimitados.
  • Decide implica regra de classificação sobre o resultado e função de próximo estado. Manter, descartar, retentar, parar.
  • Estado persistente implica memória das tentativas, que é o que permite o loop convergir em vez de vagar.

Esta definição não depende de tamanho de modelo, fornecedor ou tier de marketing. É mecânica. Um modelo local pequeno rodando este loop é um agente no sentido estrito; um modelo de fronteira respondendo uma pergunta por vez não é.

3. A arquitetura do harness

O autoresearch implementa o loop com um conjunto deliberadamente pequeno de partes móveis. O diagrama em prosa:

problem.yaml          ┐
contrato read-only    │
dados e avaliação     │   →  crítico LLM (Ollama)  →  proposta JSON
                      │           │
                      │           ↓
                      │   harness aplica proposta a solution.py
                      │           │
                      │           ↓
                      │   runner executa prepare.py + evaluate.py
                      │   sob timeout duro (cap no orçamento de recurso)
                      │           │
                      │           ↓
                      │   classificador: keep | discard | crash
                      │           │
                      │           ↓
                      │   git: avança branch (keep) ou reseta (discard/crash)
                      │           │
                      │           ↓
solution.py (mutável) ┘   audit log: results.tsv + AUDIT_LOG.md + critic_logs/

Três componentes carregam o design.

O crítico é um LLM local rodando em Ollama (família Gemma por default; qualquer endpoint OpenAI-compatível funciona). Sua saída é restringida por um JSON Schema com sete campos:

  • thought_process: o rastro da hipótese de trabalho.
  • alternatives_considered: os movimentos vice-líderes que foram rejeitados.
  • hypothesis: a alegação concreta e testável sobre o efeito esperado.
  • expected_delta: a melhoria predita na métrica.
  • justification: a fundamentação em propriedades conhecidas do problema.
  • code_pseudocode: a mudança proposta em nível de pseudo-código.
  • risk_level: a probabilidade que o próprio crítico atribui à degradação.

JSON Schema não é decoração. Força o crítico a se comprometer com uma mudança específica e prever seu efeito, ambos verificáveis post hoc. Propostas em texto livre não permitem isso.

O harness aplica a proposta ao único arquivo mutável (solution.py), faz commit da mudança na branch de pesquisa ativa, e dispara o runner.

O runner executa o prepare.py (configuração de dados) e o evaluate.py (computação da métrica), ambos read-only, sob timeout duro. O timeout faz parte do contrato, não é rede de proteção. Torna runs comparáveis entre propostas e entre máquinas distintas. O classificador lê o stdout do runner, faz parse da métrica e emite uma das três etiquetas:

  • keep se a métrica melhorou em relação ao melhor corrente.
  • discard se a métrica não melhorou, ou melhorou ao custo de uma restrição declarada pelo evaluate.py.
  • crash se o runner falhou (timeout, exceção, saída malformada).

Toda iteração escreve uma linha em results.tsv e um bloco JSONL em critic_logs/. O audit log é o estado persistente que torna o loop convergente em vez de aleatório.

4. Três estudos de caso

O autoresearch v1.0 ship com três exemplos funcionais, cada um contendo um diretório sample_run completo gravado durante o desenvolvimento. O gráfico abaixo resume a convergência dos três.

[Figura 1: posts/images/PROJ-003.png. Painéis de convergência para os três exemplos shippados. Iteração no eixo x, métrica no eixo y, propostas mantidas em verde, descartadas em vermelho, trajetória do melhor-até-agora em linha azul.]

4.1 Busca heurística para TSP

O problema é um Caixeiro Viajante euclidiano de 30 cidades com coordenadas aleatórias, avaliado por comprimento total do tour. A solução baseline retorna o tour aleatório inicial. O crítico rodou quatro iterações dentro do orçamento de tempo:

Iter   Tour length   Status    Movimento
----   -----------   -------   --------------------------------------
   0        25,251   keep      baseline (tour aleatório)
   1         5,975   keep      busca local 2-opt sobre init aleatório
   2         5,893   keep      init nearest-neighbor + 2-opt
   3         5,893   discard   simulated annealing sobre NN init

Melhoria: 76,7% em relação ao baseline. Três de quatro movimentos aceitos. O descarte na iteração 3 é informativo: o crítico propôs simulated annealing sobre NN+2-opt, o runner retornou a mesma métrica dentro do timeout, e o harness corretamente rejeitou o movimento por não demonstrar melhoria. A branch reverteu para a iteração 2.

4.2 Tuning de hiperparâmetros XGBoost

O problema é uma tarefa de regressão com RMSE como objetivo. Seis iterações:

Iter   RMSE     Status    Movimento
----   ------   -------   ------------------------------------------
   0   0,4639   keep      baseline (n_estimators=500, eta=0,1)
   1   0,4503   keep      n_estimators=750
   2   0,4561   discard   eta=0,05
   3   0,4485   keep      n_estimators=1000
   4   0,4449   keep      eta=0,08
   5   0,4481   discard   eta=0,05 (revisitada)

Melhoria: 4,1% em relação ao baseline. Quatro de seis movimentos aceitos. Este é o regime típico de tuning de hiperparâmetros, no qual ganhos são menores e a taxa de descarte informa sobre a geometria local. Os dois descartes envolvem reduções agressivas de eta, sugerindo que o crítico aprendeu que a superfície de perda era plana o suficiente para penalizar shrinking excessivo.

4.3 Escalarização multi-métrica

O problema combina performance de modelo, latência e contagem de parâmetros em um score escalar com pesos predefinidos. Três iterações:

Iter   Score    Status    Movimento
----   ------   -------   --------------------------------------------------
   0   0,6532   keep      baseline (max_depth=3)
   1   0,7061   discard   max_depth=2 (menor, mais rápido, predição pior)
   2   0,6159   keep      max_depth=4

Melhoria: 5,7% em relação ao baseline. Um de três movimentos aceitos, mas o caso é o mais valioso pedagogicamente. A iteração 1 retornou score bruto mais alto em tamanho e latência ao custo da performance preditiva. A escalarização corretamente penalizou o movimento, e o harness o descartou. Sem guarda multi-métrica, o loop teria felizmente aceitado um modelo menor, mais rápido, pior. É exatamente para demonstrar isso que o terceiro estudo de caso existe.

5. Quando o padrão se aplica

autoresearch é um loop, não um modelo. Aplica-se onde quatro condições se mantêm:

  1. Existe uma métrica escalar única que o runner pode emitir no stdout. Trade-offs multi-objetivo devem ser escalarizados antes de entrarem no loop, como na seção 4.3.
  2. Existe um orçamento de tempo fixo por iteração. O orçamento torna runs comparáveis e força o crítico a propor mudanças que cabem nele.
  3. Existe um único arquivo mutável. A proposta estruturada do crítico tem como alvo aquele arquivo. Outros arquivos (dados, avaliação, contrato) são read-only.
  4. Existe uma branch git dedicada. O estado vive em commits; a convergência vem de reverter commits ruins e avançar commits bons.

Domínios que satisfazem essas condições em produção: roteamento e scheduling sob restrições com janela temporal; calibração de threshold para classificadores em pipelines de produção; configuração de campanha ou pricing com simulação delimitada; tuning de modelo e pipeline onde cada candidato leva minutos em vez de horas.

Domínios que não satisfazem: qualquer coisa que exija julgamento humano na métrica (qualidade subjetiva, percepção de justiça sem operacionalização); qualquer coisa com efeitos colaterais fora do arquivo mutável (escritas irreversíveis em estado compartilhado); qualquer coisa em que uma única iteração seja indeterminada no tempo.

6. Por que local-first

O crítico roda em Ollama por default. A escolha é deliberada.

Custo é o primeiro eixo. Um loop que roda centenas de iterações em endpoint hospedado acumula dinheiro real. Um loop que roda em modelo Gemma local em laptop custa zero por chamada uma vez baixado o modelo. Custo deixa de ser restrição de design e remove uma categoria de otimizações prematuras.

Privacidade é o segundo eixo. Código sob análise, lógica de avaliação e propostas intermediárias nunca saem da máquina. Para organizações com restrições regulatórias ou contratuais sobre saída de dados (jurídico, saúde, contratos governamentais, auditoria interna), isso pesa mais que performance de benchmark. Um loop com crítico local é um loop que essas organizações conseguem rodar de fato.

Replicabilidade é o terceiro eixo. Qualquer leitor com Ollama, Python e git pode rerodar os três exemplos, ver curvas de convergência comparáveis e inspecionar o mesmo audit log do qual este artigo foi construído. O depósito Zenodo contém os diretórios sample_run completos. Não há estado oculto.

Velocidade é o quarto eixo. Sem throttling de quota, sem jitter de API. O gargalo é hardware local, que é previsível e tunável.

O trade-off é teto de capacidade. Um modelo de fronteira hospedado propõe movimentos melhores em problemas duros do que um modelo local pequeno. A resposta certa é "use o crítico local para o loop e traga um modelo mais forte quando o local empacar", o que é direto de fazer com a configuração de endpoint OpenAI-compatível.

7. Dirigindo o loop com agentes de codificação

O pacote foi desenhado para ser agent-agnóstico: qualquer agente de codificação capaz de clonar repositório, instalar dependências Python e editar um arquivo mutável único pode dirigir o loop. Três agentes populares validados para isto:

  • Claude Code (Anthropic): aponte para a URL do repositório e ele clona, instala, faz scaffolding de uma run via autoresearch init e itera.
  • Codex (OpenAI Codex CLI): mesmo fluxo; o agente lê o README, roda o wizard de pré-checagem e entra no loop.
  • OpenCode: agente CLI open-source; mesmo caminho de entrada via URL.

A interação é mínima. Diga a qualquer um destes agentes:

Use o repositório github.com/pcbrom/autoresearch para rodar o exemplo TSP heurístico até convergência.

O agente cuida de instalação, pull do modelo, scaffolding do projeto e o loop iterativo. O audit log persiste no diretório do projeto independente de qual agente rodou; pode-se entregar entre agentes no meio de uma run.

Esse desacoplamento importa: autoresearch é o harness, o crítico LLM é uma parte móvel, e o agente orquestrador é outra. Qualquer das peças é substituível.

8. Genealogia: de karpathy/autoresearch a um pacote generalizado

O padrão tem origem no repositório autoresearch de Andrej Karpathy. Aquela base de código amarrava o harness a um único experimento de pretraining de LLM e era pensada para ser clonada, modificada e rodada nessa única tarefa.

O autoresearch v1.0 extrai o padrão. A superfície mutável agora é um solution.py plugável, definido por problema; o contrato agora é um problem.yaml com métrica, runner e orçamento declarados; o runner agora é uma CLI genérica que consome o contrato; o crítico está desacoplado de qualquer endpoint particular via cliente OpenAI-compatível; e o audit log foi consolidado como artefato navegável em vez de scaffolding por experimento.

O crédito é explícito. O campo related_identifiers no Zenodo declara isDerivedFrom: github.com/karpathy/autoresearch, o README declara a genealogia, e a licença é MIT, alinhada com o upstream.

9. Referências

BROM, P. C.. autoresearch v1.0. Zenodo, 2026. DOI 10.5281/zenodo.19772195.

KARPATHY, A.. autoresearch. Repositório GitHub. Disponível em: github.com/karpathy/autoresearch.

Locaweb (2026). 22% de crescimento em buscas no Google sobre agentes de IA no Brasil. Reportado em IstoÉ Dinheiro, 23 de abril de 2026.


Código: github.com/pcbrom/autoresearch
Licença: MIT
DOI conceito (versão mais recente): 10.5281/zenodo.19772194

Carregando publicação patrocinada...