Graph-Anrufbot
Graph-Anrufbot
Rufen Sie Ihren ElevenLabs-Agenten in Microsoft Teams per Namen an oder chatten Sie mit ihm – wie mit einem Kollegen.
Überblick
Dieser Ansatz macht den Agenten zu einer anrufbaren Teams-Identität. Ein Nutzer sucht ihn per Namen und ruft ihn im 1:1-Gespräch an. Der Agent antwortet in Echtzeit – ohne Telefonnummer, PSTN oder Communications Credits. Dies ist der einzige Ansatz, bei dem ein Anruf per Namen möglich ist, und der aufwendigste im Betrieb.
Er nutzt einen Microsoft Graph-Echtzeit-Medienbot (die Cloud Communications Calling-Plattform). Das Media SDK (Microsoft.Skype.Bots.Media) unterstützt nur .NET auf Windows Server – für Roh-Audio in Teams-Anrufen gibt es keinen Linux- oder Nicht-.NET-Weg.
Dies ist der einzige Ansatz, der in Teams per Namen anrufbar ist. Für eine einfachere Einrichtung verwenden Sie den Widget- Tab oder ACS, wenn Sie ausdrücklich eine Telefonnummer benötigen.
Funktionsweise
Der Bot antwortet mit anwendungsgehosteten Medien, empfängt 50 Audio-Frames pro Sekunde (20 ms PCM mit 16 kHz), verbindet sie über einen WebSocket mit dem ElevenLabs-Agenten und streamt das Audio des Agenten zurück in den Anruf.
Anforderungen
- Eine Azure Bot-Registrierung + App (Entra-App-Registrierung).
- Graph-Anwendungsberechtigungen mit Admin-Einwilligung:
Calls.AccessMedia.All(Rohmedien) plusCalls.Initiate.All. - Eine Windows Server-VM (≥ 2 physische Kerne – z. B.
Standard_D4s_v3) mit öffentlicher IP und offenen Medienports. - Ein von einer CA signiertes TLS-Zertifikat auf einer öffentlichen FQDN für den Medien-/Signalisierungsendpunkt (die Medienplattform lehnt selbstsignierte Zertifikate ab).
- Ein ElevenLabs-Agent, der auf beiden Seiten auf PCM 16000 Hz eingestellt ist: TTS-Ausgabeformat im Tab Voice, Audioformat für Nutzereingaben im Tab Advanced.
Eine D2s_v3 (2 vCPU = 1 physischer Kern) schlägt mit MediaPlatform needs a system with at least 2 cores fehl. Verwenden Sie eine Größe mit ≥ 2 physischen Kernen (z. B. D4s_v3).
Berechtigungen und Rollen
Schritt 1 – Bot + Graph-Berechtigungen registrieren
Erstellen Sie eine App-Registrierung und einen daran gebundenen Azure Bot. Erteilen und genehmigen Sie anschließend die Anrufberechtigungen (für die Einwilligung benötigen Sie Global Admin / Privileged Role Admin):
Erteilen Sie die beiden Graph-Anwendungsrollen und die Admin-Einwilligung (erfordert Global Admin / Privileged Role Admin). Prüfen Sie anschließend, ob die Zuweisungen erfolgt sind:
Wenn admin-consent den Fehler Consent validation failed zurückgibt, erteilen Sie die App-Rollen stattdessen direkt für den Dienstprinzipal:
Prüfen Sie im Portal im Entra Admin Center unter App registrations → Ihre App → API permissions: Beide Berechtigungen sollten mit grünen Häkchen als Granted angezeigt werden.

