← Blog

Chat agents

Chat agent thuiszorg: 2.140 vragen per week, één wachtrij

Zondagavond 23:14: een mantelzorger vraagt wanneer haar moeder morgen ochtendzorg krijgt. De widget antwoordt in acht seconden, zonder het medicatiedossier aan te raken.

Jacob Molkenboer· Oprichter · A Brand New Company· 28 dec 2025· 9 min
Messing belletje op open linnen register, gevouwen kaart met groen lint, porseleinen schoteltje met penhouder.

Het is zondag, 23:14. Een dochter in Wormerveer ligt weer wakker. Haar moeder, eenentachtig, hartfalen, woont alleen in een flat bij de Zaanbocht. Ze wil weten hoe laat morgen de ochtendzorg komt. Ze wil niet bellen. Ze wil een tijd op een scherm zien zodat ze kan gaan slapen.

Ze typt haar vraag in de chat widget op de site van de coöperatie. Acht seconden later staat het antwoord er: tussen 07:40 en 08:10, Carla rijdt. De dochter sluit de tab. De widget logt het gesprek en stuurt niemand een melding.

Dit stuk gaat over waarom die interactie lastiger is dan hij eruitziet. We bouwden de agent eerder dit jaar voor een thuiszorg-coöperatie van drieëndertig mensen in Zaanstad. De agent verwerkt nu zo'n 2.140 mantelzorgervragen per week. Bijna geen enkele bereikt een mens. De vragen die dat wel doen, komen binnen zestig seconden bij de juiste persoon terecht, en nooit met medicatieadvies.

De coöperatie achter de widget

Namen en exacte identifiers laten we om voor de hand liggende redenen weg. De vorm: drieëndertig mensen, waarvan tweeëntwintig wijkverpleegkundigen en verzorgenden IG, drie teamleiders, één bestuurder-zorgmanager, de rest planning en backoffice. Ongeveer 410 cliënten in Zaanstad en de lintdorpen tot Krommenie. Gemengde financiering: de meeste cliënten op Zvw wijkverpleging, een flink deel op Wlz, een handvol op Wmo huishoudelijke hulp via de gemeente. Het ECD is Nedap Ons, in productie sinds 2014, diep gemaatwerkt, met twaalf jaar aan routes, planningsprofielen en indicatie-templates erachter.

De coöperatie is niet groot genoeg voor een contactcenter. Voor de agent live ging, kwam elke vraag buiten kantoortijd binnen in één gedeelde inbox die de teamleiders volgens een rooster bewaakten. Gemiddeld 380 berichten per week, met een mediane eerste reactietijd van zeventien uur en het soort weekendbacklog dat carrières van teamleiders beëindigt. De vraag voor ons was nooit “kan een chat agent dit”. Het was: wat is de kleinste set vragen die we zonder mens kunnen beantwoorden, en wat is de grootste set die we überhaupt niet mogen beantwoorden?

Twee harde regels, vastgelegd op dag één

Vóór elke prompt, elke retriever, elke integratie: twee regels van de bestuurder, in gewoon Nederlands opgeschreven in de project brief.

Regel één. Als een vraag een cliënt betreft met een Wlz-vlag in het dossier — CIZ-indicatie, complexer zorgprofiel, andere administratieve route — mag de agent geen antwoord geven uit cache, RAG of parafrase. Hij moet de vraag doorzetten naar de teamleider queue. Wlz-cliënten lopen via andere tarieven en een ander inspectieregime. Een verkeerd antwoord over een Wlz-cliënt is niet alleen pijnlijk; het is een meldingsplichtig incident.

Regel twee. Elke vraag die medicatie noemt of impliceert — dosering, tijdstip, interactie, “mag mijn moeder haar oxazepam nu nemen”, “ze is haar metoprolol vergeten” — wordt bij de widget geblokkeerd. De agent stelt nooit een medicatie-antwoord op. Hij vertelt de gebruiker dat een verpleegkundige eerst in het dossier kijkt en terugbelt, en schrijft de vraag dan naar een vier-ogen-queue. Twee verpleegkundigen moeten het dossier en de vraag lezen voordat er een antwoord uitgaat. Dit is geen overdreven voorzichtigheid van ons. Het is wat de Inspectie Gezondheidszorg en Jeugd van een kleine thuiszorg-organisatie verwacht, en wat de bestuurder op dinsdagochtend niet wilde hoeven uitleggen.

Praten met een twaalf jaar oude Nedap Ons

Nedap Ons heeft een moderne API. OAuth2, JSON, geversioneerde endpoints. Op papier is integratie rechttoe rechtaan. In de praktijk lijkt een instance die sinds 2014 draait in niets op een verse tenant. Deze had:

  • Twee parallelle cliënt-identifierschema's uit een fusie in 2018, met zo'n zestig cliënten die er twee hadden.
  • Een custom indicatieprofiel-veld met eenendertig waarden, waarvan er nog maar negen actief in gebruik waren.
  • Drie vrije-tekstvelden die het planningsteam al zeven jaar stilletjes als gestructureerde data gebruikte.
  • Een geplande job uit 2016 die 's nachts bepaalde statusvlaggen herschreef. Niemand in het team wist ervan. We vonden hem omdat twee van onze queries om 03:00 andere antwoorden gaven dan om 09:00.

