Voice agent met Claude Code en ElevenLabs: volledige build
De agent beantwoordde de testoproep met mijn eigen stem en deed vervolgens iets wat ik niet had verwacht. Het pauzeerde. Lang genoeg dat ik bijna sprak. Toen werd er zachtjes gevraagd naar de spelling van de bedrijfsnaam die ik zojuist had gezegd. Niet de e-mail. Het bedrijf. Omdat ik twee minuten eerder tegen Claude Code had gezegd dat hij de agent niet langer naar eigennamen moest laten raden, en Claude Code stilletjes een regel aan de systeemprompt had toegevoegd die de agent ertoe aanzette om er elke keer om te vragen.
Die ene pauze is het moment waarop ik dit ding niet meer als een script zag, maar het als een werknemer begon te behandelen.
Ik had de middag ervoor een complete voice agent gebouwd met Claude Code als het orkestratiebrein, ElevenLabs als de stem- en gespreksengine en Cal.com als de boekingsbackend. Geen lijmservice. Nee Maak scenario's. Geen Zapier in het midden. Slechts drie API's, één .env-bestand, een widget-fragment op een landingspagina en Claude Code die de documenten voor mij voorleest terwijl ik in gewoon Engels beschreef wat ik wilde.
Uiteindelijk had ik een verkoopagent die in een gekloonde versie van mijn eigen stem kon antwoorden, een prospect in vijf velden kon kwalificeren, mijn agenda in Central Time kon bekijken, een ontdekkingsgesprek van 30 minuten kon boeken en de bevestigingsmail kon sturen - allemaal vanuit een telefoonvormige bubbel in de hoek van een website. De eerste versie ervan werd op vijf verschillende manieren verbroken. De vijfde versie ervan werkt. Dit bericht is het volledige overzicht van hoe een echte voice agent-build eruit ziet in 2026 – inclusief de bugs, de kredietwiskunde en de beveiligingslekken die ik bijna had verzonden.
Waarom ik niet meer dacht aan stemagenten als iets van de toekomst
Twee jaar lang had ik voice agent's behandeld als een probleem van morgen. De demo's waren indrukwekkend op het podium en raar in de productie. Robotachtige cadans. Gehallucineerde beschikbaarheid. Het soort 'druk op één voor verkoop'-energie waardoor mensen vóór de tweede prompt ophangen.
Dat veranderde stilletjes. Drie dingen tegelijk op een rij. ElevenLabs Agents is uitgegroeid tot een echt product: spraakklonen die de griezelige vallei doorkruist met Professioneel stemklonen met meer dan 30 minuten audio, conversatielatentie die niet langer aanvoelt als satellietvertraging, en facturering per minuut die daadwerkelijk aansluit bij een businesscase. Cal.com heeft een schone v2 API verzonden waarbij voor het maken van een boeking geen verificatie vereist is en de beschikbaarheid van slots één GET is. En Claude Code leerde een API-documentatiepagina van derden lezen, stelde me drie scherpe vragen en schreef de integratiecode zonder dat ik VS Code verliet.
Dat laatste deel is het ontgrendelen. De technische kennis die nodig was om ElevenLabs aan te sluiten op Cal.com was vroeger het knelpunt. Het knelpunt is nu weten wat u wilt dat de agent doet.
Kijk – ik verkoop je geen visie waarin de stem mensen vervangt. Ik verkoop u een enkelvoudig gebruiksscenario waarbij de wiskunde zo helder is dat het zonde zou zijn om deze niet te verzenden: een agent die uw inkomende siteverkeer op zondag om 23.00 uur beantwoordt, de lead kwalificeert en de vergadering in uw echte agenda boekt voordat de bezoeker het tabblad sluit. Dat is wat ik heb gebouwd. Dat is waar ik je doorheen ga leiden.
Maar voordat we aan de bouw beginnen, moet je iets begrijpen dat de meeste tutorials overslaan. Een voice agent is niet één ding. Het zijn vier dingen die aan elkaar zijn genaaid - en als je de vier delen niet begrijpt, voelt het bouwen als tovenarij en het debuggen als gissen.
De vier onderdelen van elke stemagent
Elke voice agent op de markt – die van jou, de mijne, degene die de telefoonboom van je bank wenst – is een combinatie van vier componenten. Als je één van deze dingen fout doet, stort de hele zaak in. Als je ze alle vier goed hebt, voelt de agent zich als een collega.
Persona is de systeemprompt. Toon, stijl, woordenschat, wat de agent wel en niet zal zeggen, hoe hij met bezwaren omgaat, wat hij doet als hij geen antwoord weet. Dit is het onderdeel waar de meeste builds beschamend fout gaan. Ze plakken 'Je bent een behulpzame assistent' in en vragen zich af waarom de agent klinkt als elke andere AI op internet. De persona is waar jouw merk leeft. Het is het verschil tussen een agent die zegt: "Ik help je graag" en een agent die zegt: "Laat me door wat je probeert op te lossen en ik zal kijken of we bij elkaar passen."
Stem is de synthetische stem die de audio aanstuurt. ElevenLabs geeft je drie echte opties: een standaardstem uit hun bibliotheek, een Instant Voice Clone opgebouwd uit één tot vijf minuten zuivere audio, of een Professional Voice Clone opgebouwd uit minimaal 30 minuten en idealiter meerdere uren bronmateriaal. Ik ging met een Professional Voice Clone die getraind was op ongeveer vier uur van mijn eigen stem: oude podcastafleveringen, schermopnames, gesproken tutorials. Het getal van vier uur is niet willekeurig. Na ongeveer twee uur pikt het model cadans- en ademhalingspatronen op die klonen van één uur missen. De afgelopen vier uur vlakten de rendementen hard af. Het heeft geen zin om er twintig te geven.
Kennisbasis is wat de agent weet. De mijne was elk transcript van mijn YouTube-kanaal, plus een gestructureerd document waarin mijn diensten, prijzen en het soort projecten dat ik aanneem, worden beschreven. ElevenLabs neemt deze op als RAG-documenten die aan de agent zijn gekoppeld. De agent kan eruit citeren, ze samenvatten, en weigeren vragen buiten hen te beantwoorden. Voor een verkoopagent is de kennisbank grotendeels uw eigen pitch; voor een ondersteuningsagent zijn dit de productdocumentatie.
Tools zijn de dingen die de agent daadwerkelijk kan doen. Dit is waar de meeste demo-agenten op hun gezicht vallen. Ze kunnen praten. Ze kunnen niet handelen. Aan een echte agent zijn tools gekoppeld: een Cal.com-boekingseindpunt, een CRM-webhook, een GitHub-opslagplaatszoekopdracht, een MCP-server, een Python-script dat een klantendatabase bevraagt, een Zapier-webhook die de volgende stap in een workflow activeert. Het zijn de tools die de agent nuttig maken in plaats van theatraal.
De build waar ik doorheen loop, gebruikt alle vier. Persona is een warme professionele B2B-verkoopstem. Stem is mijn eigen kloon. De kennisbank is mijn YouTube-transcripties en -servicedocument. Er zijn twee hulpmiddelen: de beschikbaarheid van Cal.com-slots en het maken van Cal.com-boekingen, rechtstreeks getroffen door de v2 API.
Dat is de architectuur. Dit is wat er feitelijk nodig was om het te bouwen.
De installatie voordat Claude Code iets raakt
Ik begon in VS Code met een kleine Next.js-bestemmingspagina die al op localhost:3000 draaide. Niets bijzonders: een heldensectie, een CTA-knop, een lege div waar de stem widget uiteindelijk zou verschijnen. De pagina bestond omdat ik wilde dat Claude Code een echte plek had om de widget neer te zetten zodra we daar aankwamen. Het bouwen van een voice agent zonder hostpagina is als het geluiddicht maken van een kamer voordat je de muren bouwt.
Ik heb de Claude Code-extensie geopend in VS Code. Als je het nog niet eerder in de IDE hebt gebruikt, is de ervaring op één belangrijke manier anders dan die in de terminal: Claude Code kan je bestandsboom zien, bestaande code lezen en rechtstreeks in het project schrijven zonder dat je iets hoeft te kopiëren en plakken. De extensie is de aanbevolen manier om Claude Code binnen VS Code te gebruiken, en voor een build als deze verdient de side-by-side diff-weergave zijn waarde binnen de eerste tien minuten.
Vervolgens typte ik een alinea in Claude Code. Grofweg:
Ik wil een stemverkoopagent voor mijn website bouwen. Het moet vragen over mijn diensten beantwoorden, de lead kwalificeren door te vragen naar de volledige naam, e-mailadres, bedrijfsnaam, het probleem dat ze proberen op te lossen en de teamgrootte, en vervolgens een ontdekkingsgesprek van 30 minuten boeken in mijn Cal.com-agenda. De stem zou mijn Professional Voice Clone in ElevenLabs moeten zijn. Ik geef je de stem-ID. De toon moet warm maar professioneel zijn, B2B-verkoop, geen enthousiasme-fake, geen AI-clichétaal. Laten we beginnen met dat je me alles vraagt wat je wilt weten.
Claude Code is niet begonnen met coderen. Er werden vijf vragen gesteld in één bericht. Wat is mijn Cal.com-gebeurtenistype slug? In welke tijdzone wil ik beschikbaarheid? Wil ik een specifiek werktijdenvenster of gebruik ik de standaardkalender? Wat moet de agent doen als de bezoeker buiten mijn openingstijden wil boeken? Heb ik een ElevenLabs API-sleutel en een Cal.com API-sleutel, of moet ik hiermee helpen deze te genereren?
Dit is het deel dat er stilletjes toe doet. Een junior ontwikkelaar zou onmiddellijk zijn begonnen met het schrijven van code en een uur bezig zijn geweest met het herschrijven van de kwalificatiestroom toen ik hem halverwege vertelde dat ik de bedrijfsgrootte als numeriek bereik nodig had, en niet een vrij tekstveld. Claude Code vroeg eerst.
antwoordde ik. Het gebeurtenistype Cal.com was discovery-call-30. Tijdzone Central Time. Werktijden van 9.00 tot 21.00 uur op weekdagen. Bied buiten de openingstijden het eerstvolgende beschikbare slot aan. Ik had beide API-sleutels bij de hand. Vervolgens schreef Claude Code een plan als een afwaarderingsbestand en liet het in de repository vallen. Het plan vermeldde elk bestand dat het zou maken, elke API-aanroep die het zou doen, elke omgevingsvariabele die het nodig had en de volgorde waarin het zou worden ingebouwd. Ik las het plan, vroeg om één wijziging: sla de kwalificatie-antwoorden op als een gestructureerd JSON-object dat vóór de boeking naar een webhook wordt gestuurd, zodat ik leads later naar mijn CRM kan doorsturen - en gaf groen licht.
De bouw, in de volgorde waarin het feitelijk gebeurde
Dit is waar de meeste tutorials met de hand zwaaien. Ze zeggen "Claude Code heeft de integratie gegenereerd" en gaan naar de demo. Ik wil je de daadwerkelijke volgorde geven, omdat de volgorde ervoor zorgt dat de iteratielus werkt.
Eerst het .env-bestand. Claude Code heeft .env.local gemaakt met drie variabelen weggelaten: ELEVENLABS_API_KEY, CAL_COM_API_KEY, ELEVENLABS_AGENT_ID is voorlopig leeg gelaten. Het voegde ook .env.local toe aan .gitignore zonder dat ik erom vroeg. Kleinigheidje, maar elke keer als een LLM zich zonder enige waarschuwing de basisveiligheidshygiëne herinnert, merk ik het.
Ten tweede de ElevenLabs-agent zelf. Claude Code drukt op ElevenLabs Agents API om een nieuwe agent te maken — programmatisch, niet via het dashboard. De create-agent-aanroep accepteert een JSON-hoofdtekst met de systeemprompt, stem-ID, kennisbankdocument-ID's en tooldefinities. Claude Code schreef de systeemprompt als een afzonderlijk markdown-bestand (prompts/sales-agent-system.md), zodat ik er in versiebeheer op kon herhalen. Zo zag het eerste concept er ongeveer uit:
You are a sales voice agent for Mejba, a software engineer who builds AI
systems, automates workflows, and ships custom Claude Code integrations.
# Goal
Qualify the prospect. Answer their questions about Mejba's services. If they
seem like a fit, book a 30-minute discovery call on Mejba's calendar.
# Voice & Tone
- Warm but professional. B2B sales, not retail support.
- Never use the words "absolutely", "amazing", "I'd be happy to", or any
variation that signals AI-cliche language.
- Speak in short sentences. Pause after asking a question.
- If the prospect goes on a tangent, listen. Do not interrupt to redirect.
# Qualification Fields (collect in this order, naturally)
1. Full name (ask them to spell the last name back if uncertain)
2. Email (read it back to confirm)
3. Company name (ask for the spelling, every time)
4. The problem they're trying to solve, in their own words
5. Team size (ask for an approximate number of people)
# Booking
- Once qualified, offer the next three available 30-minute slots from
Cal.com via the get_available_slots tool.
- Confirm the slot in Central Time before calling create_booking.
- After booking, confirm the email confirmation will arrive within minutes.
# Boundaries
- Do not quote prices. Tell the prospect Mejba reviews scope before quoting.
- Do not promise specific delivery timelines.
- If asked something you don't know, say so plainly and offer to follow up.
Die prompt werd vier keer herschreven voordat de agent het goed vond. Op de herschrijvingen kom ik in de volgende paragraaf terug. Maar de structuur – rol, doel, stem, kwalificatie, boeking, grenzen – zijn de botten. Elke voice agent-systeemprompt die ik schrijf, volgt nu exact de vorm van zes secties.
Ten derde de tools. Claude Code heeft twee aangepaste tools op de agent gedefinieerd. get_available_slots accepteert een datumbereik en een tijdzone, raakt het /v2/slots-eindpunt van Cal.com en retourneert een lijst met beschikbare vensters van 30 minuten. create_booking accepteert de naam van de deelnemer, het e-mailadres, de kwalificatievelden als metagegevens en een gekozen slot, en raakt het /v2/bookings-eindpunt van Cal.com. Beide tools leven als serverloze functies in de Next.js-app onder app/api/. De ElevenLabs-agent roept deze eindpunten aan via webhooktools. Dit betekent dat ElevenLabs een HTTPS POST naar mijn eindpunt stuurt, mijn eindpunt Cal.com raakt en het antwoord terugvloeit via de agent.
De reden voor de indirecte actie (agent belt mijn server, mijn server roept Cal.com aan) is van cruciaal belang en de moeite waard om te vertragen. Als u de Cal.com API-sleutel rechtstreeks in de ElevenLabs-toolconfiguratie plaatst, bevindt die sleutel zich in de agentdefinitie. Iedereen die de agentconfiguratie kan zien, kan de sleutel zien. Door via mijn eigen eindpunten te routeren, leeft de Cal.com-sleutel alleen in .env.local op Vercel. De agent heeft geen eigen referenties. Het praat alleen met mijn webhook. Dit patroon verschijnt opnieuw in het beveiligingsgedeelte, maar het begint hier.
Ten vierde, de widget. Zodra de agent-ID terugkwam van de ElevenLabs API, plaatste Claude Code het insluitingsfragment op de landingspagina. Het fragment ziet er ongeveer zo uit:
<elevenlabs-convai
agent-id="agent_xxxxxxxxxxxxxxxxxxxxx"
></elevenlabs-convai>
<script
src="https://unpkg.com/@elevenlabs/convai-widget-embed"
async
type="text/javascript"
></script>
Twee labels. Dat is de gehele oppervlakte aan de cliëntzijde. De widget heeft een zwevende telefoonpictogramknop in de benedenhoek van de pagina. Klik erop en er begint een realtime spraakgesprek. Al het andere – de kwalificatiestroom, de kalenderlogica, de boeking – draait op de server of in het brein van de agent.
Ik druk op opslaan. Vernieuwd localhost:3000. De telefoonbel verscheen. Ik heb erop geklikt. En toen begonnen de bugs.
Vijf dingen gingen kapot. Dit is wat iedereen mij heeft geleerd.
Dit is de sectie die ik wenste dat elke voice agent-tutorial had. Omdat het bouwen het gemakkelijke gedeelte is. Tijdens het eerste gesprek leert u wat uw agent eigenlijk is.
Bug één: de agent zei niets toen het gesprek begon. Ik klikte op het telefoonpictogram, de verbinding werd geopend en toen was er stilte. De agent wachtte op mij. Als een ongemakkelijk Zoom-gesprek. ElevenLabs Agents heeft een first_message-veld in de agentconfiguratie - een letterlijke tekenreeks die de agent uitspreekt op het moment dat een sessie wordt geopend - en Claude Code had het leeg gelaten omdat ik er geen had opgegeven in mijn opdracht. Ik zei tegen Claude Code: "Stel het eerste bericht in als: Hé, dit is Mejba's AI-assistent - waar denk je aan?" Claude Code heeft de agentconfiguratie bijgewerkt via API, opnieuw implementeren is niet nodig. Het volgende gesprek begon met een warme groet.
Bug twee: de stem klopte niet. Technisch gezien niet verkeerd: het was absoluut mijn voice clone. Maar de cadans was dat wat elke Instant Voice Clone doet, waarbij elke zin eindigt met een licht opwaartse toon, alsof de agent door elk woord heen lacht. Het klonk als een opname van de klantenondersteuning. Voor een B2B-verkoopagent was die energie weg. Te gretig. Een beetje nep.
De oplossing zat in de steminstellingen, niet in de prompt. ElevenLabs geeft je vier schuifregelaars die er toe doen: snelheid, stabiliteit, gelijkenis en stijloverdrijving. Ik liet Claude Code de agentconfiguratie openen en de steminstellingen verschuiven: stabiliteit tot 0,75 (meer consistente, minder expressieve variatie), gelijkenis tot 0,85 (dichter bij de bronopnames), stijloverdrijving tot 0,3 (minder performatief). Ik heb één regel aan de systeemprompt toegevoegd: 'Spreek op een rustige, afgemeten toon. Je verkoopt niet. Je luistert.' Het volgende testoproep klonk als een echt persoon die praatte: langzamer, bedachtzamer, zonder doorlachen. Die ene combinatie van slider-tuning plus tooninstructie bleek de grootste kwaliteitshefboom in de hele build.
Bug drie: de tijdzone klopte niet. Het kostte een uur om deze te vinden. Ik vroeg de agent om de beschikbaarheid voor 'morgenmiddag' te controleren. De agent zei dat het vroegste tijdstip 18.00 uur was. Mijn agenda stond eigenlijk om 11.00 uur wagenwijd open. Ik ging ervan uit dat Cal.com kapot was. Dat was het niet. Cal.com's v2 slots endpoint vereist de tijdparameters in UTC, maar accepteert een timeZone-parameter voor uitvoeropmaak. Claude Code had het verzoek correct aangesloten in UTC, maar had de parameter timeZone niet ingesteld op het antwoord, dus de agent las slottijden terug in UTC en kondigde deze aan als Central Time. 11.00 uur Centraal in UTC is 16.00 uur. Voeg Cal.com's minimale opzegtermijn van twee uur toe en het vroegste tijdsbestek dat de agent kon zien, sprong naar 18.00 uur.
De oplossing bestond uit vier regels code. Claude Code heeft timeZone=America/Chicago toegevoegd aan de slotsquery, het time-veld van het antwoord geparseerd (dat nu al geconverteerd terugkwam) en de systeemprompt bijgewerkt met de tekst "Lees altijd tijden voor de prospect in Central Time." Toen hebben we getest. 11.00 uur kwam opdagen. De agent zei: "Ik heb morgen 11.00 uur Central." Ik slaakte een kleine, hoorbare zucht van verlichting.
Als je je niets anders herinnert van dit hele bericht, onthoud dan dit: wanneer een LLM-gestuurde agent iets raars doet met de tijd, is het bijna altijd een tijdzonefout, en bijna nooit de schuld van het model.
Bug vier: de e-mail was verkeerd opgemaakt en de bedrijfsnaam was verkeerd gespeld. Ik testte het boekingsproces door mijn e-mail hardop uit te spreken: "mejba dot one three at gmail dot com." De agent bevestigde terug "M-E-G-B-A op gmail dot com." Fout. Bij stemtranscriptie worden M-E-J regelmatig verward met M-E-G als er geen woordenboekcontext is. Hetzelfde probleem met bedrijfsnamen. De agent kon niet weten of ik 'Acme Inc' of 'Acne Inc.' had gezegd.
De oplossing was op promptniveau, niet op codeniveau. Ik vroeg Claude Code om dit blok aan de systeemprompt toe te voegen:
# Spelling Discipline
For any proper noun the prospect provides — full name, email, company —
do NOT trust your transcription. Always:
1. Repeat the value back, letter by letter for short tokens (names, the
local part of an email, company names under 8 characters).
2. For longer values, repeat back and ask: "Did I get the spelling right?"
3. For email addresses, separate the local part and the domain when
reading back: "M-E-J-B-A dot one-three, at G-mail dot com — correct?"
4. If the prospect corrects you, accept the correction and read the new
spelling back one more time before moving on.
Bij het volgende testoproep zei ik "mejba dot one three at gmail dot com." De agent wachtte even en las het vervolgens letter voor letter voor. Ik bevestigde. Boeking verliep vlekkeloos. Dit is de pauze waarmee dit artikel werd geopend. Het is ook het soort gedragsverandering dat bijna gratis kan worden toegevoegd en dat de waargenomen intelligentie van de agent dramatisch verhoogt.
Bug vijf: Cal.com weigerde te boeken "op welk moment dan ook in de komende twee uur." De agent bleef maar zeggen dat het vroegste tijdslot twee en een half uur later was, zelfs op een duidelijk open kalender. Dit was geen bug. Cal.com hanteert een standaard minimale opzegtermijn van 120 minuten voor gebeurtenistypen – een instelling die is ontworpen om mensen te beschermen tegen het per ongeluk boeken van zichzelf voor iets over drie minuten. Ik ging naar de Cal.com-instellingen voor het gebeurtenistype, verlaagde de minimale kennisgeving naar 30 minuten en testte opnieuw. De agent bood nu slots aan vanaf 35 minuten. Het kennen van het standaardbeleid van het platform maakt deel uit van de integratie ermee. Claude Code heeft die 120-minutenregel niet uitgevonden; Cal.com deed dat. Maar Claude Code kon ook niet weten dat ik het wilde overschrijven, omdat ik het niet had verteld.
Vijf bugs. Vijf oplossingen. Totale tijd om alle vijf te debuggen: ongeveer negentig minuten, waarbij Claude Code elke keer de relevante documentenpagina las en de oplossing voorstelde voordat ik klaar was met het lezen van de fout.
Middenbouw opzij
Als je liever hebt dat iemand een voice agent zoals deze end-to-end op je stack bouwt - voice clone, systeemprompt, Cal.com of HubSpot of welke boekingsbackend je ook gebruikt, hostnaamvergrendeling, de hele kit - dat is precies het soort project dat ik aanneem. Je kunt zien wat ik heb gebouwd en een gesprek boeken op fiverr.com/s/EgxYmWD.
Beveiliging: het gesprek dat bijna niet heeft plaatsgevonden
Ik had dit ding bijna verzonden zonder aan de beveiliging te denken. De widget werkte. De kalender werkte. Ik had mijn vinger op de uitrolknop.
Toen zei een klein, nuttig stemmetje in mijn achterhoofd: iedereen met een browser kan deze site openen, op de widget klikken en beginnen met het verbranden van mijn ElevenLabs-credits.
Spraakagenten zijn niet zoals tekstchatbots. Elke minuut gesprek kost echt geld. ElevenLabs Agents factureert per gespreksminuut, tussen $ 0,08 en $ 0,12, afhankelijk van het niveau, los van het tekenquotum van uw basisabonnement. Een beledigend telefoontje van een uur kost ongeveer $ 5 tot $ 7. Een botnet dat elke avond tien parallelle oproepen van een uur uitvoert, is het soort rekening dat een dinsdagochtend verpest.
Daarom heb ik Claude Code vier beveiligingslagen laten toevoegen voordat het werd geïmplementeerd.
Toelaatbare lijst met hostnamen. Het agentplatform van ElevenLabs ondersteunt een hostname allowlist op het tabblad Beveiliging — u geeft maximaal tien domeinen op, en elke widget-verbinding van een domein dat niet op die lijst staat, wordt afgewezen bij de WebSocket-handshake. Ik heb mejba.me, www.mejba.me en localhost:3000 toegevoegd. Iedereen die mijn widget-fragment naar zijn eigen site kopieert, kan mijn agent niet gebruiken.
Maximale gespreksduur. Ik heb elk gesprek beperkt tot 8 minuten. Als een echte prospect meer tijd nodig heeft, moeten ze een Zoom-gesprek met mij voeren en geen misbruik maken van mijn stembot. Acht minuten is genoeg om je te kwalificeren en te boeken. Het betekent ook dat het absoluut slechtste geval voor een misbruiker ongeveer $ 0,96 per sessie bedraagt.
Per-IP-snelheidslimiet. Claude Code heeft een kleine Vercel Edge-functie toegevoegd vóór de widget die verbindingen per IP beperkt. Drie sessies per uur. De tiende sessie in een uur krijgt een 429. Ik heb dit tarief niet bedacht. Ik vroeg Claude Code om nummers te kiezen die voor de hand liggende automatisering blokkeren, zonder een echte gebruiker af te wijzen die ophing en terugbelde.
Auth-gated escalatie. Voor de eerste versie heb ik de widget openbaar gelaten: een verkoopagent waarvoor inloggen vereist is, is een verkoopagent met wie niemand praat. Maar Claude Code schreef een feature flag voor signed URLs (de aanbevolen standaard volgens de ElevenLabs auth-documenten), zodat ik de agent binnen 30 seconden naar de geverifieerde modus kan schakelen als ik misbruik zie. Ondertekende URL's vereisen een token aan de serverzijde voordat de agent een verbinding accepteert. Als u een intern gerichte agent beheert (helpdesk voor medewerkers, partnerportal), begin dan met signed URLs en kijk nooit meer achterom.
Ik hou niet van de beveiligingscalculus op openbare voice agent's. De economie maakt misbruik triviaal eenvoudig en verdediging irritant gelaagd. Maar de vier bovenstaande controles brengen de dagelijkse schade in het ergste geval van ‘potentieel grenzeloos’ naar ‘irritant maar beperkt’. Dat is de grens die u moet overschrijden voordat u een voice agent op een openbaar domein plaatst.
De kostenwiskunde, eerlijk gezegd
Bij de meeste tutorials wordt de rekening overgeslagen. Dat ga ik niet doen. Dit is wat het runnen van deze agent feitelijk kost vanaf mei 2026.
De installatie van stemklonen is eenmalig. Professioneel stemklonen is inbegrepen bij het ElevenLabs Creator-abonnement ($22/month) en hoger. De vier uur aan bronaudio die ik heb geüpload, is één keer verwerkt. De kloon zelf kost geen doorlopend geld; alleen de gesynthetiseerde output doet dat.
Agentgesprekken worden per minuut in rekening gebracht. ElevenLabs Agents kost $ 0,08 per minuut op het standaardniveau en maximaal $ 0,12 per minuut op het premiumniveau (dat een duurdere LLM en de Flash voice model gebruikt). Mijn agent draait op het standaardniveau. Een typisch verkoopgesprek duurt vier tot zes minuten, bijvoorbeeld € 0,32 tot € 0,48 per gekwalificeerd gesprek.
Credits blijven twee maanden geldig bij betaalde abonnementen. Ongebruikte credits worden niet eeuwig opgestapeld. Plan uw maandelijkse verbranding op basis van het werkelijk verwachte verkeer, en niet op basis van uw wildste groeifantasie.
Cal.com is gratis op mijn volume. De gratis laag geldt voor één gebruiker met een gebeurtenistype van 30 minuten en directe API-toegang. Als je teamplanning of round-robin-opdrachten nodig hebt, is dat een betaald niveau, maar voor een solo-operator nul.
Vercel is gratis op mijn volume. Het hobbyniveau verzorgt de landingspagina en de twee API-routes die zonder moeite naar Cal.com verwijzen.
De lopende kosten voor een versie met weinig verkeer van deze agent bedragen dus ongeveer $ 22/month op ElevenLabs (Creator-abonnement, inclusief professioneel stemklonen) plus gesprekskosten per minuut. Als de agent tien gesprekken per dag van elk vijf minuten afhandelt, komt dat neer op ongeveer vijftig minuten per dag, of €4 per dag, of ongeveer €120/month aan gesprekskosten. Totaal: ongeveer $ 142/month voor een volledig werkende verkoopagent die vergaderingen in uw slaap boekt.
Ter vergelijking: een parttime menselijke BDR – iemand die inkomende gesprekken beantwoordt en leads kwalificeert – kost u ongeveer €3.000 tot €5.000 per maand en werkt niet in het weekend. De agent vervangt geen goede BDR. Het vangt de oproepen op die anders op de voicemail terecht zouden komen en in de leegte zouden lekken.
Implementeer het waar echte bezoekers het kunnen vinden
Toen localhost:3000 niet meer kapot ging, werd het implementeren bijna saai.
GitHub-synchronisatie. Claude Code initialiseerde een git-repository als deze niet bestond, creëerde een privé GitHub-repository via de gh CLI en pushte de code. .env.local bleef lokaal en raakte nooit de afstandsbediening aan. Omgevingsvariabelen voor productie leefden alleen in het dashboard van Vercel.
Vercel implement. Verbond de GitHub-repository met een nieuw Vercel-project, voegde de drie omgevingsvariabelen (ELEVENLABS_API_KEY, CAL_COM_API_KEY, ELEVENLABS_AGENT_ID) toe aan de projectinstellingen van Vercel en klikte op implementeren. Twee minuten later was de site live op een vercel.app-subdomein. Vervolgens heb ik voice.mejba.me naar de implementatie via DNS verwezen. Totale inzettijd: ongeveer zes minuten.
Twilio voor telefoon. Dit is het onderdeel dat ik nog niet naar productie heb verzonden, maar de architectuur is aanwezig. ElevenLabs Agents ondersteunt standaard Twilio-telefoonnummerintegratie. U koopt een nummer, plakt dit in het tabblad "Telefoonnummers" van de ElevenLabs-agent, en dezelfde agent die uw widget beantwoordt, beantwoordt nu de daadwerkelijke telefoontjes. Zelfde persoonlijkheid. Dezelfde stem. Hetzelfde gereedschap. Dezelfde Cal.com-integratie. Het maakt de agent niet uit of de audio afkomstig is van een browsermicrofoon of een telefoonlijn. Dat is het onderdeel waar ik steeds op terugkom als datgene dat stilletjes de business case verandert: één agent, drie oppervlakken (widget, dashboard, telefoon), één prompt, één kennisbank.
Als u al een MCP-gestuurde Claude Code-workflow hebt opgebouwd, vraagt u zich misschien af waar MCP in deze build past. Het korte antwoord is: dat is nog niet het geval, maar het langere antwoord is dat dezelfde patronen die ik heb doorlopen in mijn overzicht van de must-have MCP's voor Claude Code rechtstreeks van toepassing zijn op voice agent's op het moment dat u wilt dat de agent een database doorzoekt, uw Notion leest of een klantrecord ophaalt. Tegenwoordig loopt dat allemaal via mijn webhooks aan de serverzijde. Morgen laat ElevenLabs' MCP integration de agent deze servers rechtstreeks aanroepen met de juiste authenticatie. De architectuur convergeert.
De iteratielus is de vaardigheid
Dit is het gedeelte dat ik wil onderstrepen voordat u dit tabblad sluit. Het bouwen was niet het moeilijkste deel. Claude Code heeft de build uitgevoerd. Iedereen met twee API-sleutels en een duidelijke opdracht had dezelfde eerste versie kunnen maken.
De vaardigheid – de feitelijk overdraagbare vaardigheid – is de iteratielus. De vijf bugs die ik hierboven heb beschreven, zijn niet de fouten van Claude Code. Ze vormen de natuurlijke wrijving bij het inpassen van een generalistische LLM-agent in een specifieke zakelijke context. Elke bugfix nam de vorm aan: merk het verkeerde gedrag op, beschrijf het nauwkeurig aan Claude Code, laat Claude Code de oplossing voorstellen, controleer de oplossing, implementeer en test opnieuw. Vijf ronden van die lus veranderden een agent die onhandig pauzeerde tijdens het openen van het gesprek en mijn e-mail verkeerd spelde in een agent die echte vergaderingen boekt in echte agenda's.
Dit is dezelfde iteratielus waar ik al maanden over schrijf - degene waarbij de waarde beweegt van "kan de AI het doen" naar "kan de mens snel genoeg ontdekken wat er mis is om de volgende verandering te sturen." Ik ging dieper in op deze exacte dynamiek in waarom de context de configuratie verslaat als je agenten bouwt, en de lessen daar speelden slag voor slag in deze voice agent-build. Elke snelle wijziging die ik aanbracht was een contextfix, geen modelupgrade.
De voice agent's die in 2026 in productie werken, zijn niet degenen met de beste voice clone of de schoonste integratiecode. Zij zijn degenen wiens bouwers de iteratielus vijftien keer hebben uitgevoerd voordat ze live gingen. De meeste bouwers stopten om drie uur.
Veelgestelde vragen
Hoeveel kost het om een voice agent te bouwen en uit te voeren met ElevenLabs en Claude Code?
Verwacht in totaal ongeveer $ 142/month voor productie met weinig verkeer: $ 22/month voor het ElevenLabs Creator-abonnement (dat Professional Voice Cloning ontgrendelt), plus ongeveer $ 0,08 per gespreksminuut, plus gratis niveaus op Cal.com en Vercel. Een solo-operator die tien gekwalificeerde gesprekken per dag afhandelt van elk vijf minuten, komt neer op bijna €4/day aan gesprekskosten.
Hoeveel audio heb ik nodig om mijn stem te klonen voor een ElevenLabs-agent?
ElevenLabs Voor professioneel stemklonen is minimaal 30 minuten nodig, maar de kwaliteit springt merkbaar tussen twee en vier uur schone bronaudio. Ik gebruikte vier uur en zag de cadans en ademhalingspatronen in elkaar grijpen. De afgelopen vier uur werden de rendementen vlakker. Voor Instant Voice Cloning is één tot vijf minuten voldoende, maar het resultaat is merkbaar minder natuurlijk voor gesprekken op verkoopniveau.
Kan dezelfde ElevenLabs-agent telefoontjes en de website widget beantwoorden?
Ja. ElevenLabs Agents ondersteunt Twilio-telefoonintegratie in dezelfde agentconfiguratie die de website widget aanstuurt. Eén persona, één stem, één kennisbank, één set tools: drie oppervlakken. U koopt een Twilio-nummer, plakt dit in het tabblad met telefoonnummers van de agent en inkomende oproepen komen terecht in dezelfde gespreksengine die uw widget gebruikt.
Hoe voorkom ik dat willekeurige bezoekers mijn ElevenLabs-credits op de openbare widget verbranden?
Gebruik vier lagen: hostname allowlist op het tabblad Beveiliging van de ElevenLabs-agent (limiet op uw echte domeinen plus localhost), een limiet per gespreksduur (ik gebruik 8 minuten), snelheidslimiet per IP op een Vercel Edge-functie vóór de widget, en een functievlag voor signed URLs als u tijdens een aanval naar de auth-gated modus moet overschakelen. Zie het beveiligingsgedeelte hierboven voor de exacte configuratie.
Waarom leest mijn voice agent kalendertijden in de verkeerde tijdzone?
Dit is bijna altijd een configuratieprobleem met Cal.com /v2/slots. Het eindpunt vereist UTC-tijdparameters bij invoer, maar accepteert een timeZone-parameter voor uitvoeropmaak. Als u vergeet timeZone=America/Chicago (of uw relevante zone) in te stellen op het verzoek, komt het antwoord terug in UTC en leest de agent het alsof het al lokaal is. Corrigeer de verzoekparameter en voeg een systeempromptregel toe die de agent dwingt altijd de tijden in de lokale zone van de prospect te lezen.
Laten we samenwerken
Wilt u AI-systemen bouwen, workflows automatiseren of uw technische infrastructuur schalen? Ik help je graag.
- Fiverr (aangepaste builds en integraties): fiverr.com/s/EgxYmWD
- Portfolio: mejba.me
- Ramlit Limited (ondernemingsoplossingen): ramlit.com
- ColorPark (ontwerp en branding): colorpark.io
- xCyberSecurity (beveiligingsdiensten): xcybersecurity.io