Erstellen Sie in 20 Minuten einen Voice-Agenten mit ElevenLabs und Twilio
- Veröffentlicht
- Zuletzt aktualisiert
AnhörenArtikel anhören
Ein Voice Agent kann eingehende Anrufe entgegennehmen, Anrufer in Echtzeit mit
Für Entwickler besteht der vollständige Stack aus ElevenLabs für Sprachsynthese (Flash v2.5) und Transkription (Scribe v2 Realtime), Twilio für Telefonie und entweder OpenAI oder Anthropic als LLM. Alle Komponenten sind austauschbar, sodass Sie die Bausteine wählen können, mit denen Sie am vertrautesten sind.
Dieser Artikel zeigt, wie Sie in 20 Minuten einen Voice-Agenten bauen – mit Node.js und Typescript. Wenn Sie eine verwaltete Alternative suchen, die Turn-Taking, Unterbrechungen und Telefonie übernimmt, ohne dass Sie die Kaskade selbst pflegen müssen, besuchen Sie ElevenAgents.
So funktioniert die Architektur eines Voice-Agenten
Bevor Sie Code schreiben, ist es hilfreich zu verstehen, wie die drei Dienste in Ihrem Tech-Stack zusammenarbeiten.
- Twilio: Übernimmt den Anruf und den Audio-Transport.
- ElevenLabs: Übernimmt STT mit Scribe v2 Realtime und TTS mit Flash v2.5.
- LLM: Übernimmt Tool-Calls und generiert die Antwort.
Jede Stufe ist ein schlanker Adapter, daher können Sie einzelne Komponenten austauschen, ohne den Rest zu ändern. Zum Beispiel können Sie das OpenAI LLM durch Anthropic ersetzen, ohne andere Komponenten neu zu schreiben.
Ein Anruf erreicht Ihren Server über Twilio. Twilio nimmt den PSTN-Anruf an, öffnet einen WebSocket zu Ihrem Server und leitet das Audio des Anrufers als Stream von base64-kodierten mu-law-Frames weiter. Ihr Server führt die Kaskade aus und streamt synthetisiertes Audio über denselben WebSocket zurück, das Twilio dem Anrufer vorspielt.