Aan Nedap Ons hebben we niets aangeraakt. We bouwden er een read-only adapter voor die drie dingen deed: de identifierschema's normaliseren, indicaties projecteren door een current-vs-legacy mapping-tabel die de bestuurder zelf bijhoudt, en elke vijftien minuten een snapshot van de canonieke cliëntweergave in een Postgres aan onze kant zetten. De agent leest uit de snapshot, nooit live uit Ons. De snapshot is de bron van waarheid voor de widget; Ons is de bron van waarheid voor al het andere.

Elegant is anders. Dit is wat twaalf jaar organische schema-groei vereist. Hadden we vastgehouden aan live reads, dan zaten we nog steeds die nachtelijke job te debuggen.

def classify_question(text: str, dossier: Dossier) -> Route:
    if mentions_medication(text):
        return Route.FOUR_EYES_NURSE  # rule two: hard block
    if dossier.wlz_flag:
        return Route.TEAMLEIDER_QUEUE  # rule one: hand off
    if is_planning_question(text) and dossier.has_active_route():
        return Route.AUTO_ANSWER
    return Route.TEAMLEIDER_QUEUE  # default: human

def route(q: Question) -> None:
    dossier = snapshot.load(q.client_id)  # never Ons live
    target = classify_question(q.text, dossier)
    sla = None if target == Route.AUTO_ANSWER else 60
    queue.dispatch(target, q, sla_seconds=sla)

De classifier heeft twee lagen. Een regex- en keyword-check op medicatietermen draait als eerste en escaleert nooit naar de LLM. Daarna een klein, fine-tuned Nederlands intent-model. De medicatiecheck dekt ongeveer 380 generieke en merknamen plus veelvoorkomende spelfouten. We werken hem maandelijks bij vanuit het Farmacotherapeutisch Kompas. Hij is niet slim. Dat hoeft ook niet.

Zestig seconden in de teamleider queue

Als een Wlz-gevlagde vraag binnenkomt, doet de agent in dezelfde call drie dingen: hij schrijft een entry in de teamleider queue met volledige context en dossier-links, hij stuurt een iOS-push naar de teamleider die dienst heeft, en hij vertelt de mantelzorger dat een mens er binnen het uur naar kijkt. De SLA in het contract is zestig seconden van vraag tot queue-entry plus push. De mediaan in productie is 4,1 seconden. De 95e percentiel is 22 seconden. De trage staart komt vrijwel volledig door cold-start op de Ons-snapshot-reader na lange idle-periodes. We hebben dat niet opgelost omdat er bij 22 seconden niets breekt.

De queue zelf is een kleine React-view. Hij toont de vraag, de cliënt (naam, geboortejaar, route, huidige indicatie, Wlz-status), de laatste drie contactmomenten, en een samenvatting van één regel die de agent heeft gegenereerd. De teamleider tikt op behandeld of doorzetten naar verpleegkundige. Dat is de hele interface. We hebben de eerste zes maanden bewust elk verzoek om filtering, sortering en dashboards afgehouden. Een queue die eruitziet als een tool wordt gebruikt als een tool. Een queue die eruitziet als een inbox wordt genegeerd als een inbox.

Medicatie: vier ogen, geen uitzonderingen

De medicatie-pipeline is met opzet het saaiste systeem in de stack. Als de keyword-check raak schiet, geeft de agent een vast Nederlands antwoord: “Voor vragen over medicatie kijkt een verpleegkundige eerst in het dossier. We bellen u binnen twee uur terug op het nummer dat bij ons bekend is. Klopt dat nummer nog?” Het nummer wordt vervolgens in de widget bevestigd. De vraag valt in een aparte queue die twee verpleegkundigen moeten afhandelen voordat het gesprek als afgerond wordt gelogd. We loggen beide reviewer-ID's en de timestamps. Audit-ready by design.

In negen maanden productieverkeer, ruwweg 78.000 mantelzorger-interacties, heeft de agent nul medicatieantwoorden geproduceerd. Niet omdat hij heeft geleerd het niet te doen. Omdat hij het niet kán. Het pad door de code dat er één zou genereren, bestaat niet.

Kernpunt

De veiligheid van een agent in een gereguleerd domein wordt bepaald door wat hij niet kán, niet door hoe goed je hem vertelt iets niet te doen.

Hoe 2.140 vragen per week er in de praktijk uitzien

