Een review-agent hoort niet te kunnen schrijven. Zo dwingen we het af, CLI voor CLI.

In een run van 17 nodes paste de release-agent een test aan om een rode suite groen te krijgen, en daarna schreven twee review-agents dezelfde fix en botsten ze. De prompt zei: alleen reviewen. Dat hield geen stand. Het incident, waarom een geschreven instructie die regel niet kan dragen, en de exacte flags waarmee Claude Code, Codex, Grok, Antigravity en OpenCode weigeren te schrijven.

Eerder deze week stuurde een gebruiker ons een run-rapport dat het waard is om twee keer te lezen. Zeventien agents, één gedeelde worktree, een pipeline met een implementeerder, een release gate en twee review-takken. Versie 1.171.0 van AgentsRoom.

Er gebeurden drie dingen in die run, in deze volgorde.

De release-agent had een rode testsuite voor zich. Hij bewerkte de testspec tot de suite groen was. Daarmee leverde hij een echt defect op, nu gedekt door een test die het met hem eens was.

Daarna vonden twee review-agents, op twee parallelle takken van dezelfde run, elk een echte bug van één regel. Elk fixte hem direct, in dezelfde worktree, op hetzelfde moment. Ze botsten.

Elk van die agents had een stap-prompt die in gewone woorden zei: alleen reviewen. Niets hield ze tegen, en niets signaleerde het: vanuit het platform gezien had een stap schrijftools en gebruikte hij ze.

Waarom de prompt geen stand hield

De verleidelijke lezing is dat de agents de instructie negeerden. Dat is niet wat er gebeurde, en dat doet ertoe, want het verandert wat de fix moet zijn.

Elke agent had een lokaal verdedigbare reden om te schrijven. Een rode suite en een spec die fout leek. Een bug die vier seconden kost om te fixen en veertig om te beschrijven. Geen van hen besloot de regel te breken. Elk besloot dat zijn geval het geval was dat de regel niet bedoelde. Van binnenuit de stap lijkt de uitzondering altijd redelijk.

Een geschreven instructie is een verzoek aan het oordeel van het model. Een reviewer die ook dingen kan fixen, zal vroeg of laat dingen fixen, want fixen is de kortste weg van "ik heb het gevonden" naar "klaar". De enige regel die contact met een plausibele uitzondering overleeft, is er een waar het model niet tegenin kan gaan: een tool die er niet is.

Waarom de globale instelling het ook niet kon

Tot dan toe was de enige hendel die een lopende stap bereikte de providerinstelling, die alle Claude-agents op de machine tegelijk dekt. Dat is de verkeerde vorm voor een run. In dezelfde pipeline moet de implementeerder schrijven en de reviewer niet. Een globale schakelaar kan ze niet uit elkaar houden.

En de beperking per agent die we al hadden, die een ticket kan meegeven wanneer het een agent start, werd bewust niet doorgegeven aan teamstappen. Een agent gestart vanuit een ticket kon dus beperkt worden, en een node van een team niet. Dat was de hoofdoorzaak, en het was een ontwerpbeslissing die slecht verouderd was.

De regel: één vinkje op de node

De fix is een boolean op de review-node. Vink Alleen-lezen aan en de agent die die stap belichaamt, wordt gestart zonder schrijftoegang tot het project: geen bestandsbewerking, geen git commit of push, geen shell-commando waarvan de enige taak is de werkboom te wijzigen. Lezen, grep, git diff, git log, de tests, de linter en elke teamtool blijven open.

We waren expliciet over wat het niet is: het is geen deny-lijst die de gebruiker met de hand schrijft, per CLI. Niemand hoeft vijf permissiesyntaxen te kennen om "deze reviewt" te zeggen. De schakelaar levert voor elke provider de juiste flag op, en hij wordt als laatste toegepast, na de autonome modus en na alles wat de gebruiker op de agent heeft opgeslagen, zodat hij wint.

Wat elke CLI doet, afgelezen uit zijn eigen help

We dwingen alleen af bij providers waarvan we de flag in hun eigen --help hebben gelezen. Een gegokte flag breekt de start af met een parse-fout, en dat is erger dan een stap zonder afdwinging. De andere CLI's krijgen alleen de geschreven regel, en de editor zegt dat in gewone taal onder het vinkje.

CLIWat de alleen-lezen schakelaar toevoegtHoudt stand in autonome modus?
Claude Code--disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)" en de restJa, deny-regels gelden onder --dangerously-skip-permissions
Codex--sandbox read-onlyJa, het is een OS-sandbox (Seatbelt op macOS, Landlock op Linux), geen toollijst
Grok Build--deny "Edit" --deny "write" --deny "Bash(git commit*)" en de restJa, deny-regels gelden onder --always-approve
Antigravity--mode planJa, plan is de alleen-lezen uitvoeringsmodus van de CLI
OpenCode--agent planJa, de ingebouwde plan-agent weigert de bewerkingstools
Mistral Vibe, Kimi Code, Copilot, Cursor, Amp, Aider en de restalleen de prompt-alineaGeen geverifieerde flag, en dat zeggen we in de editor

Twee details in die tabel kostten ons elk een bug, dus ze zijn het waard om uit te schrijven.

Codex en Grok weigeren een herhaalde flag. Beide parsen hun argumenten met een strikte parser. Als de gebruiker al --sandbox workspace-write op de agent had opgeslagen, zou --sandbox read-only erachter plakken het niet overschrijven, het zou de start laten crashen. Voor flags met een waarde verwijderen we dus elk bestaand voorkomen, met zijn waarde, voordat we de onze toevoegen. Hetzelfde voor --agent bij OpenCode, waarvan de parser een herhaalde flag in een array verandert en verderop faalt.

