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/catchou 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 diff | Por que é suspeito |
|---|---|
Novo try/catch que registra e segue em frente | O erro fica escondido, o estado ruim continua |
Optional chaining ou ?? default adicionado no ponto da falha | Trata dados ausentes como normais em vez de perguntar por que estão ausentes |
| Retries ou timeouts maiores | Muitas vezes mascara uma race condition |
Tipo ampliado para any ou unknown | Cala o compilador em vez de corrigir o tipo |
| Expectativa do teste alterada | A 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.tse 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:
- Pare o turno (Esc no Claude Code e no Codex).
- Desfaça as mudanças. Faça commit antes de começar a depurar, para que
git restore .ougit stashlevem você de volta; desfazer mudanças do Claude Code cobre as opções. - Anote o que você aprendeu: quais teorias estavam erradas e por quê.
- 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.