Como depurar código com IA: um fluxo prático

Depure código com IA do jeito confiável: reproduza primeiro, passe ao agente o teste que falha e os logs, use git bisect, ache a causa raiz e trave a correção.

Solviera Teknoloji 10 min de leitura

Para depurar código com IA, dê ao agente um jeito de reproduzir o bug, o erro completo e os logs, e uma regra clara: achar a causa raiz antes de mudar qualquer coisa. Um agente de código como o Claude Code ou o Codex consegue rodar seus testes, ler stack traces, fazer bisect no histórico do git e adicionar logs, o que faz dele um ótimo parceiro de depuração. Ele também falha de jeitos previsíveis: chuta quando não consegue rodar o caso que falha e “corrige” sintomas capturando erros ou afrouxando testes.

Este guia é um fluxo que aproveita o primeiro ponto e protege contra o segundo: reproduzir, entregar as evidências, estreitar a busca, explicar, corrigir, travar com um teste e saber a hora de parar.

Por que os agentes erram na depuração

A maioria das correções ruins de IA vem dos mesmos poucos lugares:

  • Sem reprodução. O agente lê o código, forma uma teoria e aplica um patch. Nada prova que a teoria estava certa.
  • Evidência parcial. Você cola a última linha do erro. O frame útil, três níveis abaixo na pilha, nunca chega ao modelo.
  • Corrigir o sintoma. Uma checagem de null, um try/catch ou um retry faz o erro sumir enquanto o estado ruim que o causou continua lá.
  • Mudar a regra do jogo. O teste falha, então o agente edita o teste.
  • Sessões longas e poluídas. Depois de cinco tentativas falhas, a conversa está cheia de teorias erradas, e o modelo continua construindo em cima delas.

Cada passo abaixo mira em um desses pontos.

Passo 1: reproduza o bug primeiro

Antes de o agente tocar no código, ele precisa de um comando que mostre o bug. Pode ser um teste que falha, uma chamada curl, um script ou uma página no navegador. O importante é que qualquer pessoa, incluindo o agente, consiga rodar e ver a falha.

Se você já tem um, coloque no topo do prompt:

This fails:

  pnpm vitest run src/billing/invoice.test.ts -t "applies discount once"

Expected total 90, got 81. Don't change any code yet.
Run the test, confirm you see the same failure, and tell me what you see.

Se você não tem uma reprodução, faça disso a primeira tarefa:

Users report that saving a draft twice creates two drafts.
Write a failing test that reproduces this. Do not fix anything.
Stop when the test fails for the right reason.

“Pelo motivo certo” importa. Um teste que falha por causa de um erro de digitação no próprio teste não prova nada. Peça ao agente para mostrar a saída da falha e explicar por que ela bate com o relato do bug. Para bugs intermitentes, faça-o rodar a reprodução em loop (por exemplo, 50 vezes) e informar com que frequência ela falha, para você saber depois se uma correção realmente ajudou.

Passo 2: dê ao agente todas as evidências

Agentes são bons em ler saídas longas e cheias de ruído. Não corte para eles. Passe:

  • o stack trace completo, não só a mensagem;
  • o comando exato e a saída inteira;
  • os logs relevantes em torno do momento da falha;
  • o que mudou recentemente: uma atualização de dependência, um deploy, uma branch que entrou;
  • detalhes do ambiente se puderem importar: sistema operacional, versão do runtime, feature flags.

Você não precisa colar tudo no chat. Salve em um arquivo e aponte o agente para ele, ou mande direto por pipe. Com o modo print do Claude Code:

pnpm test 2>&1 | tail -n 200 > /tmp/test-output.txt
cat /tmp/test-output.txt | claude -p "Explain the root cause of this failure. Don't edit files."

