← Blog

Voice agents

Voice agents op een legacy GDS: 1.820 omboekingen per week

Een Maastrichts reisbureau van 28 mensen parkeert elke late omboeking in 60 seconden in de wachtrij van de duty manager. De voice agent leest Galileo. De duty manager belt terug.

Jacob Molkenboer· Oprichter · A Brand New Company· 20 feb 2026· 9 min
Zwarte bakelieten hoorn op crème leer, groen lint eroverheen, ivoren kaartje, koperen presse-papier en rood lakzegel.

Het is 22:47 op een dinsdag in maart. De duty manager van een Maastrichts reisbureau met 28 medewerkers heeft veertien tickets in haar wachtrij en dertien minuten voor het SGR-rapportagevenster om 23:00 sluit. Een half jaar geleden zat ze nu aan haar negende telefoontje van de avond. Vanavond heeft de telefoon nog geen één keer gerinkeld, want een voice agent neemt voor haar op.

Hij heeft vandaag 247 calls afgehandeld. De meeste werden opgelost zonder mens: een spellingscorrectie op een uitgaande PNR, een bagage-upgrade op een Kreta-charter, een vluchtnummer opzoeken voor een reiziger die haar bevestigingsmail niet kon vinden. De veertien tickets in de duty-manager-wachtrij zijn de wijzigingen die de agent weigerde aan te raken. Elke boekingswijziging binnen 24 uur voor vertrek gaat per ontwerp binnen 60 seconden naar een mens.

Zo ziet een van onze voice agents er in productie uit, vijf maanden na livegang. De architectuur is minder interessant dan de randvoorwaarden die hem vormden, dus we beginnen bij de randvoorwaarden.

De 23:00-deadline

Nederlandse reisbedrijven met een SGR-garantiefonds-aansluiting hebben een rapportageplicht: elke wijziging die een gegarandeerd onderdeel raakt (vlucht, hotel, transfer) binnen het beschermingsvenster moet vóór het einde van de operationele dag in hun systeem staan. Het fonds verrekent op next-day rapportage, en de operationele dag van onze klant sluit klokslag 23:00. Mis je het venster, dan is de wijziging nog steeds legaal, maar de afstemming met het fonds schuift een dag op, en de duty manager besteedt woensdagochtend aan het opnieuw opbouwen van de cijfers van dinsdag.

Dit was niet hypothetisch. Voordat we de agent live zetten, was de telefoonwachtrij na sluitingstijd genadeloos. Eén Kreta-vertraging stapelde tussen 21:00 en 23:00 dertig calls op elkaar. Twee duty managers, negentig seconden per call op de makkelijke, vier minuten op de moeilijke. De rekensom is wreed. Gemiddeld misten ze twee keer per maand de 23:00-deadline, en twee keer per maand verloor iemand een stuk van haar woensdag.

Waarom voice en niet chat

We hadden deze discussie in het eerste scoping-gesprek. Het klantenbestand van het bureau is gemiddeld ouder (gemiddelde boekingsleeftijd 54, mediaan 58), en calls na sluitingstijd komen onevenredig vaak van reizigers die al op een vliegveld of op de bestemming zijn. Een 60-jarige die op de check-in van Heraklion staat met een gemiste aansluiting opent geen chatwidget. Ze belt het nummer dat op haar reisbescheiden staat.

Dus: voice, alleen inbound, Nederlands, Duits en Engels. Geen outbound dial-out. We gebruiken een Twilio-nummer dat op een media stream landt, doorgesluisd via Deepgram voor transcriptie en een function-calling model voor intent- en slot-extractie. Text-to-speech is ElevenLabs met een custom voice die, in de woorden van het hoofd operations, klinkt als een Limburger die genoeg geslapen heeft.

De stack die we aantroffen

Reizen is een van de branches waar je nog steeds productie-infrastructuur tegenkomt die ouder is dan de engineers die hem onderhouden. Onze klant draait twee systemen die ertoe doen, en aan allebei viel binnen de scope niet te tornen.

Het eerste is Travelport Galileo, de GDS die het bureau sinds 2011 gebruikt. Medewerkers werken erin via Smartpoint, de Windows-desktopterminal. Travelport biedt een JSON API op hogere abonnementsniveaus; de bestaande licentie had die niet. Het tweede is een zelfgebouwde pakketreizen-database op SQL Server 2012, met hun non-GDS inventory: Griekse eilandcharters, Marokkaanse riads, skipakketten met eigen gecontracteerde hotels. SQL Server 2012 bereikte in juli 2022 het einde van extended support. Hij draait nog steeds alles wat ertoe doet.

We overwogen om eerst de SQL Server te upgraden. De klant overwoog het ook. Toen rekenden we uit wat de migratie zou kosten en hoe lang het bureau parallel zou moeten draaien, en waren we het erover eens dat het oplossen van het na-sluitingstijd-telefoonprobleem het waard was om eerst aan te pakken, tegen de stack zoals die werkelijk bestond. De migratie staat op de roadmap. Vóór maart zou hij sowieso niet live gaan.

