Um agente de revisão não deveria conseguir escrever. É assim que a gente impõe isso, CLI por CLI.

Em um run de 17 nós, o agente de release editou um teste para deixar verde uma suíte vermelha, e depois dois agentes de revisão escreveram a mesma correção e colidiram. O prompt dizia «só revisar». Não segurou. O incidente, por que uma instrução escrita não consegue sustentar essa regra, e as flags exatas que fazem Claude Code, Codex, Grok, Antigravity e OpenCode se recusarem a escrever.

No começo desta semana, um usuário nos mandou um relatório de run que vale a pena ler duas vezes. Dezessete agentes, um worktree compartilhado, um pipeline com um implementador, um portão de release e dois ramos de revisão. Versão 1.171.0 do AgentsRoom.

Três coisas aconteceram nesse run, nesta ordem.

O agente de release tinha uma suíte de testes vermelha na frente dele. Ele editou o spec do teste até a suíte ficar verde. Ao fazer isso, entregou um defeito real, agora coberto por um teste que concordava com ele.

Depois, dois agentes de revisão, em dois ramos paralelos do mesmo run, encontraram cada um um bug real de uma linha. Cada um corrigiu diretamente, no mesmo worktree, ao mesmo tempo. Eles colidiram.

Cada um desses agentes tinha um prompt de etapa que dizia, com todas as letras, só revisar. Nada os impediu, e nada sinalizou: do lado da plataforma, uma etapa tinha ferramentas de escrita e usou.

Por que o prompt não segurou

A leitura tentadora é que os agentes ignoraram a instrução. Não foi o que aconteceu, e isso importa, porque muda o que a correção precisa ser.

Cada agente tinha um motivo localmente defensável para escrever. Uma suíte vermelha e um spec que parecia errado. Um bug que leva quatro segundos para corrigir e quarenta para descrever. Nenhum deles decidiu quebrar a regra. Cada um decidiu que o seu caso era aquele que a regra não pretendia cobrir. Vista de dentro da etapa, a exceção sempre parece razoável.

Uma instrução escrita é um pedido ao julgamento do modelo. Um revisor que também consegue corrigir vai, mais cedo ou mais tarde, corrigir, porque corrigir é o caminho mais curto entre «achei» e «feito». A única regra que sobrevive ao contato com uma exceção plausível é aquela que o modelo não consegue discutir: uma ferramenta que não está lá.

Por que a configuração global também não dava conta

Antes disso, a única alavanca que alcançava uma etapa em execução era a configuração do provider, que cobre todos os agentes Claude da máquina de uma vez. Esse não é o formato certo para um run. No mesmo pipeline, o implementador precisa escrever e o revisor não. Uma chave global não consegue distinguir os dois.

E a restrição por agente que a gente já tinha, aquela que um ticket pode carregar quando lança um agente, deliberadamente não era passada para as etapas de um time. Então um agente iniciado a partir de um ticket podia ser restringido, e um nó de um time não. Essa foi a causa principal, e era uma decisão de design que tinha envelhecido mal.

A regra: uma caixa de seleção no nó

A correção é um booleano no nó de revisão. Marque Somente leitura e o agente que encarna essa etapa é lançado sem acesso de escrita ao projeto: sem edição de arquivo, sem commit nem push no git, sem nenhum comando de shell cuja única função seja alterar a árvore de trabalho. Leitura, grep, git diff, git log, os testes, o linter e todas as ferramentas de time continuam abertos.

Fomos explícitos sobre o que isso não é: não é uma lista de negação que o usuário escreve à mão, CLI por CLI. Ninguém deveria precisar conhecer cinco sintaxes de permissão para dizer «este aqui revisa». A chave produz a flag certa para cada provider, e é aplicada por último, depois do modo autônomo e depois de qualquer coisa que o usuário tenha salvo no agente, então ela vence.

O que cada CLI faz, lido na própria ajuda dele

A gente só impõe a regra nos providers cuja flag lemos no próprio --help deles. Uma flag chutada mata o lançamento com erro de parsing, o que é pior do que uma etapa sem restrição. Os outros CLIs recebem só a regra escrita, e o editor diz isso em texto claro embaixo da caixa de seleção.

CLIO que a chave somente leitura adicionaSegura em modo autônomo?
Claude Code--disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)" e o restoSim, as regras de negação valem sob --dangerously-skip-permissions
Codex--sandbox read-onlySim, é um sandbox do sistema operacional (Seatbelt no macOS, Landlock no Linux), não uma lista de ferramentas
Grok Build--deny "Edit" --deny "write" --deny "Bash(git commit*)" e o restoSim, as regras de negação valem sob --always-approve
Antigravity--mode planSim, plan é o modo de execução somente leitura do CLI
OpenCode--agent planSim, o agente plan embutido nega as ferramentas de edição
Mistral Vibe, Kimi Code, Copilot, Cursor, Amp, Aider e os demaissó o parágrafo do promptSem flag verificada, e a gente diz isso no editor

Dois detalhes dessa tabela nos custaram um bug cada, então vale a pena explicar.