Dentro de uma sessão interativa, ! roda um comando de shell e coloca a saída na conversa, tanto no Claude Code quanto no Codex, por exemplo !pnpm test src/billing. Para logs enormes, peça ao agente para fazer grep pelo ID da requisição ou pelo código de erro em vez de ler o arquivo inteiro; isso economiza muito da janela de contexto.

Passo 3: estreite a busca com git bisect

Quando algo funcionava e agora não funciona, você não precisa de uma teoria. O git bisect acha o primeiro commit ruim por busca binária, e pode rodar de forma totalmente automática, o que faz dele um trabalho perfeito para um agente.

Primeiro, escreva um script pequeno que sai com 0 quando o código está bom e diferente de zero quando está ruim:

#!/bin/sh
# check.sh
pnpm install --frozen-lockfile >/dev/null 2>&1 || exit 125
pnpm vitest run src/billing/invoice.test.ts -t "applies discount once"

Depois deixe o git fazer a caminhada:

git bisect start
git bisect bad HEAD
git bisect good v2.3.0
git bisect run ./check.sh
git bisect reset

Os códigos de saída são o contrato, como a documentação oficial do git bisect define: 0 significa bom, qualquer código de 1 a 127 exceto 125 significa ruim, 125 significa “não dá para testar este commit, pule”, e qualquer valor maior aborta o bisect. É por isso que o passo de instalação acima sai com 125: um commit que nem instala deve ser pulado, não contado como ruim.

Um prompt que entrega tudo isso a um agente:

