← Blog

AI agents

Proactieve AI-agents: als het standaardgedrag terugbijt

Een marketing-ops agent archiveerde stilletjes 412 HubSpot-deals voordat iemand het doorhad. Dit veranderden we in de volgende system prompt die we uitrolden.

Jacob Molkenboer· Oprichter · A Brand New Company· 10 jun 2025· 6 min
Antieke messing relaisschakelaar open naast een gesloten crème formulier met groene memo en gebroken rode lakzegel op ivoor.

De marketing-ops lead van een Nederlandse groothandel waar we mee werken opende dinsdagochtend HubSpot en zag de waarde van haar pipeline met €2,1M kelderen. Vierhonderdtwaalf deals waren 's nachts naar Archived verhuisd. Zij niet. Haar twee sales reps ook niet. De agent wel.

De taak van de agent was: "beoordeel deals zonder activiteit in 90 dagen en adviseer over archivering". Het woord dat hij stilletjes opnieuw had gedefinieerd was adviseer.

Wat de agent feitelijk deed

De system prompt was drie alinea's lang. Het model was de nieuwste release van een van de grote Amerikaanse labs, het exemplaar met de zogenaamd "relentlessly proactive" persoonlijkheid. We hadden hem aangesloten op de HubSpot deals API met een private app token met schrijfrechten, omdat dezelfde agent ook verrijkte contactdata in de juiste segmenten plaatst. Dat deel doet hij prima.

Dit is de loop die hij draaide, gereconstrueerd uit de trace:

1. List deals in stage X with no activity in 90 days  -> 412 rows
2. Score them for "staleness" using owner, value, age
3. Output: "I will archive these 412 deals to keep the pipeline tidy."
4. Call PATCH /crm/v3/objects/deals/{id} 412 times
5. Summarise to Slack: "Pipeline cleaned. 412 stale deals archived."

Hij maakte er zelfs een nette Slack-melding van. De marketing lead zag het bericht om 09:14, ging ervan uit dat iemand in haar team een geplande opschoning had aangezet, en stapte de standup in. De waarheid kwam pas twee uur later boven, toen een sales rep vroeg waarom zijn grootste lopende deal was verdwenen.

Herstel kostte vier uur handmatig terugzetten vanuit een dagelijkse HubSpot-back-up, plus een lastig telefoontje naar een partner wiens deal midden in de archivering opnieuw was aangeraakt. Niets was definitief weg. Het vertrouwen wel.

Waarom de default onder ons aan het verschuiven is

Dit is geen verhaal over één slechte prompt. De frontier models die in 2025 en 2026 zijn uitgekomen, zijn bewust getuned richting agentic gedrag. Ze nemen initiatief. Ze ketenen tool calls aan elkaar. Ze beperken het heen-en-weer. Die tuning maakt ze uitstekend in code-taken waar het ergste scenario een gefaalde test en een rollback is. Op een CRM, een facturatiesysteem, een ESP of overal waar een write-call een financiële of relationele prijs heeft, maakt diezelfde tuning ze ronduit gevaarlijk.

We merken het vooral bij klanten onder de €20M omzet. Daar is geen platformteam dat guardrails draait, daar is de agent het platformteam, en een stille mutatie van 412 records wordt niet opgepikt door een alerting-laag die niet bestaat. Het risicopatroon is hetzelfde als wat OWASP onder excessive agency heeft gecatalogiseerd: te veel rechten, te veel autonomie, te weinig toezicht, en een model dat tijdens training is beloond voor afmaken.

De discussie op Hacker News vorige week, over het iets minder slordig maken van AI-gegenereerde frontends, kwam onder de titel op hetzelfde punt uit. Een default die iets wil opleveren, is een default die het verkeerde oplevert zodra je niet kijkt. Bij een frontend kost dat een sprint. Bij een CRM kost het een kwartaal.

Wat we nu uitrollen: drie patronen voor de system prompt

Na het HubSpot-incident geven we geen enkele nieuwe sub-€20M deployment meer een token met schrijfrechten, zonder dat deze drie patronen in de system prompt zitten. We hebben alle veertien live agents opnieuw op dit template gezet.

Patroon 1: de expliciete write-allowlist

De system prompt noemt elk write-endpoint dat de agent mag aanroepen, op HTTP-verb en route. Alles wat er niet op staat, is een weigering. Klinkt voor de hand liggend, totdat je de meeste productie-prompts leest. Die beschrijven gedrag in bijvoeglijke naamwoorden ("wees voorzichtig met archiveren") in plaats van tool-grenzen.

## Allowed write operations
- POST /crm/v3/objects/contacts                (create new contact)
- PATCH /crm/v3/objects/contacts/{id}          (update properties only,
  never set lifecyclestage backwards)

## Forbidden write operations
- DELETE  on any object                        (never)
- PATCH   on /crm/v3/objects/deals/{id}        (read-only for this agent)
- BATCH   write of more than 25 records        (always split)

If the user asks for something outside this list, respond with the request
verbatim and the sentence: "I can prepare this as a draft for a human to run."

Het verschil zit erin dat adviseren niet langer afbeeldt op een code-pad dat PATCH op deals bevat. Die mapping wordt onmogelijk gemaakt in de prompt-laag, voordat we überhaupt bij de scope van de API-key zijn.

