Graph-samtalsbot
Ring eller chatta med din ElevenLabs-agent med namn i Microsoft Teams, som med en kollega.
Översikt
Med den här metoden blir agenten en uppringningsbar Teams-identitet. En användare söker efter den med namn och ringer den 1:1, och agenten svarar i realtid — utan telefonnummer, PSTN eller Communications Credits. Det är den enda metoden som kan ringas upp med namn och den mest omfattande att köra.
Den använder en Microsoft Graph-bot för realtidsmedia (Cloud Communications-samtalsplattformen). Media-SDK:t (Microsoft.Skype.Bots.Media) fungerar endast med .NET på Windows Server — det finns ingen Linux- eller annan .NET-lösning för råljud i Teams-samtal.
Detta är den enda metoden som kan ringas upp med namn i Teams. Välj helst widget- fliken för en enklare konfiguration, eller ACS när du specifikt vill ha ett telefonnummer.
Så fungerar det
Boten svarar med applikationsvärdad media, tar emot 50 ljudramar/sekund (20 ms PCM 16 kHz), bryggar dem till ElevenLabs-agenten via en WebSocket och strömmar tillbaka agentens ljud till samtalet.
Krav
- En Azure Bot-registrering + app (Entra-appregistrering).
- Graph-programbehörigheter med administratörsmedgivande:
Calls.AccessMedia.All(råmedia) samtCalls.Initiate.All. - En Windows Server-VM (≥ 2 fysiska kärnor — till exempel
Standard_D4s_v3) med en offentlig IP-adress och öppna medieportar. - Ett TLS-certifikat signerat av en CA på ett offentligt FQDN för media-/signaleringsslutpunkten (medieplattformen avvisar självsignerade certifikat).
- En ElevenLabs-agent inställd på PCM 16000 Hz i båda riktningarna: TTS-utdataformat på fliken Voice, och ljudformat för användarindata på fliken Advanced.
En D2s_v3 (2 vCPU = 1 fysisk kärna) misslyckas med MediaPlatform needs a system with at least 2 cores. Använd en storlek med ≥ 2 fysiska kärnor (till exempel D4s_v3).
Behörigheter och roller
Steg 1 — Registrera boten + Graph-behörigheter
Skapa en appregistrering och en Azure Bot som är kopplad till den, och bevilja + godkänn sedan samtalsbehörigheterna (du behöver Global Admin / Privileged Role Admin för att godkänna):
Bevilja de två Graph-applikationsrollerna och administratörssamtycke (kräver Global Admin / Privileged Role Admin), och bekräfta sedan att tilldelningarna har lagts till:
Om admin-consent returnerar Consent validation failed beviljar du i stället approllerna direkt för tjänstens huvudnamn:
I portalen kontrollerar du i Entra-administrationscentret under App registrations → din app → API permissions: båda behörigheterna ska visas som Granted med gröna bockar.

