Email automation
Email-automation in de jeugdzorg: 1.420 mails per week
Dinsdagochtend 08:12: de operations lead opent haar inbox en ziet 312 verwijzersmails uit het weekend. De week ervoor verwerkte de agent er 1.420.

Dinsdagochtend 08:12. De operations lead van een Utrechtse jeugdzorginstelling met 27 medewerkers opent haar inbox en vindt 312 verwijzersmails uit het weekend. Een paar van huisartsen. Twee van een wijkteam. Eén bericht, veertien mails diep weggezakt, is een melding van een interne zorgcoördinator op een school. Het beschrijft een zestienjarige die op kwam dagen met blauwe plekken die ze niet kon verklaren. De teamregel: dat bericht moet binnen dertig minuten bij een gedragswetenschapper liggen. Het staat al eenenveertig uur ongelezen.
Zo zag het eruit toen we begonnen. Twaalf maanden later opent dezelfde operations lead haar dinsdaginbox en vindt nul ongelezen berichten. De agent heeft die week 1.420 mails getrieerd, 1.118 ontvangstbevestigingen opgesteld, 23 berichten in een gedragswetenschapper-queue gezet, en op 39 randgevallen een mens om een beslissing gevraagd. Het bericht over de blauwe plekken zou nu binnen vier minuten bij een gedragswetenschapper liggen.
Dit is het engineering-verhaal achter die verandering. Een deel ervan is saai. Het meeste van de waarde zat in de saaie stukken.
De vorm van het probleem
De jeugdzorg in Nederland draait op correspondentie van verwijzers. Een huisarts mailt een vraag, een wijkteam stuurt een melding door, een school stuurt een zorgsignaal, een medewerker van Veilig Thuis vraagt een update op een lopend dossier. Elke mail heeft een ander intakepad, een andere urgentie en een eigen juridische klok. Onder Jeugdwet artikel 7.3.8 moet een jeugdhulpaanbieder de gegevens van de cliënt correct en binnen redelijke termijn na ontvangst registreren, wat de inspectie in de praktijk uitlegt als dezelfde werkdag.
De instelling waar we mee werkten heeft 27 medewerkers: elf gedragswetenschappers en jeugdhulpverleners, zes ambulante medewerkers, vier schoolzorgcoaches, drie kantoormedewerkers, twee managers en één IT-coördinator die ook controller is. De inbox-triage ging handmatig. De twee intake-coördinatoren deelden een algemene mailbox, typten velden met de hand over in Nedap Ons, en aan het eind van elke dag zat er één om 21:00 nog vanuit huis ontvangstbevestigingen te beantwoorden.
De stack was net zo verouderd als het klinkt:
- Nedap Ons, het dossiersysteem, in productie sinds 2013. SOAP-API onder de motorkap, met een REST-shim die Nedap er in 2021 op zette en die ongeveer 60% afdekt van wat wij nodig hadden.
- Een on-prem Exchange Server 2013-archief. Zeven jaar correspondentie stond daar, geïndexeerd op
From:en weinig meer. - Outlook 2016 op elk bureau, nog steeds verbonden met die Exchange-server via RPC-over-HTTP.
- Een goedkeuringsflow van twee stappen in een SharePoint 2013-lijst die niemand onder de 35 begreep.
De belangrijkste constraint was niet technisch. De Jeugdwet staat niet toe dat je de eerste beoordeling van een melding met acuut veiligheidssignaal delegeert aan iets anders dan een gedragswetenschapper. Wat we ook bouwden, het moest allergisch zijn voor die categorie mail. De eerste taak van de agent — voor er ook maar één antwoord werd opgesteld — was weigeren om iets op te stellen.
De veiligheidssignaal-classifier komt eerst
We begonnen met het kleinst mogelijke model en de kleinst mogelijke belofte: nooit een acuut signaal missen. We accepteerden dat we te vaak zouden flaggen. We accepteerden niet dat we te weinig zouden flaggen.
De classifier loopt in twee passes. De eerste is een rule-laag: domme keyword- en structurele checks tegen een lijst met zinnen die de gedragswetenschappers zelf opschreven tijdens een workshop van twee uur. De lijst is korter dan je zou denken — "ik weet niet meer wat ik moet doen", "suïcidale uitingen", "fysiek geweld vanavond", en nog veertien andere. De tweede pass is een Claude Sonnet-call met een systemprompt die het team schreef, een few-shot van zeventien echte geanonimiseerde meldingen, en een output die één van drie strings moet zijn: acuut, spoed, regulier.
def triage(email: ParsedEmail) -> Triage:
if rule_layer_hits_acuut(email):
return Triage(level="acuut", reason="rule", confidence=1.0)
verdict = claude_classify(
system=SAFETY_SYSTEM_PROMPT,
few_shots=ANON_SHOTS,
user=email.plain_text,
)
# We bias toward escalation on disagreement.
if verdict.level == "regulier" and rule_layer_hints_spoed(email):
return Triage(level="spoed", reason="rule_override")
return verdict
Alles met de tag acuut wordt in een eigen queue in Microsoft Teams gezet, pingt de gedragswetenschapper van dienst en stopt. Geen autoreply. Geen concept. Geen "we hebben uw bericht ontvangen". De stilte van de agent is de feature. Een geautomatiseerde ontvangstbevestiging op een bericht dat zegt dat een kind in gevaar is, leest voor een verwijzer als een systeem dat de urgentie niet begreep.
Als je inkomende mail automatiseert in een zorg-, juridisch- of veiligheidsdomein, bouw dan eerst het "doe niets"-pad en lever dat op vóór het "stel een antwoord op"-pad. De agent moet het recht om te schrijven verdienen.
Praten met een dertien jaar oud dossiersysteem
Nedap Ons is geen vijandige API. Het is een systeem ontworpen voor menselijke schermen en daarna gedeeltelijk opengesteld voor machines. De REST-endpoints die er zijn, zijn goed gedocumenteerd. Die er niet zijn, zijn dat niet. Per intake-mail moesten we vier dingen doen: een bestaande cliënt vinden op basis van BSN-fragment-of-naam-of-geboortedatum, de mail aanhangen als correspondentie-item, een verrichting wegschrijven voor de ontvangstbevestiging, en de trajectstatus uitlezen zodat het concept kon refereren aan waar de cliënt zat in zijn hulpverleningsplan.
Drie van die vier hadden REST-endpoints. De vierde, het uitlezen van de trajectstatus, was alleen SOAP. We hebben beide achter een dunne Python-adapter gezet die de agent als één tool-oppervlak benadert.
class OnsClient:
def find_client(self, hint: ClientHint) -> Optional[Client]: ...
def attach_correspondence(self, client_id: str, email: ParsedEmail) -> str: ...
def write_verrichting(self, client_id: str, kind: str, body: str) -> str: ...
def get_traject_status(self, client_id: str) -> TrajectStatus: ...
De find_client-stap is waar bijna alle fouten zitten. Verwijzers spellen achternamen verkeerd, geven een roepnaam in plaats van een voornaam, gebruiken een oud adres. Wij hebben ervoor gekozen om nooit automatisch een cliënt aan te maken; als de agent geen match met hoge confidence kon vinden, ging de mail naar een "needs human match"-queue. Die queue draait op ongeveer negen mails per dag. De kosten van een verkeerde koppeling zijn een privacy-incident onder de AVG, dus de afweging is niet spannend.
Zeven jaar Exchange 2013 inlezen
Het archief was de verrassing. De eerste versie van de agent negeerde het; we waren twee weken live en de gedragswetenschappers begonnen te signaleren dat de concepten contextloos klonken. Een schoolzorgcoach schreef "naar aanleiding van ons gesprek vrijdag" en de agent had geen idee welk gesprek. Het archief bevatte de eerdere correspondentie (achttien maanden ervan voor een actief dossier) maar Exchange 2013 EWS laat zich niet graag scrapen.
We hebben het saaie werk gedaan. We schreven een EWS-pulling worker die om 03:00 draait, nieuwe items in een Postgres-tabel met een tsvector-kolom dropt, en de agent een search_archive(thread_id | sender, max_results)-tool geeft. De tool geeft maximaal zes eerdere berichten terug, plain text, met PII-reductie. De agent raakt Exchange nooit direct aan. De archive worker is één bestand van 240 regels code. Hij is in acht maanden niet meer aangepast.
Exchange 2013 is sinds april 2023 uit extended support. De instelling wist het. De migratie naar Exchange Online stond al op de roadmap voor 2026. We hebben bewust gekozen om de worker te bouwen tegen de versie die er was, niet tegen de versie die er zou komen, omdat waarde leveren in 2025 meer waard was dan future-proofen tegen een migratie waar de IT-coördinator al voor was ingepland.
Het opstellen van de ontvangstbevestiging
De drafting-stap is het deel waar de meeste case studies mee beginnen, en wij zetten 'm bewust bijna aan het eind. Tegen de tijd dat de agent een reply mag schrijven, is al het zware werk al gedaan: de mail is geclassificeerd, de cliënt gematcht, de correspondentie aangehangen, de archive-context opgehaald, de trajectstatus uitgelezen. Het concept zelf is een Claude-call met een systemprompt die de Jeugdwet 7.3.8-verplichtingen expliciet benoemt, de voornaam van de cliënt, de organisatie van de verwijzer, de termijn waar het team zich aan committeert, en een kopie van de laatste drie replies van dezelfde intake-coördinator zodat de toon klopt.
Elk concept landt in een review-queue. De intake-coördinator drukt op Verzenden, bewerkt en verzendt, of wijst af. We loggen de ratio van elk. In maand één was de verzonden-zonder-edit-ratio 38%. In maand negen is dat 84%. Het verschil is niet het model. Het verschil is dat we de afgewezen concepten steeds terugzetten in een few-shot-file waar de agent uit leest.
De drafting-prompt is het kleinste onderdeel van een werkende email-agent. De triage-laag, de integraties en de menselijke review-loop zijn waar 90% van de bouw zit.
Hoe de cijfers eruitzien in maand twaalf
In de week die eindigde op 14 juni 2026 verwerkte de agent 1.420 binnenkomende verwijzersmails. Daarvan:
- 23 kregen het label
acuuten werden zonder concept in de gedragswetenschapper-queue gezet. Mediane tijd tot oppakken door een mens: 3 minuten en 41 seconden. - 118 kregen het label
spoed, werden opgesteld en bovenaan de review-queue gezet met een SLA van twee uur. - 1.118 werden als
reguliergerouteerd, opgesteld en binnen dezelfde werkdag verstuurd. - 39 gingen naar de "needs human match"-queue omdat de agent ze niet met voldoende zekerheid aan een cliënt kon koppelen.
- 122 waren spam, nieuwsbrieven of out-of-scope en werden stil gearchiveerd.
De twee intake-coördinatoren besteden nu ongeveer 90 minuten per dag aan e-mail, tegen zes uur per persoon zoals ze zelf rapporteerden. De vrijgekomen tijd hebben ze gebruikt om de planning van de schoolzorgcoaches over te nemen — de meest gehate terugkerende meeting van de IT-coördinator. In de afgelopen twaalf maanden is niemand bij de instelling vertrokken. We claimen niet dat de agent dat veroorzaakt heeft. We claimen wel dat hij geen bijdrage meer leverde aan de redenen om te vertrekken.
Wat we anders zouden doen
Drie dingen, zonder omhaal.
Eén: we hebben onderschat hoeveel van het werk neerkwam op data-cleanup in Nedap Ons. Ongeveer een vijfde van de cliëntrecords had verouderde verwijzer-velden, wat onze matching-heuristieken brak bij het eerste echte volume. We hadden moeten vragen om een data-audit van één dag voor we ook maar één regel agent-code schreven.
Twee: de rule-laag in de safety classifier had vanaf dag één in version control moeten staan, niet onderhouden in een gedeeld document. We hebben hem in maand vijf naar een Git-repo verhuisd. De gedragswetenschappers leerden een pull request te openen. Die zin verbaast me nog steeds.
Drie: de Exchange 2013-worker had in week één live moeten gaan, niet in week drie. Concepten zonder archive-context waren erger dan geen concepten. Ze klonken zelfverzekerd én fout, en dat is de slechtste failure mode voor een systeem dat zorg raakt.
Toen we de email-agent voor deze Utrechtse jeugdzorginstelling bouwden, liepen we er steeds tegenaan dat het safety-signal-pad en het draft-pad twee aparte systemen moesten zijn, geen twee prompts in dezelfde keten. We hebben het uiteindelijk opgelost door de triage-classifier te behandelen als een microservice met één taak en een eigen escalatie-queue, en de drafting-agent alleen de output ervan te laten lezen, nooit de input. Als je naar een vergelijkbare bouw kijkt, is dat de structurele keuze die je als eerste moet maken — en het is precies het soort beslissing dat we bij elke AI-agent-opdracht maken.
De audit van vijf minuten die je morgen kunt draaien
Open je gedeelde inbox. Pak de laatste vijftig binnenkomende mails. Schrijf voor elk de latency op tussen aankomst en de eerste menselijke actie. Plot de verdeling. Als de long tail over een harde juridische of veiligheidsdrempel heen gaat (die van jou zal anders zijn dan de Jeugdwet, maar je hebt er één), is dat de mail die je als eerste automatiseert. Niet de mail met het hoogste volume. De mail met de hoogste inzet.
Kern
In een gereguleerde inbox bouw je eerst het doe-niets-pad, dan pas het concept-pad. De agent moet het recht om te schrijven verdienen — stilte op het verkeerde bericht is een feature.
FAQ
Waarom stuurt de agent geen automatisch antwoord op berichten die als acuut veiligheidssignaal worden gemarkeerd?
Omdat de Jeugdwet voorschrijft dat de eerste beoordeling van een acuut signaal door een gedragswetenschapper gedaan moet worden. Een machinaal gegenereerde bevestiging op dat soort bericht leest als een systeem dat de urgentie niet begreep, en dat is erger dan stilte.
Hoe gaat de agent om met privacy onder de AVG?
E-mailinhoud wordt in-region verwerkt, zoekresultaten uit het archief worden PII-gereduceerd voordat ze bij het model komen, en de agent maakt nooit automatisch een cliëntrecord aan. Matches met lage confidence gaan naar een menselijke queue in plaats van aan het verkeerde dossier te worden gekoppeld.
Moesten jullie weg van Nedap Ons of Exchange 2013 om dit werkend te krijgen?
Nee. We hebben dunne adapters tegen beide systemen gebouwd, precies zoals ze waren. De migratie naar Exchange Online stond al op de roadmap voor 2026, maar het live krijgen van de agent hoefde daar niet op te wachten.
Hoe lang duurde de bouw van begin tot eind?
Ongeveer twaalf weken tot de eerste productie-traffic op één intake-mailbox, daarna nog vier maanden iteratie op de rule-laag, de matching-heuristieken en de few-shot concepten voordat het team hem op de volledige inbox vertrouwde.