Schritt 2 – Windows-VM, Zertifikat und Ports bereitstellen
Auf der VM (der native Code der Medienplattform benötigt diese Komponenten – Windows Server enthält sie standardmäßig nicht):
Öffnen Sie dieselben Ports in der Windows-Firewall und notieren Sie sich den Fingerabdruck des Zertifikats. Der Bot bindet Kestrel (443 + einen Benachrichtigungsport) und die Medienplattform (8445) daran.
Die eigene *.cloudapp.azure.com-FQDN der VM funktioniert für ein Let’s-Encrypt-Zertifikat – eine
separate Domain ist nicht erforderlich.
Schritt 3 – Bot erstellen und ausführen
Starten Sie mit Microsofts microsoft-graph-comms-samples PublicSamples/EchoBot. Es zielt auf net6.0 und wird mit dem .NET SDK erstellt (keine Visual Studio Build Tools erforderlich):
Konfigurieren Sie den Abschnitt AppSettings in appsettings.json mit Ihrer AadAppId, Ihrem AadAppSecret, ServiceDnsName/MediaDnsName (der FQDN der VM), CertificateThumbprint und den Ports (Anrufe 443, Benachrichtigungen 9441, Medien 8445). Fügen Sie für die folgende ElevenLabs-Bridge zwei Einstellungen hinzu: ElevenLabsAgentId und ElevenLabsOrigin (wss://api.elevenlabs.io oder Ihren Residency-Host). Führen Sie sie als geplante Windows-Aufgabe bzw. Dienst aus, damit sie Neustarts übersteht.
Das standardmäßige Ausführungszeitlimit (72 Stunden) der Aufgabenplanung beendet langlaufende Aufgaben unbemerkt. Ein beim Start gestarteter Bot fällt drei Tage später aus und Anrufe schlagen mit „we couldn’t connect you“ fehl. Deaktivieren Sie das Limit und fügen Sie einen Neustart bei Fehlern hinzu:
Der Standard-EchoBot stürzt bei einem Anruf über den Standardport 443 ab: HttpHelpers.SetAbsoluteUri
ruft req.Host.Port.Value auf, was null ist, wenn der Host-Header keinen expliziten Port enthält.
Ändern Sie dies in req.Host.Port ?? (req.IsHttps ? 443 : 80).
Echo durch ElevenLabs ersetzen
Die Audioschnittstelle von EchoBot ist klar: SpeechService.AppendAudioBuffer(in) und ein OnSendMediaBufferEventArgs(out)-Ereignis. Ersetzen Sie den Azure-Speech-Body durch eine ElevenLabs-Agent-WebSocket-Bridge mit derselben Oberfläche:
Beide Seiten verwenden PCM mit 16 kHz und Mono. Daher ist es ein Base64-Passthrough – stellen Sie den Agenten auf pcm_16000 ein. Bei einer ElevenLabs-interruption (Unterbrechung) löst die Bridge FlushMedia aus. Verbinden Sie dies mit Ihrem Medienstream, damit ausstehende AudioMediaBuffer verworfen werden. Andernfalls spricht der Agent weiter über den Anrufer hinweg. Die vollständige Nachrichtenreferenz finden Sie in der WebSocket-Dokumentation. Das Auflegen am Anrufende und die Warmübergabe werden in den folgenden Abschnitten behandelt.
Die URL in Connect() erreicht einen öffentlichen Agenten. Für einen privaten Agenten fordern Sie
serverseitig eine kurzlebige signierte URL an – GET /v1/convai/conversation/get-signed-url?agent_id=... mit
Ihrem API-Key – und verbinden Sie sich stattdessen mit der zurückgegebenen URL. Setzen Sie bei Datenresidenz
ElevenLabsOrigin auf Ihren Residency-Host (wss://api.eu.residency.elevenlabs.io, .in. oder .sg.) – Anfragen
nach signierten URLs verwenden den passenden https://-Host.
Schritt 4 – In Teams anrufbar machen
-
Aktivieren Sie Calling im Teams-Kanal des Azure Bots und setzen Sie den Calling-Webhook auf
https://YOUR_FQDN/api/calling:Im Portal finden Sie dies unter Ihrer Azure-Bot-Ressource → Channels → Microsoft Teams → Tab Calling:

Azure Bot → Channels – der verbundene Microsoft-Teams-Kanal 
Microsoft-Teams-Kanal → Calling – Calling mit dem Webhook des Bots aktiviert -
Erstellen Sie ein Teams-App-Manifest mit
bots[0].supportsCalling: trueund der App-ID des Bots und laden Sie es quer (Apps → Manage your apps → Upload a custom app), oder veröffentlichen Sie es ohne Benutzeroberfläche organisationsweit:New-TeamsApp -DistributionMethod organization -Path ./bot-app.zip(MicrosoftTeams-PowerShell-Modul).
Suchen Sie die App in Teams per Namen und rufen Sie sie an – der Bot antwortet und der ElevenLabs-Agent spricht.

Für 1:1-Anrufe per Name ist keine Telefonnummer oder Ressourcenidentität erforderlich – diese werden nur für PSTN-
Einwahl benötigt. Calls.AccessMedia.All aktiviert die Roh-Audio-Bridge.
Textchat (derselbe Bot)
Derselbe Azure Bot kann in Teams auch auf Text antworten — Nutzer können den Agenten also anrufen oder mit ihm chatten. Anrufe und Nachrichten sind unabhängige Kanäle des Bots: Der Calling-Webhook verarbeitet Sprache, und ein Bot-Framework-Messaging-Endpunkt (/api/messages) verarbeitet Chats.

Richten Sie den Messaging-Endpunkt des Bots auf den Host, der ihn bereitstellt (den Medienbot oder einen anderen Dienst — es muss nicht die Windows-VM sein):
Implementieren Sie den Endpunkt mit dem Bot Framework SDK und leiten Sie jede Nachricht im Textmodus über denselben für Sprache verwendeten Conversation-WebSocket an den Agenten weiter — senden Sie ein user_message-Event und lesen Sie das agent_response-Event. Aktivieren Sie zuerst das Feld erste Nachricht in den Override-Einstellungen des Agenten — der folgende Code überschreibt es mit einem leeren Wert, sodass die Antwort auf die Nachricht des Nutzers und nicht die Begrüßung des Agenten zurückgegeben wird:
Registrieren Sie ihn auf die übliche Weise (einen CloudAdapter, den Bot über AddTransient<IBot, ChatBot>() und einen /api/messages-Controller) und fügen Sie dem Bot-Eintrag des Manifests Chat-Bereiche hinzu:
Das Snippet öffnet für jede Nachricht eine neue Conversation, daher ist jeder Turn unabhängig. Für
Chat-Speicher halten Sie einen WebSocket pro Teams-conversation.id geöffnet (verwenden Sie ihn über mehrere Turns hinweg) und bereinigen Sie
inaktive Sitzungen — der Agent erinnert sich dann an frühere Nachrichten in diesem Chat. Der Override für first_message
muss in den Override-Einstellungen des Agenten aktiviert sein — der Server
schließt die Conversation, wenn ein nicht erlaubter Override gesendet wird. Falls Sie ihn nicht aktivieren können, lassen Sie den
Override weg und verwerfen stattdessen die erste agent_response jeder Sitzung (die Begrüßung) und geben Sie
die nächste zurück.
Falls Chat-Antworten nie eintreffen, aktivieren Sie das agent_response-Client-
Event in den erweiterten
Einstellungen des Agenten — Textantworten werden über dieses Event bereitgestellt.
Anruf beenden
Wenn ElevenLabs die Conversation beendet (das Tool Anruf beenden schließt den WebSocket), legen Sie die Teams-Verbindung auf:
Warme Übergabe an einen Mitarbeiter
Der Agent löst ein benutzerdefiniertes transfer_to_human-Client-Tool aus; der Bot lädt einen Teams-Nutzer in den laufenden Anruf ein (beratendes Hinzufügen) und tritt dann zurück:
Die beratende Übergabe (replacesCallId) setzt voraus, dass beide Parteien Teams-Nutzer im selben
Tenant sind; PSTN-Übergabeziele erfordern eine Anwendungsinstanz. Um den Mitarbeiter zuerst zu informieren, übergeben Sie einen
reason-Parameter vom Agenten und spielen Sie ihn dem Mitarbeiter vor dem Verbinden vor.
Fehlerbehebung
MediaPlatform benötigt ein System mit mindestens 2 Kernen
MediaPlatform benötigt ein System mit mindestens 2 Kernen
Die VM hat nur einen physischen Kern. Ändern Sie die Größe auf ≥ 2 physische Kerne (z. B. D4s_v3) und starten Sie neu.
DLL 'NativeMedia' kann nicht geladen werden
DLL 'NativeMedia' kann nicht geladen werden
Installieren Sie das VC++ Redistributable (vcredist140) und das Windows-Feature Server-Media-Foundation,
und starten Sie dann den Bot neu.
Eingehender Anruf gibt 500 zurück / Anruf wird nicht verbunden
Der EchoBot-Port-Null-Bug auf 443 — patchen Sie HttpHelpers.SetAbsoluteUri (siehe Schritt 3). Prüfen Sie außerdem,
ob das Zertifikat von einer CA signiert und über 443 erreichbar ist.
Beim Anrufen des Bots heißt es: 'Verbindung konnte nicht hergestellt werden'
Prüfen Sie, ob Calling im Teams-Kanal mit dem korrekten /api/calling-Webhook aktiviert ist, die
Graph-Berechtigung Calls.AccessMedia.All genehmigt wurde und die Ports 443/8445/9441 sowohl in der
NSG als auch in der Windows-Firewall geöffnet sind. Falls Anrufe früher funktionierten und dann nicht mehr, prüfen Sie, ob der Bot-Prozess
noch auf der VM läuft — das standardmäßige Ausführungslimit der Aufgabenplanung von 72 Stunden beendet ihn einige
Tage nach dem Start (siehe Warnung in Schritt 3).