Steg 2 — Etablera Windows-VM, certifikat och portar
På VM:en (mediaplattformens inbyggda kod behöver dessa — Windows Server saknar dem som standard):
Öppna samma portar i Windows-brandväggen, och notera certifikatets tumavtryck — boten binder Kestrel (443 + en aviseringsport) och mediaplattformen (8445) till det.
VM:ens egna *.cloudapp.azure.com-FQDN fungerar för ett Let’s Encrypt-certifikat — ingen separat domän
behövs.
Steg 3 — Bygg och kör boten
Börja med Microsofts microsoft-graph-comms-samples PublicSamples/EchoBot — den använder net6.0 och byggs med .NET SDK (inga Visual Studio Build Tools behövs):
Konfigurera avsnittet AppSettings i appsettings.json med dina AadAppId, AadAppSecret, ServiceDnsName/MediaDnsName (VM:ens FQDN), CertificateThumbprint och portar (samtal 443, aviseringar 9441, media 8445). Lägg till två inställningar för ElevenLabs-bryggan nedan: ElevenLabsAgentId och ElevenLabsOrigin (wss://api.elevenlabs.io eller din dataplaceringsvärd). Kör den som en schemalagd Windows-uppgift / tjänst så att den överlever omstarter.
Aktivitetsschemaläggarens standardgräns för körningstid (72 timmar) avslutar tyst långvariga uppgifter — en bot som startas vid uppstart slutar fungera tre dagar senare och samtal misslyckas med “we couldn’t connect you”. Inaktivera gränsen och lägg till omstart vid fel:
Standardversionen av EchoBot kraschar vid samtal till standardporten 443: HttpHelpers.SetAbsoluteUri
anropar req.Host.Port.Value, som är null när Host-rubriken saknar en uttrycklig port. Ändra den till
req.Host.Port ?? (req.IsHttps ? 443 : 80).
Byt ut ekot mot ElevenLabs
EchoBots ljudgränssnitt är tydligt: SpeechService.AppendAudioBuffer(in) och en OnSendMediaBufferEventArgs(out)-händelse. Ersätt Azure Speech-innehållet med en ElevenLabs-agent-WebSocket-brygga som behåller samma gränssnitt:
Båda sidor använder mono-PCM i 16 kHz, så det är en base64-genomströmning — ställ in agenten på pcm_16000. Vid en ElevenLabs-interruption (avbrott) utlöser bryggan FlushMedia; koppla den till din mediaström så att den släpper alla köade AudioMediaBuffers, annars fortsätter agenten att prata över den som ringer. Den fullständiga meddelandereferensen finns i WebSocket-dokumentationen. Avslut av samtal och varm överföring behandlas i avsnitten nedan.
URL:en i Connect() når en offentlig agent. För en privat agent begär du en kortlivad
signerad URL på serversidan — GET /v1/convai/conversation/get-signed-url?agent_id=... med din API-
nyckel — och ansluter i stället till den returnerade URL:en. För dataplacering
ställer du in ElevenLabsOrigin på din dataplaceringsvärd (wss://api.eu.residency.elevenlabs.io, .in.
eller .sg.) — förfrågningar om signerade URL:er använder motsvarande https://-värd.
Steg 4 — Gör den uppringbar i Teams
-
Aktivera Calling på Azure Botens Teams-kanal och ställ in webhooken för samtal på
https://YOUR_FQDN/api/calling:I portalen finns detta under din Azure Bot-resurs → Channels → Microsoft Teams → fliken Calling:

Azure Bot → Channels — den anslutna Microsoft Teams-kanalen 
Microsoft Teams-kanal → Calling — samtal aktiverat med botens webhook -
Skapa ett Teams-appmanifest med
bots[0].supportsCalling: trueoch botens app-ID, och sideloada det (Apps → Manage your apps → Upload a custom app), eller publicera det för hela organisationen utan gränssnittet:New-TeamsApp -DistributionMethod organization -Path ./bot-app.zip(MicrosoftTeams PowerShell-modul).
Sök efter appen på namn i Teams och ring den — boten svarar och ElevenLabs-agenten pratar.

Inget telefonnummer eller resurskonto behövs för 1:1-samtal via namn — de behövs endast för PSTN-
uppringning. Calls.AccessMedia.All är det som aktiverar råljudsbryggan.
Textchatt (samma bot)
Samma Azure Bot kan även svara med text i Teams — användare kan alltså antingen ringa agenten eller chatta med den. Samtal och meddelanden är oberoende kanaler på boten: webhooken för samtal hanterar röst, och en Bot Framework-meddelandeslutpunkt (/api/messages) hanterar chatt.

Peka botens meddelandeslutpunkt till den värd som tillhandahåller den (mediaboten eller en annan tjänst — den behöver inte vara Windows-VM:en):
Implementera slutpunkten med Bot Framework SDK och vidarebefordra varje meddelande till agenten i textläge via samma WebSocket för konversationer som används för röst — skicka en user_message-händelse, läs agent_response-händelsen. Aktivera först fältet first message i agentens inställningar för åsidosättningar — koden nedan åsidosätter det till tomt så att svaret besvarar användarens meddelande i stället för agentens hälsning:
Registrera den på vanligt sätt (en CloudAdapter, boten via AddTransient<IBot, ChatBot>() och en /api/messages-styrenhet) och lägg till chattomfattningar i manifestets botpost:
Kodavsnittet öppnar en ny konversation per meddelande, så varje tur är oberoende. För chatt-
minne behåller du en WebSocket öppen per Teams conversation.id (återanvänd den mellan turer) och rensar
inaktiva sessioner — agenten kommer då ihåg tidigare meddelanden i chatten. Åsidosättningen first_message
måste vara aktiverad i agentens inställningar för
åsidosättningar — servern
stänger konversationen om en otillåten åsidosättning skickas. Om du inte kan aktivera den utelämnar du
åsidosättningen och ignorerar i stället den första agent_response i varje session (hälsningen) och returnerar
nästa.
Om chattsvar aldrig kommer fram aktiverar du klient-
händelsen agent_response client event i agentens **Advanced **-
inställningar — textsvar levereras via den händelsen.
Avsluta samtal
När ElevenLabs avslutar konversationen (verktyget End Call stänger WebSocket-anslutningen) avslutar du Teams-delen:
Varm överföring till en människa
Agenten aktiverar ett anpassat klientverktyg, transfer_to_human; boten bjuder in en Teams-användare till det aktiva samtalet (konsultativ anslutning) och kliver sedan åt sidan:
Konsultativ överföring (replacesCallId) kräver att båda parter är Teams-användare i **samma
klientorganisation **; PSTN-överföringsmål kräver en applikationsinstans. Om du först vill informera personen, skicka en
reason-parameter från agenten och spela upp den för personen innan du kopplar ihop dem.
Felsökning
MediaPlatform needs a system with at least 2 cores
MediaPlatform needs a system with at least 2 cores
VM:en har endast en fysisk kärna. Ändra storlek till ≥ 2 fysiska kärnor (t.ex. D4s_v3) och starta om.
Unable to load DLL 'NativeMedia'
Unable to load DLL 'NativeMedia'
Installera VC++ Redistributable (vcredist140) och Windows-funktionen Server-Media-Foundation,
och starta sedan om boten.
Inkommande samtal returnerar 500 / samtalet ansluter inte
EchoBots port-null-bugg på 443 — korrigera HttpHelpers.SetAbsoluteUri (se steg 3). Kontrollera även
att certifikatet är CA-signerat och nåbart på 443.
När du ringer boten hörs 'we couldn't connect you'
Kontrollera att Calling är aktiverat på Teams-kanalen med rätt /api/calling-webhook, att Graph-
behörigheten Calls.AccessMedia.All är godkänd och att portarna 443/8445/9441 är öppna i både
NSG och Windows-brandväggen. Om samtal tidigare fungerade men slutade, kontrollera att botprocessen
fortfarande körs på VM:en — Aktivitetsschemaläggarens standardgräns på 72 timmar avslutar den några
dagar efter uppstart (se varningen i steg 3).