The invoice discount test passes on tag v2.3.0 and fails on main.
Write a check script for git bisect run (exit 125 if the commit
can't be built), run the bisect, then git bisect reset.
Report the first bad commit and explain which line in its diff
causes the failure. Don't fix anything yet.

Garanta antes que a árvore de trabalho está limpa, ou faça isso em um git worktree separado, para os checkouts do bisect não brigarem com o seu trabalho. Se o arquivo de teste não existia nos commits antigos, copie-o para um caminho fora do repositório e faça o script rodar essa cópia.

Passo 4: adicione logs, depois remova

Quando o stack trace não explica o estado que levou ao erro, o agente precisa ver os valores em tempo de execução. Peça logs direcionados e temporários:

Add temporary logs that print the cart items, the discount list and
the running total at each step of applyDiscounts(). Prefix every line
with [DEBUG-1234] so we can find and remove them later. Run the
failing test and show me the log lines.

O prefixo é o truque. Quando o bug estiver entendido, uma instrução faz a limpeza:

git grep -n "DEBUG-1234"

Agentes também lidam bem com debuggers quando eles podem ser controlados por script: node --inspect com um breakpoint é desajeitado para um agente de terminal, mas uma sessão rápida de python -m pdb, uma asserção extra ou um script avulso que chama a função com a entrada que falha costuma chegar à mesma resposta mais rápido.

Passo 5: causa raiz antes da correção

Esta é a regra mais importante. Peça ao agente para explicar o bug antes de escrever uma correção, e leia a explicação:

Before changing any code, explain the root cause:
1. What state is wrong, and where does it first become wrong?
2. Why does the code produce that state?
3. Why didn't existing tests catch it?
Then propose the smallest fix and wait for my OK.

Uma boa resposta aponta uma linha específica e uma condição específica (“o desconto é aplicado tanto em addItem quanto em checkout desde que o commit a1b2c3 moveu a chamada”). Uma resposta fraca é vaga (“pode haver um problema na forma como os descontos são tratados”) ou pula direto para um patch defensivo. Se vier a resposta fraca, o agente ainda não achou a causa; mande-o de volta ao Passo 3 ou 4.

O plan mode do Claude Code é útil aqui, porque o agente pode ler e rodar comandos somente leitura, mas não editar arquivos até você aprovar. Inicie com claude --permission-mode plan, ou aperte Shift+Tab para alternar até ele. Plan mode do Claude Code explica em detalhes. No Codex, o /plan tem um papel parecido.

Passo 6: corrija e trave com um teste de regressão

Agora deixe o agente corrigir, com restrições:

Apply the fix. Rules:
- Do not edit or skip existing tests.
- Do not catch and swallow the error.
- Add a regression test named after the bug that fails without
  the fix and passes with it. Prove both: revert the fix, run the
  test, restore the fix, run it again.
- Run the full test suite at the end.

A parte de “provar os dois” é o que torna o teste confiável. Um teste de regressão que já passaria antes da correção é enfeite. Para tirar testes úteis de um agente, veja como escrever testes unitários com IA.

Depois revise o diff você mesmo, procurando as correções de sintoma de sempre:

Padrão no diffPor que é suspeito
Novo try/catch que registra e segue em frenteO erro fica escondido, o estado ruim continua
Optional chaining ou ?? default adicionado no ponto da falhaTrata dados ausentes como normais em vez de perguntar por que estão ausentes
Retries ou timeouts maioresMuitas vezes mascara uma race condition
Tipo ampliado para any ou unknownCala o compilador em vez de corrigir o tipo
Expectativa do teste alteradaA regra do jogo mudou

Às vezes, um desses é a correção certa. A pergunta é se o agente explicou o porquê.

Bugs de navegador: dê um navegador ao agente

Bugs de interface são difíceis de descrever em texto: um botão que não faz nada, um layout que quebra depois de um clique, um erro que só aparece no console. Com o Playwright MCP, o agente pode abrir a página e olhar por conta própria. Adicione ao Claude Code:

claude mcp add playwright npx @playwright/mcp@latest

ou ao Codex em ~/.codex/config.toml:

[mcp_servers.playwright]
command = "npx"
args = ["@playwright/mcp@latest"]

Ferramentas como browser_navigate, browser_click, browser_snapshot, browser_console_messages e browser_network_requests permitem ao agente reproduzir o bug passo a passo, ler os erros do console e ver qual chamada de API falhou. Um prompt de depuração:

Start the dev server. Open http://localhost:5173/settings, change the
display name and click Save. Report console errors and the network
request for the save, with status and response body. Don't fix yet.

Quando a causa estiver clara, peça ao agente para transformar os passos em um teste do Playwright, para o bug continuar corrigido. Testes de navegador com agentes de IA aprofunda a configuração.

Bugs que só aparecem no CI

Quando os testes passam localmente mas falham no CI, a diferença normalmente é de ambiente: fuso horário, locale, paralelismo, variáveis de ambiente faltando, outra versão do Node ou do Python, ou a ordem dos testes. Dê ao agente o log do CI e o arquivo do workflow, e peça para ele listar as diferenças entre o CI e a sua máquina antes de chutar. Rodar a suíte em ordem aleatória ou com o fuso horário do CI (TZ=UTC pnpm test) muitas vezes reproduz a falha localmente. Se falhas de CI são uma tarefa recorrente, corrigir falhas de CI automaticamente com IA mostra como automatizar o ciclo.

Quando parar o agente

Um agente vai continuar tentando muito depois da hora de parar. Interrompa quando:

  • Duas ou três correções falharam. Cada nova tentativa é construída sobre a mesma teoria errada.
  • O diff se espalha. Começou em invoice.ts e agora está editando configuração, módulos sem relação ou lock files.
  • Ele mexe nos testes. Mudar uma asserção para bater com a saída errada nunca é correção de bug.
  • Ele não consegue reproduzir o bug, mas corrige mesmo assim.
  • A explicação muda de um turno para o outro sem evidência nova.

O que fazer em vez disso:

  1. Pare o turno (Esc no Claude Code e no Codex).
  2. Desfaça as mudanças. Faça commit antes de começar a depurar, para que git restore . ou git stash levem você de volta; desfazer mudanças do Claude Code cobre as opções.
  3. Anote o que você aprendeu: quais teorias estavam erradas e por quê.
  4. Comece uma sessão nova com a reprodução, os fatos e as teorias descartadas. Um contexto limpo com três fatos bons vale mais do que um longo com dez chutes ruins.

Às vezes, o melhor caminho é fazer uma pergunta mais estreita: “cart.items já está errado quando checkout() é chamado?” é mais fácil de responder do que “corrija o bug do checkout”.

Depurando com o AgentVera

O AgentVera é um app desktop para macOS, Windows e Linux que roda Claude Code, Codex, Gemini CLI e outros agentes de CLI lado a lado em terminais de verdade. Várias ferramentas dele se encaixam no fluxo acima:

  • Send to agent (enviar para o agente): selecione um erro no dock do terminal, no console do navegador ou nos logs do Docker e envie para um agente com ⌘⇧L, ou clique no selo Fix em um erro capturado. Logs longos são limitados a 12.000 caracteres e mantêm o final, onde o stack trace normalmente está.
  • Navegador do agente: um Chrome com perfil separado que os agentes controlam pelo Playwright MCP, com as abas transmitidas ao vivo para você ver o agente reproduzir o bug.
  • Checkpoints: cada turno vira um snapshot em uma ref oculta do git, então você vê o que uma tentativa falha mudou e desfaz aquele turno sem mexer nas suas branches ou no stash.
  • Duas teorias em paralelo: inicie dois agentes em worktrees separados pelo painel Git, dê a cada um uma hipótese diferente e fique com a correção que se sustentar.
  • Verify: no Pro e no Team, critérios como “o teste de regressão falha sem a correção e passa com ela” são conferidos por um verificador separado, somente leitura, quando o turno do agente termina.

Com o bug corrigido, anote o que você aprendeu onde a próxima pessoa vai encontrar; escrever documentação com IA cobre esse lado.

Conclusão

Depurar com um agente de IA funciona quando você o trata como depurar com um colega afiado: comece de uma reprodução, compartilhe todas as evidências, estreite a busca com git bisect, adicione logs para ver valores reais e insista na causa raiz antes da correção. Termine todo bug com um teste de regressão que você viu falhar e passar. E quando o agente começar a chutar, pare, desfaça e recomece com o que aprendeu.

Perguntas frequentes

A IA consegue mesmo depurar código ou só chuta?

Um agente de código consegue depurar de verdade quando pode rodar o código: reproduzir o bug, ler a saída, adicionar logs e testar uma hipótese. Sem um jeito de rodar o caso que falha, ele só consegue chutar a partir da leitura, e é daí que vem a maioria das correções erradas.

O que devo passar ao agente quando reporto um bug?

O comando ou teste exato que falha, o erro completo com o stack trace, o que você esperava em vez disso e qualquer coisa que mudou recentemente. Uma reprodução de uma linha vale mais do que uma descrição longa do sintoma.

Um agente consegue rodar o git bisect sozinho?

Sim. Dê a ele um commit bom, um ruim e um script que sai com 0 quando o código funciona e 1 quando não funciona. O git bisect run então faz checkout dos commits e roda o script até achar o primeiro ruim. O código de saída 125 diz ao git para pular um commit que não pode ser testado.

Como evito que um agente de IA faça uma correção que só esconde o bug?

Peça a causa raiz em palavras simples antes de qualquer mudança no código, proíba editar ou pular testes existentes e exija um teste de regressão que falhe sem a correção. Revise o diff procurando blocos try/catch, retries e tipos ampliados que silenciam o erro em vez de remover a causa.

Quando devo parar o agente e depurar eu mesmo?

Quando ele já tentou duas ou três correções que não funcionaram, quando começa a mudar arquivos sem relação ou quando propõe enfraquecer um teste ou uma asserção. Pare, desfaça as mudanças e recomece com uma reprodução mais precisa ou uma pergunta menor.

Reúna seus agentes em uma só mesa.

Baixe o AgentVera de graça; as CLIs que você já instalou estão prontas para usar.

Mais artigos