Você acorda com cinco relatórios de bugs críticos em uma manhã de segunda-feira. Sua ferramenta de monitoramento de revisão fez o trabalho dela. Ela capturou cada relatório de crash, cada avaliação de uma estrela irritada, cada "o app trava quando eu clico em salvar". Você sabe exatamente o que está quebrado. O que você não sabe é onde procurar.
Essa foi a barreira que encontrei após construir meu primeiro pipeline. Ele monitorava avaliações de apps e logs de crash recebidos sem problemas, organizando cada feedback em categorias organizadas: bugs, crashes ou solicitações de recursos. O dashboard parecia saudável. O processo real de depuração, não.
Saber que um bug existe é apenas o começo de uma longa jornada. Eu ainda tinha que abrir a IDE, fazer grep nos módulos, cruzar stack traces com a codebase atual e reconstruir o caminho da falha na minha cabeça. Quando os tickets estão se acumulando e o café ainda está quente, essa arqueologia manual consome um tempo que você não tem. Eu precisava que o pipeline fizesse mais do que apenas sinalizar problemas. Eu precisava que ele os investigasse.
Então, reconstruí o sistema em torno de um único objetivo: pegar um relatório de bug bruto e retornar um diagnóstico validado. Não um parágrafo de reflexões de um LLM. Um achado estruturado que nomeia o arquivo, aponta a linha, estima o risco e sugere uma correção. Aqui está como tudo se uniu.
Por que a Estrutura Vence um Log de Chat
Construí o agente de investigação com PydanticAI. O motivo foi simples. Quando você pede a um modelo de linguagem para raciocinar sobre código, a saída padrão é um fluxo amigável de texto. Isso pode ajudar um leitor humano, mas é inútil para um script subsequente. Eu precisava de um contrato legível por máquina.
O agente retorna um modelo de dados validado com quatro campos específicos: a causa raiz, os arquivos afetados, as alterações propostas e uma avaliação de complexidade e risco. Se o modelo estiver com um campo faltando ou alucinar um caminho de arquivo, a validação falha e eu percebo imediatamente. Esse rigor mantém a integridade do pipeline.
Para realizar o verdadeiro trabalho de detetive, o agente recebe quatro ferramentas de apenas leitura e nada mais. Ele pode pesquisar código via grep, ler intervalos de linhas específicos de um arquivo, listar o conteúdo de diretórios e localizar símbolos como classes ou funções. "Apenas leitura" é a parte importante. Eu não queria um agente com acesso de escrita vagando pelo meu repositório às 2 da manhã. Primeiro entender, depois editar.
O Mapa do Repositório: Contexto Antes das Ferramentas
A primeira versão do agente era precisa, mas extremamente cara. Ele consumia tokens como um turista andando em círculos. O modelo chamava list-dir, depois grep, depois lia um arquivo, depois list-dir novamente, montando lentamente um modelo mental da estrutura do projeto, um token caro por vez.
A solução foi gerar um mapa de repositório compacto antes mesmo de o agente começar. Este mapa é uma visão geral destilada do repositório: arquivos principais, suas funções ou classes primárias e como os principais módulos se conectam. Pense nisso como entregar um GPS ao agente em vez de pedir que ele descubra as estradas por tentativa e erro.
Com esse mapa em sua janela de contexto, o agente não desperdiça chamadas tentando descobrir que src/utils/parser.ts existe. Ele já conhece o terreno. Ele vai direto para a crista onde a fumaça está subindo. Essa única mudança eliminou completamente a fase de errância.
O Funil de Ferramentas: Forçando uma Conclusão
Mesmo com um mapa, o agente podia hesitar. Ele encontrava um arquivo suspeito, depois duvidava de si mesmo, depois pesquisava novamente, depois lia outro arquivo, preso em um loop infinito de "só mais uma verificação". Eu precisava de uma maneira de forçar o ímpeto.
Implementei um funil de ferramentas de três fases que restringe o que o agente pode fazer conforme ele progride.
A fase um é exploração. O agente tem acesso total às quatro ferramentas. Ele pode pesquisar, navegar e ler o que for necessário para replicar o bug em seu raciocínio.
A fase dois é o mergulho profundo. Assim que o agente identifica as prováveis linhas de falha, ele perde as ferramentas de descoberta. Ele só pode ler arquivos. Nada de grep, nada de listagem de diretórios. Nesta etapa, ele deve estudar o código que já encontrou e construir sua cadeia de evidências.
A fase três é a saída. Todas as ferramentas são bloqueadas. O agente não pode mais consultar a codebase. Ele precisa se sentar e escrever o relatório. Isso evita a espiral interminável do "deixe-me verificar só mais uma coisa".
Esse funil reduziu o número médio de chamadas de ferramentas de mais de quarenta por análise para aproximadamente dez. O agente tornou-se mais rápido, mais barato e, paradoxalmente, mais confiante, porque teve que se comprometer com uma conclusão.
Mantendo o Backend Substituível
Eu não queria vincular o sistema de forma rígida a um único provedor de modelo. Uso diferentes motores dependendo da tarefa. Às vezes Claude Code, às vezes Grok Build, às vezes o que estiver mais barato no momento. Para manter a lógica central independente de provedor, dividi o trabalho em dois estágios.
O primeiro estágio é a exploração. O agente de codificação, que pode ser qualquer modelo capaz, lê o mapa do repositório, utiliza as ferramentas e produz um relatório markdown bruto. Esta é a parte de raciocínio custosa.
O segundo estágio é a estruturação. Um LLM barato e rápido pega esse markdown e o reformata no modelo Pydantic estrito. Este estágio quase não exige raciocínio. É apenas extração e formatação, portanto, roda em hardware leve.
Como a fronteira é clara, posso trocar o backend sem tocar na lógica de validação. O relatório markdown atua como um adaptador universal entre o cérebro exploratório e a saída estruturada que eu realmente utilizo.
O que realmente funcionou
Essa configuração mudou a forma como lido com as issues recebidas. A camada de classificação ainda separa bugs de solicitações de funcionalidades, mas agora a camada de análise assume imediatamente depois. No momento em que abro meu editor, já tenho um caminho de arquivo, um intervalo de linhas e uma mudança proposta me esperando. Eu ainda reviso tudo manualmente. Isso é assistência, não piloto automático. Mas a coleta de contexto que costumava