Let op

Bouw je een agent tegen een verouderde database die je niet end-to-end in eigen beheer hebt, laat dan elke schrijfactie via een queue lopen die jij beheert. Laat de agent het verouderde systeem nooit rechtstreeks aanraken. De agent die de schrijfactie doet, is de agent die de schuld krijgt van de corrupte rij.

De 60-seconden-guardrail

De agent leest uit Galileo en uit de SQL Server. Hij schrijft naar geen van beide. Elk wijzigingsverzoek — een naamcorrectie, een datumverschuiving, een upgrade naar een andere klasse of een volledige annulering — produceert een gestructureerd handoff-ticket in een wachtrij voor de duty manager. De regel is binair. Valt de wijziging binnen 24 uur voor vertrek, dan verschijnt het ticket binnen 60 seconden na het einde van de call in de duty-manager-wachtrij. Zit de wijziging verder dan 24 uur weg, dan gaat hij naar de back office-wachtrij voor verwerking de volgende ochtend.

De grens van 24 uur is niet van ons. Hij komt uit het eigen SGR-rapportagebeleid van het bureau: alles binnen dat venster moet vóór 23:00 op een menselijk scherm staan. De 60-seconden-SLA is van ons, want het verschil tussen een ticket dat om 22:58 en een dat om 22:59 binnenkomt, is het verschil tussen het halen of missen van het rapportagevenster.

De 60 seconden halen we met brute eenvoud. De tool-call output van de agent voor elke "wijziging-binnen-24u"-intent schrijft direct naar een Postgres queue-tabel die we naast de legacy stack draaien. Een kleine Go-worker polt elke vijf seconden, classificeert het ticket en duwt het via een WebSocket de duty-manager-UI in. Het hele hot path — call eindigt, transcriptie zakt, tool-call vuurt, queue-insert, UI-push — meet p95 op 14 seconden in productie. De 60 seconden is de SLA die we naar het operations-team communiceren. Het werkelijke getal wordt vooral begrensd door hoe snel de mens op "volgende ticket" klikt.

Wat er op de handoff-kaart staat

De duty manager wil geen transcriptie. Ze wil de volgende actie.

De kaart bevat daarom, in deze volgorde: naam van de beller, telefoonnummer voor terugbellen, PNR of boekingsreferentie, vertrekdatum en -tijd (groot, rood als die binnen 6 uur valt), de gevraagde wijziging in één zin, de lezing van de agent waarom in één zin, en een deeplink die Smartpoint opent met de juiste PNR voorgeladen. Geen transcriptie op de kaart. De volledige transcriptie zit één klik verderop, en in vijf maanden hebben de duty managers hem voor ongeveer één op de twintig tickets geopend.

Dit was de grootste designdiscussie van het project. Engineers willen de transcriptie zichtbaar. Operations-mensen willen de actie zichtbaar. Bouw voor operations. De transcriptie bestaat voor de slechte dag waarop iets ter discussie komt te staan. Op een gewone avond leest niemand hem.

Conversatieontwerp, kort

De agent vraagt alleen wat hij nodig heeft. Hij begroet niet, vraagt niet hoe het met je gaat en becommentarieert het weer niet. De eerste beurt is: "Goedenavond, ABN-reizen, ik help u met uw boeking. Wat is uw boekingsnummer?" Antwoordt de beller in het Duits of Engels, dan schakelt de volgende beurt van taal. Is taaldetectie onzeker bij de eerste uiting, dan vraagt hij één keer en committeert daarna.

Hij herhaalt elk PNR terug in zowel letters als cijfers, NATO-stijl, en gaat alleen verder bij expliciete bevestiging van de beller. PNR's die na twee pogingen niet bevestigd zijn, gaan direct door naar een mens. Wordt hem gevraagd of hij een mens is, dan zegt hij dat hij een virtuele assistent is. Wordt hem gevraagd iets onomkeerbaars te beloven, dan zegt hij dat de duty manager binnen vijftien minuten terugbelt om te bevestigen. Die zin valt zonder uitzondering aan het eind van elke late-vertrek-call.

Wat de agent weigert te doen

We hebben dit in de system prompt geschreven en in een guardrail-laag die na elke modelbeurt draait. De agent neemt geen kaartbetalingen aan — het voice-kanaal valt niet binnen PCI-scope en daar willen we niets aan veranderen. Hij belooft geen goodwill-credit, voucher of restitutiebedrag; hij kan het verzoek erkennen en routeren. Hij bevestigt geen wijziging als geboekt. Hij zegt elke keer: "Ik heb uw verzoek bij onze duty manager geplaatst en zij belt u binnen vijftien minuten terug om te bevestigen." Hij raakt geen boeking aan die als groepsreis of zakelijk contract gemarkeerd staat; die gaan direct door naar een mens, zonder model in the loop.