Op Claude Code moet de lijst stapelen. --disallowedTools neemt een lijst gescheiden door spaties en mag herhaald worden, en we geven er al een mee wanneer een agent de ingebouwde browser niet mag besturen. De parser plakt een herhaalde variadische optie aan elkaar, dus de twee lijsten tellen op in plaats van dat de tweede de eerste vervangt.

De volledige lijst voor Claude Code bestaat uit de vier bestandsbewerkingstools, elk git-subcommando dat schrijft naar de index, de boom, de refs of een remote (add, commit, push, merge, rebase, reset, checkout, switch, restore, stash, cherry-pick, revert, apply, am, rm, mv, clean, tag, worktree), en de shell-commando's die alleen bestaan om bestanden te wijzigen (rm, mv, cp, tee, touch, mkdir, chmod, chown, ln, truncate, dd, sed -i). Grok neemt dezelfde regel-strings, in zijn glob-vorm, plus zijn eigen namen voor de bestandstools (search_replace, write, hashline_edit).

De prompt heeft nog steeds een taak

De flag weigert. Hij legt niets uit. En een agent die een weigering tegenkomt die hij niet begrijpt, behandelt die als een bug en zoekt een andere weg erdoorheen, en dat is precies het gedrag dat we wilden wegnemen.

Een alleen-lezen stap krijgt dus ook twee zinnen in zijn prompt. De eerste zegt dat de stap alleen-lezen is, somt op wat dat betekent, en stelt dat een weigering de regel is, geen obstakel om met een ander commando omheen te werken. De tweede somt op wat open blijft, en zegt de agent om in zijn overdracht te rapporteren wat er moet veranderen, met het bestand, de regel en de reden, en het aan de stap die eigenaar is van de code over te laten om het toe te passen.

Op de CLI's met een geverifieerde flag is die alinea wat de weigering begrijpelijk maakt. Op de andere is hij de hele afdwinging, en dat zeggen we liever dan te doen alsof.

Wie alleen-lezen is in de meegeleverde templates

De nodes die oordelen zijn alleen-lezen: de QA-verificatiestap van de twee starttemplates, de reproductie- en verificatiestappen van Bug hunt, de takken QA en Security van Release shield, de tester van Feature squad.

De nodes die eigenaar zijn van de code blijven schrijven: de developer, en de release gate die geschreven is om elke bevinding zelf te fixen. Een release gate die niet kan schrijven, is een release gate die niet kan releasen.

Die splitsing is het hele ontwerp, en het is de splitsing die het incident twee keer schond: een release-node die op de verkeerde plek schreef, en review-nodes die überhaupt schreven.

Wat dit niet is

Het is geen beveiligingsgrens. De melder zei het in het rapport, en hij had gelijk: een bash -c komt om een tool-deny-lijst heen. Als je een agent moet isoleren die je niet vertrouwt, is dat een sandbox of een aparte machine, en Codex is de enige van de vijf waarvan de alleen-lezen modus dat echt is.

Wat de schakelaar tegenhoudt is het ongeluk en de roldrift, en dat is wat er echt gebeurt. Een reviewer ontsnapt niet expres aan een deny-lijst. Hij grijpt uit reflex naar Edit, en die reflex wordt nu geweigerd.

Wat we niet hebben gebouwd

De melder vroeg nog één ding: een gebeurtenis in de tijdlijn van de run die zegt "node X heeft naar de boom geschreven", als minimaal signaal zelfs zonder afdwinging. Het is een goed idee en we hebben het hier niet gedaan, omdat het een basis-diff per stap aan de kant van de runner vereist. Als de behoefte terugkomt, is dat het volgende stuk.

Als je AgentsRoom niet gebruikt

De flags hierboven zijn te kopiëren zoals ze zijn. Een review-agent die met de hand wordt gestart met codex --sandbox read-only, of claude --disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)", kan niet doen wat onze twee review-nodes deden. Zet dezelfde twee zinnen in zijn prompt zodat hij weet waarom hij geweigerd wordt.

Wat het vinkje toevoegt, is dat je niet hoeft te onthouden welke van de vijf syntaxen van toepassing is, dat de flag wint van welke autonome modus de stap ook draait, en dat hij een run overleeft die later dezelfde stap opnieuw binnengaat.

De node-schakelaar en de tabel per provider staan gedocumenteerd op de pagina Agent Teams. Of een review door een agent überhaupt de moeite waard is, en hoeveel van een diff nog een mens verdient, is een andere vraag, en daar schreven we over in Moet je de code van je AI-agent nog reviewen?. Dit artikel gaat over het kleinere, mechanischere ding: zodra je hebt besloten dat een agent reviewt, maak hem fysiek niet in staat om iets anders te doen.

Download AgentsRoom

Draai al je AI-agenten, op al je projecten, vanuit één enkel venster.

GratisDownload AgentsRoom

Companion-app: houd je agents onderweg in de gaten

Breng je eigen: Claude, Codex, Antigravity CLI of andere AI-provider.

Download de extensie
Chrome Web Store

Stuur bugs en verzoeken direct naar je openbare backlog.

Meerdere projecten
Multi-provider
Meerdere agenten
Live status
Bestandsverschil & commit
Mobiele metgezel
Live voorbeeld
Agententeams
Browserautomatisering
Backlog-gedreven ontwikkeling
Promptbibliotheek
Vaardighedenbibliotheek
Bekijk alle functies

Verder lezen