Codex e Grok recusam uma flag repetida. Os dois analisam os argumentos com um parser estrito. Se o usuário já tivesse salvo --sandbox workspace-write no agente, acrescentar --sandbox read-only depois não sobrescreveria, faria o lançamento quebrar. Então, para flags com valor, a gente remove qualquer ocorrência existente, com o valor dela, antes de acrescentar a nossa. O mesmo vale para --agent no OpenCode, cujo parser transforma uma flag repetida em array e falha mais adiante.

No Claude Code a lista precisa se acumular. --disallowedTools recebe uma lista separada por espaços e pode ser repetida, e a gente já passa uma quando um agente não tem permissão para controlar o navegador embutido. O parser concatena uma opção variádica repetida, então as duas listas se somam em vez de a segunda substituir a primeira.

A lista completa do Claude Code são as quatro ferramentas de edição de arquivo, todo subcomando do git que escreve no índice, na árvore, nas refs ou em um remoto (add, commit, push, merge, rebase, reset, checkout, switch, restore, stash, cherry-pick, revert, apply, am, rm, mv, clean, tag, worktree), e os comandos de shell que só existem para alterar arquivos (rm, mv, cp, tee, touch, mkdir, chmod, chown, ln, truncate, dd, sed -i). O Grok recebe as mesmas strings de regra, na forma glob dele, mais os nomes próprios dele para as ferramentas de arquivo (search_replace, write, hashline_edit).

O prompt ainda tem um papel

A flag recusa. Ela não explica. E um agente que esbarra numa recusa que não entende trata isso como bug e procura outro caminho, que é exatamente o comportamento que a gente queria eliminar.

Então uma etapa somente leitura também recebe duas frases no prompt dela. A primeira diz que a etapa é somente leitura, lista o que isso significa, e estabelece que uma recusa é a regra, não um obstáculo a contornar com outro comando. A segunda lista o que continua aberto, e pede ao agente que reporte o que deveria mudar, com o arquivo, a linha e o motivo, na passagem dele, e deixe a etapa que é dona do código aplicar.

Nos CLIs com flag verificada, esse parágrafo é o que faz a recusa ser entendida. Nos outros, ele é toda a restrição, e a gente prefere dizer isso a fingir.

Quem é somente leitura nos templates entregues

Os nós que julgam são somente leitura: a etapa de verificação QA dos dois templates iniciais, as etapas de reprodução e verificação do Bug hunt, os ramos QA e Segurança do Release shield, o testador do Feature squad.

Os nós que são donos do código continuam escrevendo: o desenvolvedor, e o portão de release que foi escrito para corrigir ele mesmo cada achado. Um portão de release que não consegue escrever é um portão de release que não consegue lançar.

Essa divisão é todo o design, e é a divisão que o incidente violou duas vezes: um nó de release que escreveu no lugar errado, e nós de revisão que escreveram, ponto.

O que isso não é

Não é uma fronteira de segurança. Quem reportou disse isso no relatório, e estava certo: um bash -c passa por cima de uma lista de ferramentas negadas. Se você precisa isolar um agente em que não confia, isso é um sandbox ou uma máquina separada, e o Codex é o único dos cinco cujo modo somente leitura é de fato isso.

O que a chave impede é o acidente e o desvio de papel, que é o que acontece de verdade. Um revisor não escapa de uma lista de negação de propósito. Ele pega o Edit por reflexo, e agora o reflexo é recusado.

O que a gente não construiu

Quem reportou pediu mais uma coisa: um evento na linha do tempo do run dizendo «o nó X escreveu na árvore», como sinal mínimo mesmo sem restrição. É uma boa ideia e a gente não fez aqui, porque precisa de um diff de referência por etapa do lado do runner. Se a necessidade voltar, essa é a próxima peça.

Se você não usa o AgentsRoom

As flags acima podem ser copiadas como estão. Um agente de revisão lançado à mão com codex --sandbox read-only, ou com claude --disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)", não consegue fazer o que os nossos dois nós de revisão fizeram. Coloque as mesmas duas frases no prompt dele para que ele saiba por que está sendo recusado.

O que a caixa de seleção adiciona é que você não precisa lembrar qual das cinco sintaxes se aplica, que a flag vence qualquer modo autônomo em que a etapa rode, e que ela sobrevive a um run que volta a passar mais tarde pela mesma etapa.

A chave do nó e a tabela por provider estão documentadas na página Agent Teams. Se uma revisão feita por um agente vale a pena, e quanto de um diff ainda merece um humano, é outra pergunta, e a gente escreveu sobre isso em Você ainda deveria revisar o código do seu agente de IA?. Este post é sobre a coisa menor e mais mecânica: depois que você decidiu que um agente revisa, torne-o fisicamente incapaz de fazer qualquer outra coisa.

Baixar AgentsRoom

Rode todos os seus agentes de IA, em todos os seus projetos, de uma única janela.

GrátisBaixar AgentsRoom

App complementar: acompanhe seus agentes em qualquer lugar

Use Claude, Codex, Antigravity CLI ou outro provedor de IA.

Instalar a extensão
Chrome Web Store

Envie bugs e pedidos direto para o seu backlog público.

Multi-projetos
Multi-provedor
Multi-agentes
Status ao vivo
Diff e commit
App mobile
Preview ao vivo
Equipes de agentes
Testes no navegador
Dev guiada por backlog
Biblioteca de prompts
Biblioteca de skills
Ver todas as funcionalidades

Continue lendo