Van de ruwweg 2.140 vragen die de widget in een gemiddelde week ziet:

  • Zo'n 1.610 worden volledig door de agent afgehandeld. Het gros zijn planningsvragen (“wanneer is het volgende bezoek”), routebevestigingen, ziekmeldingen door mantelzorgers, en adres- of telefoonwijzigingen die de agent via de adapter terugschrijft naar een te-controleren queue voor het planningsteam.
  • Zo'n 380 belanden in de teamleider queue. De meeste zijn Wlz-gevlagde routinevragen die we in principe zouden kunnen beantwoorden; de bestuurder heeft regel één nog niet versoepeld en gaat dat misschien ook nooit doen. Ongeveer veertig daarvan zijn echt complex.
  • Zo'n 150 belanden in de medicatie-vier-ogen-queue. Iets minder dan de helft gaat over timing in plaats van dosering en is opgelost in één terugbelmoment van een verpleegkundige.

Wat we niet hadden verwacht: 61% van de vragen komt buiten 08:00–17:30 binnen; 88% komt van mantelzorgers in plaats van cliënten zelf; en mantelzorgers leerden binnen twee weken na livegang kortere, beter beantwoordbare vragen te stellen. Gedrag past zich sneller aan de interface aan dan je zou denken.

Wat we anders zouden doen

Twee dingen.

Eén: we zouden de snapshot-laag vóór de agent bouwen, niet ernaast. We verloren twee weken aan het zoeken naar wisselende antwoorden die uiteindelijk die nachtelijke job uit 2016 bleken. Als je integreert met een langlopend ECD: ga ervan uit dat er minstens één ongedocumenteerde geplande job is en minstens één vrije-tekstveld dat als gestructureerde data wordt gebruikt. Audit eerst, bouw daarna. Draai een week lang dezelfde read query om 02:00, 09:00 en 17:00 en diff de resultaten. Saai; goedkoop; scheelt je een sprint.

Twee: we zouden de interface van de teamleider queue eerder aan gebruikers laten zien. De eerste versie die we live zetten had de queue, de SLA en de push-meldingen, maar een teamleider-ervaring die we niet hadden stress-getest om 23:00 op een moe toestel over 4G. Het eerste weekend misten twee teamleiders pushes omdat de queue-view vier seconden nodig had om te laden. We hebben hem in een dag herschreven. We hadden hem de week voor livegang moeten herschrijven.

Wat je vanmiddag kunt doen

Als je support of operations runt voor een gereguleerde organisatie — zorg, finance, juridisch, alles met een inspecteur — en je denkt aan een chat agent: de nuttigste vijf minuten die je kunt besteden, is twee lijstjes opschrijven. Lijst één: elk type vraag dat, fout beantwoord, een meldingsplichtig incident is. Lijst twee: elk type vraag dat echt hoog volume en laag risico is. Blokkeer lijst één hard in de classifier. Bouw de agent voor lijst twee. Het middengebied, waar de meeste projecten sneuvelen, heb je nog niet nodig.

Toen we deze widget voor de Zaanse coöperatie bouwden, liepen we er telkens tegenaan dat de veiligheidsregels geen feature op een roadmap waren. Ze waren de architectuur. We hebben uiteindelijk minder functies opgeleverd dan de brief vroeg, en de bestuurder was daar gelukkiger mee. Dat is grofweg het patroon waar we voor chat agents in Nederlandse zorg, juridisch en finance op uitkomen: eerst bouwen naar de harde regels, daarna kijken wat de agent daarbinnen nuttig kan doen.

Kern

De veiligheid van een agent in een gereguleerd domein wordt bepaald door wat hij niet kán, niet door hoe goed je hem vertelt iets niet te doen.

FAQ

Mag een chat agent in de Nederlandse thuiszorg medicatievragen beantwoorden?

Niet in een vorm die wij bij de IGJ zouden verdedigen. We blokkeren medicatievragen hard in de classifier en routeren ze naar een vier-ogen-queue waar twee verpleegkundigen het dossier moeten lezen voordat er een antwoord uitgaat.

Waarom routeer je elke Wlz-gevlagde vraag naar een teamleider in plaats van hem te beantwoorden?

Wlz-cliënten lopen via andere administratieve routes, tarieven en inspectieregimes. De marginale tijdwinst van automatisch beantwoorden weegt voor een kleine thuiszorg-organisatie niet op tegen het audit-risico.

Hoe integreer je een chat agent met een twaalf jaar oude Nedap Ons?

Een read-only adapter met een Postgres-snapshot om de vijftien minuten voor Ons. De agent queryt Ons nooit live. Audit eerst op verouderde vrije-tekstvelden die als gestructureerde data worden gebruikt en op ongedocumenteerde geplande jobs.

Hoe snel reageert de teamleider queue in de praktijk?

Een SLA van zestig seconden van vraag tot queue-entry plus push. Mediaan in productie is 4,1 seconden, p95 is 22 seconden. De staart is cold-start op de snapshot-reader na lange idle-periodes.

chat agentsai agentscase studyintegrationsautomationoperations

Iets bouwen?

Start een project