Agente de código precisa de contrato de trabalho, não de mais prompt
O problema de usar agente de código raramente começa no modelo.
Começa naquele pedido meio inocente:
Corrige esse bug aqui.
Aí o agente entende. Até entende demais.
Ele mexe em dois arquivos que você esperava, depois em mais três que pareciam relacionados, talvez rode um comando, talvez não rode, deixa um diff grande, explica com bastante confiança e joga para você a parte mais chata do trabalho: descobrir o que mudou, por que mudou, se podia ter mudado e como provar que terminou.
Nesse ponto, o problema não é prompt fraco. É falta de contrato.
Não contrato jurídico, claro. Estou falando de um combinado pequeno antes da tarefa: objetivo, escopo, permissão, evidência e critério de aceite.
Parece burocracia até o primeiro PR de agente virar uma revisão de meia hora.
O agente saiu do autocomplete
Por muito tempo, era fácil pensar em IA para dev como uma sugestão dentro do editor. Ela completava uma função, explicava um erro, escrevia um teste, sugeria um snippet.
Esse mundo ainda existe, mas a conversa mudou.
As ferramentas mais recentes estão empurrando o agente para dentro do fluxo inteiro: branch, sessão paralela, terminal, ambiente remoto, CI, browser, pull request, comentário de review, log de teste e custo por uso.
Isso é bem diferente de aceitar uma linha sugerida pelo autocomplete.
Quando um agente trabalha em uma branch própria, ele não está só "respondendo". Ele está tomando pequenas decisões operacionais. Quando roda dentro do GitHub Actions, ele não está só ajudando. Ele está recebendo permissão. Quando abre ou altera um PR, ele vira parte do handoff do time.
E permissão sem contrato vira aposta.
Prompt descreve intenção, mas não define autoridade
Um prompt bom ajuda. Ninguém precisa fingir que não.
Mas prompt sozinho costuma responder à pergunta errada. Ele diz o que você quer. Nem sempre diz o que o agente pode fazer.
Tem uma diferença enorme entre:
Corrija o bug do botão de checkout.
e:
Objetivo: corrigir o estado disabled do botão de checkout quando o carrinho está vazio.
Fora de escopo: não alterar layout, copy, API ou fluxo de pagamento.
Arquivos permitidos: componente do botão e teste relacionado.
Comando de verificação: npm test -- checkout.
Evidência esperada: explicar o caso coberto e listar o comando executado.
Handoff: diff pequeno, sem refactor oportunista.
O segundo bloco não é mais inteligente porque tem palavras mágicas. Ele é melhor porque tira liberdade onde liberdade atrapalha.
O agente ainda pode errar. Mas agora ele erra contra um limite visível.
O contrato mínimo cabe em oito linhas
Para tarefa comum de desenvolvimento, eu gosto de pensar em um contrato assim:
- objetivo da mudança;
- fora de escopo;
- arquivos, diretórios ou áreas permitidas;
- comandos autorizados;
- limite de tempo, custo ou turnos;
- critério de aceite;
- evidência obrigatória;
- formato do handoff.
Só isso já muda bastante coisa.
Não precisa transformar cada issue em documento de consultoria. Time pequeno não aguenta esse peso, e nem deveria. O ponto é deixar rastro suficiente para a revisão não depender de adivinhação.
Se você pede para o agente corrigir um teste quebrado, diga qual teste. Se ele pode atualizar snapshot, diga quando. Se não pode mexer em contrato público, escreva isso. Se a validação mínima é npm test, pnpm lint ou abrir uma tela no browser, coloque no contrato.
O que parece óbvio para você nem sempre aparece para o agente. E, pior, nem sempre aparece para quem vai revisar depois.
Exemplo realista: bug pequeno
Imagine um bug no checkout: o botão fica habilitado mesmo quando o carrinho está vazio.
Pedido ruim:
Arruma o checkout.
Pedido melhor:
Objetivo: quando o carrinho estiver vazio, o botão de checkout deve ficar disabled.
Fora de escopo: não alterar layout, preços, cupom, API ou textos.
Pode tocar: CheckoutButton.tsx e CheckoutButton.test.tsx.
Verificação: npm test -- CheckoutButton.
Aceite: teste cobre carrinho vazio e carrinho com item.
Handoff: explicar a causa e mostrar o comando rodado.
Isso não deixa a tarefa mais lenta. Na prática, deixa mais rápida.
Você evita o clássico "aproveitei e refatorei". Evita mudança bonita que não era necessária. Evita diff grande demais para um bug pequeno.
E se o agente descobrir que precisa tocar outro arquivo? Ótimo. Ele deve parar e dizer: "para resolver de verdade, preciso alterar tal contrato". Essa interrupção é muito melhor do que descobrir no review que a tarefa cresceu sozinha.
Exemplo mais sensível: agente no CI
Agora muda o cenário.
Em vez de um agente rodando no seu terminal, imagine uma Action que responde a comentários em issues ou PRs.
Aqui o contrato precisa ser mais explícito, porque o risco mudou. Não estamos falando só de gerar código. Estamos falando de evento do GitHub, permissão de token, acesso a secrets, comandos de shell, branch protegida e conteúdo não confiável vindo de comentário.
Um contrato mínimo para CI poderia responder:
- quais eventos disparam o agente?
- quais usuários podem acionar?
- quais permissões o token recebe?
- o agente pode rodar shell livremente ou só comandos permitidos?
- secrets ficam inacessíveis?
- qual é o limite de turnos?
- ele pode fazer push ou apenas comentar um patch?
- quais logs ou checks precisa deixar no PR?
Repara que a parte difícil não é o YAML. YAML sempre parece fácil até alguém dar permissão demais para a coisa errada.
O desenho de autoridade é que importa.
Exemplo de PR: uma sessão por mudança revisável
Agente remoto combina muito bem com trabalho paralelo. Você abre uma sessão, descreve a tarefa, espera um branch ou PR, revisa depois.
Mas isso também cria uma tentação perigosa: pedir um pacote grande demais.
Melhora o onboarding, corrige os bugs de mobile, atualiza os testes e deixa a página mais moderna.
Esse tipo de pedido é praticamente um convite para um PR difícil de revisar.
Melhor quebrar:
Sessão 1: corrigir bug de layout mobile no passo 2 do onboarding.
Sessão 2: adicionar teste para o estado vazio.
Sessão 3: propor uma melhoria visual sem aplicar automaticamente.
Cada sessão tem critério próprio. Cada PR tem uma razão clara para existir. O humano revisa menos coisa por vez e consegue dizer "sim" ou "não" sem entrar em modo arqueologia.
Agente bom não elimina a necessidade de PR pequeno. Ele aumenta a importância disso.
O custo também faz parte do contrato
Uma parte que muita gente evita falar: agente custa.
Custa dinheiro, custa tempo de CI, custa atenção no review e pode custar confiança quando altera coisa demais.
Então limite também é requisito técnico.
Para tarefa pequena, talvez o contrato diga: "pare depois de duas tentativas se o teste continuar falhando". Para migração maior: "não processe mais de um módulo por PR". Para investigação: "traga diagnóstico antes de alterar código". Para billing sensível: "não rode comandos caros sem confirmar".
Isso não é microgerenciar a IA. É tratar recurso compartilhado como recurso compartilhado.
Dev nenhum acharia normal um job de CI rodar sem timeout. Por que agente deveria trabalhar sem limite?
Contrato demais também atrapalha
Tem um outro lado aqui.
Se você colocar contrato pesado em toda exploração, mata o fluxo. Spike existe justamente para procurar caminho. Em protótipo, você talvez queira deixar o agente tentar, errar, comparar opções e jogar fora metade do resultado.
Tudo bem.
A regra não é "documente tudo". A regra é ajustar o contrato ao risco.
Para uma pergunta no chat, quase nada.
Para um bug pequeno, escopo e teste.
Para PR em produto, critério de aceite e handoff.
Para CI, permissões e logs.
Para segurança, billing, dados sensíveis ou migração grande, contrato bem explícito.
O erro é usar o mesmo nível de liberdade para todos esses casos.
Um template que eu realmente usaria
Se você quiser algo prático para colar em issue, comentário ou prompt de agente, eu usaria este formato:
Tarefa:
Objetivo:
Fora de escopo:
Pode alterar:
Não pode alterar:
Comandos permitidos:
Critério de aceite:
Evidência obrigatória:
Se bloquear:
O campo "Se bloquear" é mais importante do que parece.
Ele evita aquele comportamento irritante em que o agente inventa um caminho só para continuar andando. Melhor dizer antes: se faltar contexto, se o teste não rodar, se a mudança exigir outro arquivo, se a API estiver ambígua, pare e explique.
Um agente que para no ponto certo economiza mais tempo do que um agente que sempre tenta parecer produtivo.
O melhor dev de agente não é o que escreve o prompt perfeito
A gente ainda fala muito sobre prompt como se existisse uma frase secreta que destrava produtividade.
Eu acho essa discussão cada vez menos interessante.
Quando o agente entra em branch, PR, terminal e CI, o ganho vem menos de pedir bonito e mais de transformar trabalho vago em unidade revisável.
O dev que vai tirar mais valor disso não é quem escreve o prompt mais longo. É quem sabe dizer:
- qual é a tarefa;
- onde ela termina;
- onde ela não deve encostar;
- como provar que funcionou;
- o que fazer quando não der.
Isso é chão de fábrica de software. Nada glamouroso. Mas é exatamente onde agente de código deixa de ser demo e começa a virar ferramenta confiável.
Antes de pedir "corrige isso", escreva o contrato.
Pode ser pequeno. Deve ser claro.
O resto fica muito mais fácil de revisar.