LiveKit Cloud, AT-SIP und Sprachdienste verbinden
Dieser Ablauf richtet den zusätzlichen LiveKit-Echtzeitpfad ein. Der bisherige Twilio-Gather/Say-Pfad bleibt getrennt bestehen. Ein LiveKit-Worker verwendet Streaming-STT, LLM und Streaming-TTS; das Vorhandensein der Pipeline beweist noch keine bestimmte Gesprächsqualität oder 20 parallele Anrufe. Alle folgenden Cloud-/SIP-Aktionen führt der Betreiber bewusst mit seinen Konten aus.
Beginne mit der Konfigurationsübersicht, falls du noch keine Anbieterzugänge hast. Für einen Cloudstart brauchst du LiveKit, einen SIP-Provider, Deepgram, einen Cloud-LLM-Anbieter und einen TTS-Anbieter. Der DGX wird erst später zugeschaltet.
1. LiveKit-Projekt und Zugangsdaten
Erstelle in LiveKit Cloud ein Projekt für SIHub. Öffne dessen Einstellungen und API-Keys. Kopiere die Projekt-URL, den API-Key und das API-Secret in deploy/.env.production:
LIVEKIT_URL=wss://DEIN_PROJEKT.livekit.cloud
LIVEKIT_API_KEY=DEIN_SERVER_API_KEY
LIVEKIT_API_SECRET=DEIN_SERVER_API_SECRET
AIHUB_VOICE_AGENT_NAME=aihub-voice
Die LiveKit-URL ist nicht deine SIHub-Website-Domain. Keys gehören ausschließlich in die Betreiberdatei; der Browser erhält später nur einen eingeschränkten Raumtoken. Der Workerbuild verwendet Python 3.12. Installation und Projektverknüpfung des optionalen lk-CLI erfolgen nach der offiziellen Anleitung bzw. einer überprüften Release-Binärdatei. umask 077 und lk cloud auth erlauben die Projektverknüpfung ohne API-Secret in Shellargumenten. LiveKit-CLI-Setup
Wähle und überprüfe die zum Vertrag passende Cloud-/SIP-Region. Für eingehende EU-Telefonie dokumentiert LiveKit das Muster <Projekt-SIP-Subdomain>.eu.sip.livekit.cloud; den tatsächlichen SIP-Endpunkt findest du in den Projekteinstellungen. Ein regionaler Medien-/SIP-Endpunkt garantiert nicht automatisch die Region von STT, LLM und TTS. SIP-Regionen
2. Österreichischen SIP-Provider konfigurieren
Beschaffe beim tatsächlich gewählten AT/EU-Provider eine verwendbare Rufnummer und einen SIP-Trunk. Fordere mindestens 30 simultane Gesprächskanäle als Vertrag-/Kontolimit an und lass dir Folgendes bestätigen: E.164-Nummernformat, erlaubte Absendernummern, Inbound-SIP-Ziel, Outbound-SIP-Host, Authentifizierungsverfahren, unterstützte Transport-/Codecoptionen sowie IP-Freigaben und Notfallrouting. Ein gekaufter Trunk allein stellt keine 30 KI-Verarbeitungsplätze bereit.
Konfiguriere die Inbound-Weiterleitung des Providers auf den LiveKit-SIP-Endpunkt, nicht auf sihub.at und nicht auf Port 5090. Der Appserver benötigt hierfür keinen eingehenden SIP-Port. Verwende die vom Provider dokumentierte Authentifizierung. Digest-Authentifizierung für Inbound ist nicht bei jedem Carrier verfügbar; alternativ kommen freigegebene Carrier-IP-Adressen infrage. LiveKit dokumentiert, dass allowed_addresses gegebenenfalls erst für das Projekt freigeschaltet werden muss. Trage keine erfundenen IP-Netze und kein offenes 0.0.0.0/0 als Ersatz ein. Inbound-Trunks und Authentifizierung
3. Inbound- und Outbound-Trunk erstellen
LiveKit Cloud bietet unter Telephony → SIP trunks die Anlage. Im JSON-Editor des Dashboards fügst du jeweils nur den inneren trunk-Inhalt ein; die Dateien mit äußerem trunk-Objekt sind für das CLI. Alternativ nutzt du das lk-CLI. Die Beispiele liegen in deploy/livekit/; kopiere sie in ein privates Verzeichnis mit Modus 0700, setze Dateien auf 0600 und ersetze sämtliche Platzhalter im Editor. Die Kennwörter stehen nicht in CLI-Flags.
umask 077
AIHUB_SIP_DIR="$(mktemp -d)"
cp deploy/livekit/inbound-trunk.example.json "$AIHUB_SIP_DIR/inbound-trunk.json"
cp deploy/livekit/outbound-trunk.example.json "$AIHUB_SIP_DIR/outbound-trunk.json"
cp deploy/livekit/dispatch-rule.example.json "$AIHUB_SIP_DIR/dispatch-rule.json"
chmod 600 "$AIHUB_SIP_DIR/"*.json
Bearbeite die Dateien mit deinem Editor. auth_username/auth_password des Inboundbeispiels werden nur verwendet, wenn der Provider diesen Ablauf unterstützt; bei IP-Authentifizierung passt du die Konfiguration anhand dessen echter Carrieradressen und der LiveKit-Freischaltung an. Die Outbounddatei erhält den Provider-SIP-Host, dessen Authdaten und ausschließlich deine verifizierte Absendernummer.
lk sip inbound create "$AIHUB_SIP_DIR/inbound-trunk.json"
lk sip outbound create "$AIHUB_SIP_DIR/outbound-trunk.json"
Notiere die zurückgegebenen Trunk-IDs (ST_...). Die Outboundtrunk-Anlage startet noch keinen Anruf. Erstelle Trunks einmalig und verwende sie wieder; pro Gespräch neue Trunks anzulegen ist nicht der vorgesehene Ablauf. Outbound-Trunk-Referenz
Für regionsbezogene Outbound-Einstellungen verwende nur eine vom aktuellen Projekt/API unterstützte Konfiguration. Die globale Standardroute und eine destination_country-Option sind kein garantiertes Hosting sämtlicher Gesprächsdaten in Österreich. Regionsverhalten
4. SIHub-Agent und Kanal erstellen
Lege in SIHub einen Nicht-Demo-Arbeitsbereich an, importiere Wissen, konfiguriere Agentprompt/-sprache und veröffentliche eine Version. Erstelle einen aktiven Kanal. API-Vertrag:
{
"name": "AT-Hauptnummer",
"status": "active",
"data": {
"type": "sip",
"voice_engine": "livekit",
"mode": "live",
"agent_id": "DEIN_VERÖFFENTLICHTER_AGENT"
}
}
Dieser Body an POST /api/entities/channels liefert unter id die Kanal-ID. Typen sind sip, phone oder webvoice. Administrative Operatorbindung und Livegates kommen zusätzlich; ein Kunde darf durch frei eingegebene Trunk-IDs keine fremde Nummer verwenden.
Ergänze in der geschützten Betreiberumgebung:
AIHUB_LIVE_ENABLED=1
AIHUB_LIVE_WORKSPACE_IDS=DEINE_WORKSPACE_ID
AIHUB_LIVEKIT_CHANNEL_BINDINGS='{"DEINE_CHANNEL_ID":{"workspace_id":"DEINE_WORKSPACE_ID","inbound_trunk_id":"ST_INBOUND","outbound_trunk_id":"ST_OUTBOUND","from_number":"DEINE_VERIFIZIERTE_E164_NUMMER"}}'
Erzeuge die neu konfigurierte App mit sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml up -d --force-recreate app neu. Setze anschließend in SIHub unter Einstellungen den Livebetrieb des Arbeitsbereichs auf aktiv; die API-Entsprechung ist PATCH /api/settings mit {"live_enabled":true}. Demoarbeitsbereiche bleiben gesperrt. Eine neue Operatorumgebung wird erst nach Neuanlage der betreffenden Container wirksam; kontrolliere anschließend GET /api/voice/status. Keine Passwörter oder LiveKit-API-Secrets gehören in die Kanal-Entity.
5. Dispatchregel an exakt diesen Kanal binden
Öffne Telephony → Dispatch rules oder bearbeite die private dispatch-rule.json. Der Dashboard-JSON-Editor erwartet den inneren dispatch_rule-Inhalt; das CLI erhält die ganze Beispieldatei. Setze trunk_ids auf deinen Inboundtrunk; ein weggelassenes Trunkfilterfeld würde einen unnötig breiten Wildcarddispatch erzeugen. agentName ist exakt aihub-voice. Die Jobmetadaten sind der JSON-String {"channel_id":"DEINE_CHANNEL_ID"}.
lk sip dispatch create "$AIHUB_SIP_DIR/dispatch-rule.json"
Die Regel erzeugt pro Anruf einen eigenen Raum und startet den benannten Worker. Der Worker prüft den Kanal, den veröffentlichen Agentstand, dessen Arbeitsbereich und die Operatorbindung. Raumnamen/Telefonieattribute können beim Plattformanbieter Rufnummern enthalten; konfiguriere Log-/Datenschutzregeln entsprechend, ohne automatisch von anonymen Providerlogs auszugehen. Dispatchschema und Metadaten
Das Projekt darf nicht zugleich eine zweite überlappende Dispatchregel für denselben Trunk besitzen. Prüfe vorhandene Regeln, bevor du eine neue aktivierst. Das Audio wird standardmäßig nicht von SIHub aufgezeichnet; es wird keine Egress-/Recording-Anlage automatisch gestartet.
6. STT, LLM und TTS-Konten
Deepgram: Erstelle Projekt und API-Key in der Deepgram Console. Setze DEEPGRAM_API_KEY und ein tatsächlich freigegebenes DEEPGRAM_MODEL. Für den EU-Streamingpfad verwendet die Vorlage DEEPGRAM_BASE_URL=https://api.eu.deepgram.com/v1/listen; das Plugin nutzt daraus die entsprechende sichere WebSocketverbindung. Der Anbieter dokumentiert den EU-Endpunkt einschließlich bestehender Keyverwendung. EU-Endpunkt
DEEPGRAM_MIP_OPT_OUT=1 verlangt den modellverbesserungsbezogenen Opt-out im Worker. Die regionale URL allein ist keine Aussage über Drittanbieter-LLM/TTS und alle Log-/Vertragsfristen. Deepgram beschreibt weitere Unterschiede zwischen Region, Speicherung und MIP; kontrolliere den Opt-out in deinem tatsächlichen Konto. Deepgram-Datenverarbeitung
OpenAI: Erstelle einen projektbezogenen API-Key im OpenAI-Projekt, aktiviere das benötigte Konto-/Nutzungslimit und setze OPENAI_API_KEY, OPENAI_MODEL, VOICE_LLM_PROVIDER=openai. Wähle ein im Konto verfügbares Modell; diese Vorlage erzwingt keinen angeblich neuesten Modellnamen. Providerkeys bleiben serverseitig. Offizielle API-Authentifizierung
Cartesia: Erstelle im Anbieter-Dashboard einen API-Key, wähle eine freigegebene Stimme und übernimm deren Voice-ID. Setze CARTESIA_API_KEY, CARTESIA_VOICE_ID, CARTESIA_MODEL, AIHUB_VOICE_TTS_PROVIDER=cartesia. Der Worker verwendet den Streaming-TTS-Pfad. Model-ID, Voice-ID und API-Version sind unterschiedliche Werte. Cartesia-WebSocket-TTS
ElevenLabs als alternative TTS: Erstelle einen eingeschränkten API-Key und kopiere eine im Konto verfügbare Voice-ID. Setze ELEVENLABS_API_KEY, ELEVENLABS_VOICE_ID, ELEVENLABS_MODEL, AIHUB_VOICE_TTS_PROVIDER=elevenlabs. Die Provider-Doku beschreibt Keyrestriktionen und serverseitige Authentifizierung. Trage das Modell ausdrücklich ein, etwa das im Konto freigegebene eleven_flash_v2_5; die aktuelle Modelldokumentation empfiehlt Flash statt der älteren Turbo-Modelle. ElevenLabs-Modelle Eine Stimme zu verwenden ist kein implementierter Voice-Cloning-Workflow. ElevenLabs-Keys
Providerkonkurrenzlimits müssen pro Projekt und Region mindestens deine geplante Peaklast erlauben; neue zusätzliche Keys umgehen nicht automatisch Projektlimits. Prüfe Vertrags-/Regionoptionen der tatsächlich gewählten Anbieter. Deepgram-Limits
Konkrete Startwerte und Neuladen
Die Produktionsvorlage verwendet DEEPGRAM_MODEL=nova-3, CARTESIA_MODEL=sonic-3 und für die TTS-Alternative ELEVENLABS_MODEL=eleven_flash_v2_5. Prüfe deren Freischaltung im jeweiligen Konto und ersetze sie bei Bedarf ausdrücklich. OPENAI_MODEL bzw. GROQ_MODEL muss dein verfügbares Textmodell enthalten. Für den Cloudstart bleibt die LLM-Route in Agent/Arbeitsbereich cloud.
sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml config --quiet
sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml up -d --force-recreate app
sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml run --rm --no-deps app python manage.py check-config --voice
check-config nennt ausschließlich fehlende Variablennamen und prüft Formate. Exitcode 1 bedeutet: Konfiguration vervollständigen. Erfolgreiche Prüfung beweist weder gültige Schlüssel noch Providerlimits; es wird kein Anbieter kontaktiert. Bei gesetzter Livefreigabe und konfigurierten Dispatchregeln können externe Anrufer bereits echte Calls auslösen; aktiviere das öffentliche Carrier-Routing erst nach diesen Prüfungen.
7. Worker starten, dann einzelne freigegebene Tests
sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml --profile voice up -d --build voice-worker-a voice-worker-b
sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml logs --tail 50 voice-worker-a voice-worker-b
Prüfe Registrierung/Health in LiveKit und im Monitoring. /internal/voice/ bleibt beim öffentlichen Apache gesperrt; Dockerworker sprechen direkt mit http://app:5090 und authentifizieren sich mit AIHUB_VOICE_WORKER_TOKEN. Veröffentliche diesen Schlüssel nicht als Arbeitsbereich-API-Key.
Ein bewusster Outbound-Test verwendet POST /api/test-call:
{"agent_id":"AGENT_ID","phone":"DEINE_EINWILLIGENDE_TESTNUMMER","consent":true,"mode":"live"}
Ein tatsächlicher E.164-Zielwert und bestätigte Einwilligung sind notwendig. Halte die Agentzuordnung zu einem passenden aktiven Telefonkanal eindeutig. Die Ausgabe enthält den Gesprächsbezug; prüfe zusätzlich die LiveKit-SIP-Session. Dispatch plus SIP-Participant verbindet den Angerufenen mit dem Raum. Outbound-Call-Ablauf
Erstelle für Browser-Audio einen eigenen aktiven Kanal mit data.type=webvoice, data.voice_engine=livekit, data.mode=live und veröffentlichter agent_id. Ergänze dessen eigene Operatorbindung {"WEBVOICE_CHANNEL_ID":{"workspace_id":"DEINE_WORKSPACE_ID"}} im selben AIHUB_LIVEKIT_CHANNEL_BINDINGS-JSON; bestehende Telefonieeinträge bleiben darin enthalten. Für diesen Kanal ist kein SIP-Trunk erforderlich.
Für Browser-Audio erhält ein authentifiziertes Konto mit Chatrechten über POST /api/voice/web-session und {"channel_id":"WEBVOICE_CHANNEL_ID"} einen url, token und room_name. Verwende den vorbereiteten Audiozugang/SDK mit Mikrofonberechtigung und HTTPS. Ein Token-JSON allein ist kein Browser-Audiotest.
Erster Inbound-Test: Rufe deine eigene AT-Nummer von einer autorisierten Testnummer an. Prüfe Sprache, Begrüßung, Unterbrechungen, veröffentlichte Wissensantworten, Verlauf und Ende. Wiederhole anschließend die Abnahmestufen, einschließlich DGX-/Worker-/Providerfehlern. Es werden durch das bloße Lesen der Doku keine kostenpflichtigen Anrufe gestartet.
8. Häufige Fehler eingrenzen
| Beobachtung | Nächster Schritt |
|---|---|
| Website 502 | sudo docker compose --env-file deploy/.env.production -f deploy/compose.yml ps, App-Health und Port 5090 prüfen; Apache-Errorlog kontrollieren. |
| Livefreigabe 409 | Operatorflag, echte Workspace-ID und Liveeinstellung des Nicht-Demobereichs prüfen. |
| Worker erhält keinen Job | agentName, Kanalmetadaten, Dispatchregel und Trunk-ID abgleichen; keine überlappende Regel aktivieren. |
| SIP 403 | Provider-/LiveKit-Trunkauthentifizierung und Carrier-IP-Freigabe prüfen. |
| Call klingelt, bleibt aber stumm | SIP-Participant sip.callStatus=active, Workerjob, STT-/TTS-/LLM-Konfiguration und Codec-/Transportweg prüfen. |
| Provider 401/403/429 | Keyberechtigung, Guthaben, Projekt-/Regionslimit und verfügbare Modell-ID im Anbieterportal prüfen. |
| Browser ohne Mikrofon | HTTPS, Browserberechtigung und gültigen neuen Webvoice-Raumtoken prüfen. |
Änderung in .env.production wirkungslos |
Betroffene Container neu erzeugen; restart allein übernimmt geänderte Umgebungswerte nicht. |
Schlüssel, komplette Umgebungsdateien und Gesprächsinhalte gehören nicht in Diagnosetickets. Für Anbieter-Sessions nutze die jeweiligen pseudonymen Call-/Room-/Request-IDs und das offizielle LiveKit-Testverfahren.