So läuft der Aufbau eines Voice-Agenten ab:
Ein Anrufer wählt Ihre Twilio-Nummer. Twilio ruft ein TwiML-Dokument von Ihrem Webhook ab. Das TwiML weist Twilio an, einen Media Stream zu Ihrem WebSocket-Endpunkt zu öffnen. Twilio streamt eingehendes Audio als JSON-Events mit base64 mu-law (ulaw_8000) Payloads.
Ihr Server leitet Audio-Chunks an Scribe v2 Echtzeit zur Echtzeit-Transkription weiter. Wenn ein Anrufer-Turn abgeschlossen ist, senden Sie das Transkript an das LLM und synthetisieren die Antwort mit Flash v2.5 in ulaw_8000. Die synthetisierten mu-law-Frames senden Sie base64-kodiert über den WebSocket zurück an Twilio, das sie dem Anrufer vorspielt.
Scribe v2 Realtime liefert Teiltranskripte mit etwa 150 ms Latenz, Flash v2.5 benötigt ca. 75 ms Modell-Inferenz (ohne Netzwerk- und Anwendungslatenz). Das LLM ist der größte und am wenigsten vorhersehbare Faktor für die Zeit bis zum ersten Audio – hier fließt der Großteil des Latenzbudgets hin. Um die Lücke kurz zu halten, streamen wir das LLM-Output Token für Token und starten die Synthese, bevor das Modell den Satz beendet hat.
Die Modell-Abwägungen hinter diesen Entscheidungen finden Sie in der Modellübersicht und in der Erklärung zu Latenz verstehen.
Was Sie vor dem Start eines Voice-Agenten benötigen
Die Anleitung setzt vier Dinge voraus. Jede ist schnell eingerichtet, aber das Fehlen einer davon blockiert den Server.
Folgende Voraussetzungen sollten Sie prüfen:
- Eine Twilio-Telefonnummer mit Voice-Funktion: Notieren Sie die Nummer sowie Ihre Account SID und Auth Token aus der Twilio-Konsole.
- ElevenLabs API-Schlüssel: Wird in Ihrem ElevenLabs-Dashboard erstellt. Der Schlüssel wird im xi-api-key-Header übermittelt und ist vertraulich, daher nur serverseitig verwenden. Siehe
- LLM API-Schlüssel: Dieses Tutorial behandelt Anthropic Claude und OpenAI als austauschbare Backends – wählen Sie eines davon.
- Ngrok (oder ein anderes Tunnel-Tool) für lokale Entwicklung: Twilio muss Ihren Server über eine öffentliche HTTPS- und WSS-URL erreichen, ngrok stellt dies bereit, ohne dass Sie etwas deployen müssen.
Legen Sie Ihre Secrets als Umgebungsvariablen ab und committen Sie sie nie.
Starten Sie dann einen Tunnel auf dem Port, den Ihr Server nutzt:
Twilio Media Streams Protokoll verstehen
Twilio stellt keinen Roh-Audio-Socket bereit, sondern kapselt alles in ein strukturiertes JSON-Protokoll über WebSocket. Wenn Sie die vier Event-Typen und das Sendeformat verstehen, ist der WebSocket-Handler in Schritt 2 sofort nachvollziehbar.
Sobald Twilio Ihren WebSocket verbindet, sendet es eine Sequenz von JSON-Textnachrichten mit vier möglichen Event-Typen.
Das connected-Event kommt zuerst und bestätigt, dass der WebSocket steht. Das start-Event wird einmalig beim Start des Media Streams gesendet; es enthält eine streamSid, die Sie speichern müssen, um Audio zurückzusenden, sowie Metadaten unter start.customParameters und start.callSid.
Das media-Event ist wiederkehrend: media.payload ist ein base64-kodierter 8kHz mu-law-Audio-Chunk (20 ms pro Frame), media.track steht für eingehendes Anrufer-Audio. Das stop-Event kommt, wenn der Stream endet, meist weil der Anruf beendet wurde.
Um Audio zurückzuspielen, senden Sie eine Nachricht vom Typ media mit derselben streamSid und einer base64 mu-law-Payload. Um bereits eingereihte Audios zu unterbrechen, senden Sie eine clear-Nachricht mit der streamSid – das leert Twilios Ausgabepuffer.
Die Ein- und Ausgangscodierungen sind identisch (ulaw_8000). Wir fordern ulaw_8000 von ElevenLabs Text to Speech an und leiten die Bytes direkt an Twilio weiter, ohne sie umzuwandeln.
Schritt 1: TwiML-Webhook bereitstellen
Wenn ein Anruf eingeht, stellt Twilio eine HTTP-Anfrage an Ihren Webhook, und Sie antworten mit TwiML, das den Anruf mit Ihrem Media Stream verbindet. Das <Connect><Stream>-Verb öffnet einen bidirektionalen WebSocket. Verwenden Sie hier <Connect> statt <Start>: So bleibt der Anruf während des Streams aktiv und Sie können Audio zurücksenden – das ist der Zweck dieses Setups.
Das TwiML, das der Webhook zurückgibt, ist:
In Express ist das ein einzelner POST-Handler, der Host einträgt und das Dokument zurückgibt:
Stellen Sie in der Twilio-Konsole den Webhook für "A call comes in" auf https://your-subdomain.ngrok.app/incoming-call mit HTTP POST.
Schritt 2: Media Stream WebSocket annehmen
Der WebSocket-Handler liest Twilio-Events, steuert die Kaskade und schreibt Audio zurück.
Wir halten pro Anruf einen kleinen Status: die streamSid, eine STT-Verbindung und ein Flag, ob der Agent gerade spricht. Der Handler dekodiert jedes eingehende Media-Frame aus base64 und leitet die rohen mu-law-Bytes an STT weiter:
Schritt 3: Transkribieren mit Scribe v2 Realtime
Scribe v2 Realtime akzeptiert gestreamte Audio-Chunks und liefert Teil- und Endtranskripte. Es unterstützt mu-law direkt, daher reichen wir Twilios Frames unverändert durch.
Es bietet außerdem Voice Activity Detection für segmentierte Abschnitte anhand von Pausen sowie manuelle Steuerung zur finalen Bestätigung eines Segments. Für einen
Die Schritte: Öffnen Sie einen STT-Stream beim Anrufstart. Senden Sie jeden eingehenden mu-law-Chunk. Reagieren Sie auf finale Transkripte, indem Sie das LLM aufrufen.
Die Oberfläche des Echtzeit-STT-Clients entwickelt sich noch, daher wird das folgende Beispiel hinter einem kleinen TypeScript-Adapter (openRealtimeStt) gekapselt, den Sie gegen die Live-API implementieren. Behandeln Sie onFinal als Hook, der einen abgeschlossenen Anrufer-Turn an die nächste Stufe übergibt.
Die Latenz der Echtzeit-Erkennung liegt bei etwa 150 ms für Teiltranskripte – das hält die wahrgenommene Lücke zwischen Anrufer-Ende und Agenten-Beginn klein. Für das Batch-Pendant und den vollen Funktionsumfang siehe die Speech to Text-Dokumentation und die Echtzeit Speech to Text Produktseite.
Schritt 4: Antwort mit LLM generieren
In dieser Stufe wird die Antwort erzeugt. Das LLM erhält den Gesprächsverlauf und gibt den Text des Assistenten zurück. Streamen Sie die Antwort, damit Sie die Synthese schon beim ersten Satz starten können.
Hier wird OpenAI verwendet:
Die oben genannte Modell-ID, gpt-4.1-mini, ist eine Beispielwahl für geringe Latenz; claude-haiku-4-5 ist eine vergleichbare Option von Anthropic. Beide Anbieter können denselben llmReply-Vertrag bedienen; tauschen Sie den Funktionskörper aus, bleibt der Rest des Agenten unverändert.
Der System-Prompt begrenzt die Antwortlänge – das ist am Telefon wichtig: Lange Antworten wirken langsam und sind schwer natürlich zu unterbrechen.
Schritt 5: Mit Flash TTS in ulaw_8000 synthetisieren
Der Text muss jetzt in Audio umgewandelt werden, das Twilio abspielen kann. Fordern Sie Flash v2.5 mit outputFormat: "ulaw_8000" an, damit die Bytes Twilios erwarteter Codierung entsprechen. Streamen Sie das Audio und senden Sie jeden Chunk als media-Event über den WebSocket zurück.
Sammeln Sie LLM-Tokens zu satzgroßen Fragmenten und synthetisieren Sie jedes Fragment, sobald es fertig ist, statt auf die gesamte Antwort zu warten. Das verkürzt die Zeit bis zum ersten Audio, da der Anrufer den ersten Satz hört, während das Modell noch den zweiten produziert. Für mehr Kontrolle über inkrementelle Synthese zeigt der Echtzeit-TTS-WebSocket-Guide, wie Sie Text in einen offenen Synthese-Socket einspeisen; der unten gezeigte HTTP-Streaming-Ansatz ist einfacher und für kurze Gesprächsturns ausreichend.
KI-Voice-Agenten für den Produktiveinsatz absichern
Nach den fünf Schritten oben haben Sie einen funktionierenden Agenten. Das ist jedoch nicht gleichbedeutend mit einem Produktivbetrieb.
Es gibt mehrere Punkte, die Sie beachten sollten, bevor Sie den Agenten auf eine echte Telefonleitung schalten.
Twilio-Webhook-Signaturen validieren
Jeder, der Ihre Webhook-URL kennt, kann POSTs senden. Prüfen Sie daher, ob die Anfrage tatsächlich von Twilio stammt. Twilio signiert jede Anfrage mit Ihrem Auth Token im X-Twilio-Signature-Header. Lehnen Sie alles ab, was die Validierung nicht besteht. Die Signatur wird über die vollständige URL und die POST-Parameter berechnet – Sie müssen es genauso machen wie Twilio.
Twilios Helper übernimmt das für Sie:
Secrets richtig verwalten
Bewahren Sie ELEVENLABS_API_KEY, den LLM-Schlüssel und TWILIO_AUTH_TOKEN in einem Secrets-Manager auf – nicht im Quellcode und nicht in Klartext-Env-Dateien im Repo. Beschränken Sie den ElevenLabs-Schlüssel auf die Endpunkte, die dieser Dienst benötigt, und setzen Sie ein Kreditlimit, damit ein Leak nur begrenzte Auswirkungen hat.
Enterprise-Pläne können einen Schlüssel zusätzlich auf bestimmte IP-Bereiche beschränken (IP-Whitelisting). Dieser Server nutzt den API-Schlüssel direkt, da er nie das Backend verlässt. Wenn Audio-Logik in den Browser oder eine mobile App wandert, wechseln Sie zu Einmal-Tokens, damit der Schlüssel nie clientseitig sichtbar ist.
Das Concurrency-Limit verstehen
Jeder Plan hat ein Concurrency-Limit, das je nach Modellfamilie variiert. Das Limit zählt, wie viele Anfragen gleichzeitig Audio generieren.
Für einen Telefon-Agenten ist das vorteilhaft: Die Audiogenerierung ist schneller als die Wiedergabe, daher wird TTS-Concurrency nur während der kurzen Synthese-Phasen pro Anruf beansprucht, nicht während des gesamten Gesprächs. Als grobe Faustregel kann ein Limit von fünf etwa 100 gleichzeitige Gespräche unterstützen, da die Generierung weit vor der Wiedergabe abgeschlossen ist.
Trotzdem sollten Sie die Auslastung überwachen, statt zu schätzen. ElevenLabs-Antworten enthalten die Header current-concurrent-requests und maximum-concurrent-requests; loggen Sie diese und alarmieren Sie, wenn Sie das Maximum erreichen. Bei Überschreitung werden Anfragen nach Priorität in die Warteschlange gestellt (typisch +50 ms), bei dauerhafter Überlast gibt es HTTP 429.
Behandeln Sie HTTP 429 mit kurzem Backoff. Bleiben sie bestehen, erhöhen Sie das Limit über die Preisseite oder – für Enterprise-Kunden – über Ihren Account Manager.
Barge-in und Unterbrechungen behandeln
Ein Anrufer, der spricht, während der Agent spricht, erwartet, dass der Agent stoppt. Das ist Barge-in – korrektes Handling ist entscheidend, damit der Agent natürlich wirkt.
Erkennen Sie Anrufer-Sprache während der Agent-Wiedergabe mit dem STT-VAD-Signal. Wenn Sie sie erkennen, tun Sie zwei Dinge: Stoppen Sie das Weiterleiten von TTS-Chunks (das Flag agentSpeaking bricht die Schleife ab) und senden Sie Twilio eine clear-Nachricht, um bereits gepuffertes Audio zu löschen.
Ohne clear spielt Twilio weiter gepuffertes Audio ab, nachdem Sie aufgehört haben zu senden – der Agent spricht dann über den Anrufer hinweg.
Protokollieren, überwachen und Fehler abfangen
Instrumentieren Sie jede Stufe, um Latenz zuzuordnen, wenn ein Anruf langsam wirkt. Messen Sie die Zeit vom finalen Transkript bis zum ersten LLM-Token, vom ersten LLM-Token bis zum ersten TTS-Byte und vom ersten TTS-Byte bis zum Frame an Twilio. Die meiste variable Latenz liegt im LLM; STT und TTS sind vergleichsweise stabil.
Planen Sie für Teilausfälle: Das LLM kann ein Timeout haben, der STT-Stream kann abbrechen, und die Netzwerk-Latenz zu ElevenLabs schwankt je nach Region zwischen 20 und 200 ms. Platzieren Sie Ihren Server in der Nähe der Anrufer, nicht nur nahe bei ElevenLabs – ElevenLabs routet ohnehin zum nächsten Cluster in Nordamerika, Europa oder Südostasien.
Wenn eine Stufe ausfällt, lassen Sie den Anrufer nicht in Stille: Synthetisieren Sie eine kurze Fallback-Zeile ("Entschuldigung, könnten Sie das bitte wiederholen?") und halten Sie den Anruf aktiv. Kapseln Sie jede Stufe in Timeout und try/catch, damit ein Fehler nicht den gesamten WebSocket beendet.
Einige weitere Defaults sollten Sie vor dem Go-Live setzen:
- Begrenzen Sie die Antwortlänge im System-Prompt, damit Turns kurz und unterbrechbar bleiben.
- Begrenzen Sie den Gesprächsverlauf, damit lange Anrufe den LLM-Kontext nicht unbegrenzt wachsen lassen.
- Setzen Sie eine maximale Anrufdauer als Schutz gegen festhängende Sessions, die Concurrency verbrauchen.
Um die Stellschrauben weiter zu optimieren, lesen Sie das Latenz-Dokument, das die Herkunft der Zeit bis zum ersten Audio erklärt, die Modellübersicht behandelt die Abwägungen zwischen Geschwindigkeit und Qualität, und der Echtzeit-TTS-WebSocket-Guide zeigt, wie Sie die Synthese-Latenz mit inkrementellem Textinput weiter senken.
Produktionsreife Voice-Agenten mit ElevenAPI bauen
Nach 20 Minuten haben Sie jede Ebene eines produktiven
Wenn Sie die Kaskade nicht selbst pflegen möchten, bietet ElevenAgents Turn-Taking, Unterbrechungs-Handling und Telefonie-Integration als Managed Service – auf denselben Modellen, die Sie gerade manuell verbunden haben.
Um einen selbst kontrollierten Stack weiter zu optimieren, besuchen Sie die ElevenAPI Produktseite für Pläne, Concurrency-Limits und die Stimmbibliothek. Alternativ können Sie sich registrieren und noch heute Ihren ersten Anruf starten.
.webp&w=3840&q=80)
.webp&w=3840&q=80)

.webp&w=3840&q=80)