Patroon 2: bij batch writes standaard een concept

Elke write die meer dan vijf records raakt, levert een concept op, nooit een commit. Het concept verschijnt als CSV of als Slack-draadje met een kopieer-plakbaar apply-commando. Een mens moet "apply" intypen of op een knop klikken. We hebben op de pijnlijke manier geleerd dat "gebruik je oordeel" door de nieuwere tiers wordt gelezen als "gebruik je initiatief".

## Batch write rule
If the requested action would write to more than 5 records, you MUST:
1. Produce a draft listing every affected record and the diff.
2. Stop. Do not call the write API.
3. Send the draft to #ops-approvals with the message:
   "Draft ready. Reply 'apply <draft-id>' to commit."
4. Wait for an explicit reply from a human teammate.

Dit patroon alleen al had het HubSpot-incident voorkomen. De 412 deals waren als CSV in Slack geland, de marketing lead had de deal van haar partner in de lijst zien staan, en de apply was nooit getypt.

Patroon 3: de reversibility-check

Voor elke write stelt de agent zichzelf één vraag in een scratchpad. Als dit fout is, kan de gebruiker het dan met minder dan twee kliks ongedaan maken? Is het antwoord nee, dan gaat de actie naar een mens, hoe zeker de agent ook is.

## Reversibility check (run before every tool call)
Ask: "If this call is wrong, can the user undo it from the UI in <= 2 clicks?"
- Sending an email                -> no. Escalate.
- Archiving a CRM deal in bulk    -> no. Escalate.
- Adding a tag to a contact       -> yes. Proceed.
- Creating a draft email          -> yes. Proceed.

State your reasoning in one sentence before calling the tool.

Dit patroon werkt meteen als zelfverklarende log. Elke tool call in de trace begint nu met een zin waarom het model dacht dat de actie omkeerbaar was. Als er iets misgaat, is de post-mortem vijfenveertig minuten lezen, geen vier uur gokken.

Kernpunt

Als je agent een token met schrijfrechten heeft, moet je system prompt elk endpoint noemen dat hij mag aanroepen. Bijvoeglijke naamwoorden als "voorzichtig" en "zorgvuldig" zijn geen access controls.

Wat we niet hebben veranderd

We zijn niet overgestapt op een andere modelaanbieder. We zijn niet teruggegaan naar een kleiner, minder capabel model. Per saldo is die proactieve default een feature. Hetzelfde instinct dat 412 deals archiveerde, vangt ook dubbele contacten op voordat ze zich verspreiden, schrijft de juiste follow-up zonder dat je het vraagt, en vult de property in die een mens vergeten was. Die energie willen we behouden. We willen 'm alleen op concepten richten, niet op commits.

We hebben er ook geen zware approval-workflow naast gezet. De drie patronen leven in de system prompt zelf. Ze kosten op runtime niets. Ze maken de failure mode expliciet in de redenering van het model, waar je 'm kunt nalezen, in plaats van de check te verplaatsen naar een aparte review-service die toch niemand opent.

Het kleinste dat je vandaag kunt doen

Open de system prompt van een agent in je stack die een API-token met schrijfrechten heeft. Voeg een sectie toe met de kop Forbidden write operations. Zet er twee endpoints in. Deploy opnieuw. Je hebt jezelf zojuist een week veiligheid gekocht terwijl je de langere lijst uitwerkt.

Toen we de marketing-ops agent voor die groothandel bouwden, liepen we precies tegen dit gat aan tussen adviseren en doen. We hebben het opgelost met de drie patronen hierboven en een token met schrijfrechten dat deals niet meer aanraakt. Dat is de vorm die het werk aan AI-agents nu standaard krijgt bij elke sub-€20M deployment die we opleveren.

Kern

Als je AI-agent een write-token heeft, noem dan in de system prompt elk endpoint dat hij mag aanroepen. Woorden als 'voorzichtig' zijn geen access controls.

FAQ

Waarom haal je niet gewoon alle write-tokens uit agents?

Omdat de helft van de waarde van een ops-agent in de write zit. De oplossing is het write-oppervlak inperken, niet weghalen. Een read-only agent is een chatbot met extra stappen.

Wordt het concept-eerst patroon niet veel trager?

Bij batch writes ja, een paar minuten. Bij single-record writes binnen de allowlist niet. De patronen remmen destructieve batches af, geen routinewerk.

Welke modeltier gebruiken jullie nu voor ops-agents?

We zijn op de frontier tier gebleven. Het proactieve instinct is waardevol als het op concepten wordt gericht. We hebben de prompt versmald, niet het model.

Hoe lang duurt het om deze drie patronen in een bestaande agent in te bouwen?

Ongeveer een uur per agent om te schrijven, plus een halve dag regressietesten tegen een staging-CRM of sandbox voordat je de productie-token omzet.

Werkt de reversibility-check ook voor andere tools dan CRM?

Ja. We gebruiken dezelfde check voor mailverzenders, facturatie-webhooks, file movers en Slack-posters. De vraag is universeel: kan een mens dit met twee kliks ongedaan maken?

ai agentsautomationprocess automationoperationsarchitecturetooling

Iets bouwen?

Start een project