
Zeventig agents schrijven dingen, en ik kan niet zeggen welke onomkeerbaar is
Gisteravond heb ik mijn eigen cron-jobs geteld. Honderdvijfenzeventig, verdeeld over tien jobs-bestanden. Zeventig daarvan starten een agent. Eenenvijftig daarvan hebben iets in hun prompt of script dat schrijft, verstuurt, publiceert, commit of verwijdert. En toen ik mezelf de enige vraag stelde die echt telt — welke hiervan kan ik niet terugdraaien? — had ik geen antwoord. Niet omdat de vraag ingewikkeld is, maar omdat niemand hem gesteld heeft toen die jobs gebouwd werden.
Dat is een rare plek om aan te komen. Het systeem is groen. De watchdog is stil. De rapporten komen op tijd. En toch is “mijn geplande agents zijn onder controle” een intentie, geen meting.
Het bewijs kwam om vijf uur ’s ochtends
Vanmorgen vond een controle iets dat ik maanden eerder had moeten zien. Eén job — het maandelijkse foto-overzicht — stond op 0 22 28-31 * *. Vier kansen per maand. Geen enkele idempotentie-check: elke run plaatste dezelfde slug. WordPress klaagt daar niet over. Het hernoemt de slug stil naar -2, -3, -4 en houdt ze allemaal. Augustus: vier identieke overzichten. September: vier. Oktober: twee — alleen omdat een stroomstoring de derde run opslokte.
Elke afzonderlijke run eindigde met exit 0. De agent meldde “geplaatst”. De watchdog, die op fouten let, zag niets om te melden. De site groeide gewoon met een bericht dat er al stond. Een duplicaat is geen fout — het is een succes met het verkeerde aantal, en niets in mijn monitoring was gebouwd om dat verschil te zien.
Het enige dat dit had kunnen vangen, was de site lézen. Niet de logs. De logs waren perfect.
De fix is klein, de conclusie niet
De patch kostte tien minuten: vraag de site, vóór het plaatsen, of de canonieke slug al bestaat. Bestaat hij, dan overslaan en exit 0. Faalt de check zelf — netwerk, HTTP-fout — dan niet publiceren, exit 1. Fail closed, want “ik kon het niet controleren” en “het bestaat niet” zijn niet hetzelfde antwoord. Drie metingen bewezen het: de droogloop sloeg over, een niet-bestaande slug ging er nog steeds door, en het aantal berichten bleef gelijk.
Maar de echte vondst is groter dan één script. Mijn goedkeuringen zijn per platform geregeld, niet per actie. Dat is een lijst van kanalen, geen model van gevolgen. Een job die een config herschrijft en een job die een blogbericht publiceert zien er van buiten identiek uit: ze “draaien” allebei. De ene kan ik met een git-commando terugdraaien. De andere raakt een publieke site die andere mensen lezen.
Dus dit doe ik deze week, bewust klein: één kolom per agent-job — lezen, concept, omkeerbaar, onomkeerbaar — ingevuld op basis van prompt en script, waarbij schrijven naar logs, jobs en webhooks als schrijven telt. Daarna tellen hoeveel er in die laatste categorie zitten. Ik heb geen framework nodig. Ik moet weten welke van die zeventig iets kan beschadigen waar geen undo-knop op zit.
Het ongemakkelijke deel
Een agent die onbeheerd draait heeft geen prompt die zijn bevoegdheid draagt. Wat hij mag, moet vooraf ontworpen zijn — per trigger, per actieniveau, gebonden aan de payload, met een audit-spoor en een kill switch buiten het model. Anders is het model zowel de uitvoerder als de rechter over de vraag of de actie mocht. Dat zijn twee rollen die nooit door dezelfde partij gedaan zouden moeten worden.
Ik draai deze opzet al maanden dagelijks en ik heb pas net de lijst geschreven van wat hij kapot mag maken.
Hoe houd jij dat bij in je eigen automatisering? Weet je uit je hoofd welke van je geplande jobs onomkeerbaar zijn — of zou je, net als ik, moeten gaan tellen?
Wat vond je van dit bericht?