De laatste regel verraste de klant. Wij beargumenteerden hem omdat omboekingslogica voor groepsreizen oprecht buiten dat valt waarover een model oordelen mag vellen. De kostprijs van een verkeerde inschatting bij een schoolreis van 40 personen is te hoog voor het opwaarts potentieel van automatisering.

Cijfers, vijf maanden later

De agent handelt 1.820 omboekings- en informatieverzoeken per week af. Daarvan wordt 62% opgelost zonder dat een mens de call ooit aanraakt — naamcorrecties, opzoeken van reisbescheiden, bagage-upgrades, check-in-vragen op de vertrekdag, voucherstatus-checks. 26% gaat naar de back office-wachtrij voor afhandeling de volgende ochtend (wijzigingen meer dan 24 uur vooruit, restitutiebeslissingen, groepsboekingen). 12% landt binnen het 60-seconden-venster in de duty-manager-wachtrij.

De 23:00-deadline is in tweeëntwintig operationele weken één keer gemist. Eén keer, op een avond waarop een staking van de luchtverkeersleiding op Schiphol 84 tickets opstapelde en de duty managers een extra uur nodig hadden dat ze niet hadden. Het bureau heeft inmiddels gedocumenteerd beleid voor het uitroepen van een "incident-avond" en het rapporteren de volgende ochtend onder een andere SGR-clausule. Dat beleid bestond vóór maart niet, omdat het probleem nog nooit duidelijk genoeg gekwantificeerd was om het de moeite waard te maken op te schrijven.

De gemiddelde handelingsduur voor calls die zonder mens worden opgelost is 2 minuten 11 seconden. Het oude telefoonkeuzemenu van het bureau, als de duty manager opnam, kwam gemiddeld uit op 4 minuten 30 seconden. De agent is niet sneller dan een goede mens. Hij is sneller dan een moede mens om 22:30, en om 22:30 is er geen aflossing.

Wat we anders zouden doen

Eén ding. We bouwden het lees-pad van de agent tegen Galileo door Smartpoint te scripten via een Windows-VM, omdat het API-niveau niet beschikbaar was. Het werkt. Het is ook het meest fragiele deel van het systeem. Elke keer dat Travelport een Smartpoint-update uitrolt, houden we onze adem in. Bouw je voice agents tegen een GDS, regel dan vóór je begint het API-niveau. De kosten van dat niveau zijn lager dan de kosten van één zondagavond opnieuw XPath-selectors vastpinnen.

Toen we deze agent bouwden voor de Maastrichtse reisorganisatie, liepen we vooral aan tegen het feit dat niet de klanten het probleem waren. De legacy stack was ook niet het probleem. Het probleem was het ontwerpen van een handoff die de duty manager om 22:50 op een dinsdag écht vertrouwde. We losten het op door de duty-manager-kaart terug te brengen tot één actie en één telefoonnummer. Scope je een voice agent voor een operations-zwaar bedrijf, begin dan daar.

Besteed morgenochtend twintig minuten aan het écht meten van de na-sluitingstijd-calls van je duty manager. Niet schatten. Meten. Het gat tussen wat je operations-team denkt dat de wachtrij is en hoe hij er werkelijk uitziet, is waar de agent in past.

Kern

Bouw voice agents tegen de legacy stack die je werkelijk hebt, en zet een mens tussen de agent en elke onomkeerbare actie.

FAQ

Waarom niet eerst SQL Server 2012 upgraden?

Omdat het na-sluitingstijd-telefoonprobleem de duty managers elke avond uitputte en de migratie van SQL Server een traject van vier maanden is. We hebben het urgente probleem opgelost tegen de stack zoals die nu is. De migratie staat op de roadmap.

Hoe weet de agent dat een vertrek binnen 24 uur valt?

Hij leest het vertrektijdstip uit de pakketreis-record in SQL Server, of uit de Galileo PNR bij losse vluchtboekingen, en vergelijkt dat met de starttijd van de call. De 24-uursregel is hard-coded routinglogica, geen modelinschatting.

Wat voorkomt dat de agent een PNR verkeerd verstaat en de verkeerde boeking routeert?

Hij herhaalt elk PNR terug in NATO-stijl (letters en cijfers) en gaat alleen verder bij expliciete bevestiging van de beller. Twee mislukte bevestigingspogingen routen de call direct door naar een mens, zonder dat er een wijziging is geprobeerd.

Kan hij Nederlands, Duits en Engels in dezelfde call aan?

Ja. Taaldetectie draait bij elke uiting en de TTS-stem schakelt per beurt mee. De meeste bellers blijven in één taal, maar Limburgse reizigers wisselen soms midden in een zin tussen Nederlands en Duits, en de agent volgt.

voice agentscase studylegacy sitesintegrationsoperationsautomation

Iets bouwen?

Start een project