> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Graph-samtalsbot

## Ö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.

> **Note**
>
> Detta är den enda metoden som kan ringas upp **med namn** i Teams. Välj helst [widget- fliken](/docs/sv/eleven-agents/phone-numbers/microsoft-teams/widget-tab) för en enklare konfiguration, eller
> [ACS](/docs/sv/eleven-agents/phone-numbers/microsoft-teams/azure-communication-services) när du
> specifikt vill ha ett telefonnummer.

## Så fungerar det

![En Teams-användare ringer boten med namn; Teams dirigerar samtalet till mediaboten på en Windows-VM, som bryggar rått PCM 16k-ljud till ElevenLabs-agenten via en WebSocket](/docs/_fern-files/elevenlabs.docs.buildwithfern.com/f411ec0b44d4c5ca1a61598fbd1e6162e46a1c74179eebb4b673ee1428823e84/assets/images/conversational-ai/teams-media-bot-architecture.svg)

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

1. En **Azure Bot**-registrering + app (Entra-appregistrering).
2. **Graph-programbehörigheter** med administratörsmedgivande: `Calls.AccessMedia.All` (råmedia) samt `Calls.Initiate.All`.
3. En **Windows Server-VM** (≥ **2 fysiska kärnor** — till exempel `Standard_D4s_v3`) med en offentlig IP-adress och öppna medieportar.
4. Ett **TLS-certifikat signerat av en CA** på ett offentligt FQDN för media-/signaleringsslutpunkten (medieplattformen avvisar självsignerade certifikat).
5. En [ElevenLabs-agent](/docs/sv/eleven-agents/quickstart) inställd på **PCM 16000 Hz** i båda riktningarna: TTS-utdataformat på fliken **Voice**, och ljudformat för användarindata på fliken **Advanced**.

> **Warning**
>
> 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

| Omfattning                    | Roll / behörighet                                                                                                                      | Varför                                                                                                       |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Entra                         | **Application Administrator**                                                                                                          | skapa appregistreringen + Azure Bot                                                                          |
| Entra                         | **Global Administrator / Privileged Role Administrator**                                                                               | ge administratörssamtycke för Graphs samtalsbehörigheter — appbehörigheter kan inte godkännas av appen själv |
| Microsoft Graph (applikation) | `Calls.AccessMedia.All`, `Calls.Initiate.All`                                                                                          | besvara 1:1-samtal och få åtkomst till råmedia                                                               |
| Azure RBAC                    | **Contributor** för resursgruppen                                                                                                      | skapa Windows-VM:en + Azure Bot                                                                              |
| Teams-administratör           | tillåt [**uppladdning av anpassade appar**](https://admin.teams.microsoft.com/policies/manage-apps); aktivera botens **Calling**-kanal | sideloada appen och ta emot samtal                                                                           |

## 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):

```bash
APPID=$(az ad app create --display-name "ElevenLabs Teams Agent" \
  --sign-in-audience AzureADMyOrg --query appId -o tsv)
az ad sp create --id "$APPID"
# create a client secret and record it
az ad app credential reset --id "$APPID" --display-name bot --query password -o tsv

# Azure Bot bound to the app
az bot create --resource-group $RG --name el-teams-agent-bot \
  --app-type SingleTenant --appid "$APPID" --tenant-id $TENANT \
  --endpoint "https://YOUR_FQDN/api/messages" --sku S1
```

Bevilja de två Graph-applikationsrollerna och **administratörssamtycke** (kräver Global Admin / Privileged Role Admin), och bekräfta sedan att tilldelningarna har lagts till:

```bash
# Graph app roles: Calls.AccessMedia.All, Calls.Initiate.All
az ad app permission add --id "$APPID" --api 00000003-0000-0000-c000-000000000000 \
  --api-permissions a7a681dc-756e-4909-b988-f160edc6655f=Role \
    284383ee-7f6e-4e40-a2a8-e85dcb029101=Role
az ad app permission admin-consent --id "$APPID"

# Verify — should print both role ids
az rest --method GET \
  --url "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$APPID')/appRoleAssignments" \
  --query "value[].appRoleId" -o tsv
```

> **Note**
>
> Om `admin-consent` returnerar `Consent validation failed` beviljar du i stället approllerna direkt för tjänstens huvudnamn:
>
> ```bash
> GRAPH_SP=$(az ad sp show --id 00000003-0000-0000-c000-000000000000 --query id -o tsv)
> BOT_SP=$(az ad sp show --id "$APPID" --query id -o tsv)
> for ROLE in a7a681dc-756e-4909-b988-f160edc6655f 284383ee-7f6e-4e40-a2a8-e85dcb029101; do
>   az rest --method POST \
>     --url "https://graph.microsoft.com/v1.0/servicePrincipals/$GRAPH_SP/appRoleAssignedTo" \
>     --body "{\"principalId\": \"$BOT_SP\", \"resourceId\": \"$GRAPH_SP\", \"appRoleId\": \"$ROLE\"}"
> done
> ```

I portalen kontrollerar du i [Entra-administrationscentret](https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/RegisteredAppsListBlade) under **App registrations → din app → API permissions**: båda behörigheterna ska visas som **Granted** med gröna bockar.

![Bladet för appregistreringens API-behörigheter som visar Calls.AccessMedia.All och Calls.Initiate.All
beviljade](/docs/_fern-img/4abc1e220d3fc03845594aa4f835656425cc1c39448dae30dace98e672fd8fb1.webp)

## Steg 2 — Etablera Windows-VM, certifikat och portar

```bash
az vm create -g $RG -n teams-media-bot --image Win2022Datacenter \
  --size Standard_D4s_v3 --admin-username azureuser --admin-password '<strong-pw>' \
  --public-ip-sku Standard --public-ip-address-dns-name elevenmediabot
az vm open-port -g $RG -n teams-media-bot --port 80,443,8445,9441 --priority 300
```

På VM:en (mediaplattformens inbyggda kod behöver dessa — Windows Server saknar dem som standard):

```powershell
# VC++ runtime + Media Foundation feature (required by NativeMedia.dll)
choco install -y vcredist140
Install-WindowsFeature Server-Media-Foundation

# CA cert for the VM's FQDN via win-acme (HTTP-01), then import to LocalMachine\My
& wacs.exe --target manual --host <vm-fqdn>.cloudapp.azure.com `
  --validation selfhosting --store pfxfile --pfxfilepath C:\bot\certs --accepttos
```

Öppna samma portar i **Windows-brandväggen**, och notera certifikatets **tumavtryck** — boten binder Kestrel (443 + en aviseringsport) och mediaplattformen (8445) till det.

> **Tip**
>
> 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`](https://github.com/microsoftgraph/microsoft-graph-comms-samples) **PublicSamples/EchoBot** — den använder `net6.0` och byggs med .NET SDK (inga Visual Studio Build Tools behövs):

```powershell
git clone --depth 1 https://github.com/microsoftgraph/microsoft-graph-comms-samples.git C:\bot\samples
cd C:\bot\samples\Samples\PublicSamples\EchoBot\src
dotnet build EchoBot.sln -c Release
```

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.

> **Warning**
>
> 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:
>
> ```powershell
> $s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 0) `
>   -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1) -StartWhenAvailable
> Set-ScheduledTask -TaskName EchoBot -Settings $s
> ```

> **Warning**
>
> 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:

**`SpeechService.cs — ElevenLabs-brygga (kärna)`**

```csharp title="SpeechService.cs — ElevenLabs-brygga (kärna)"
public class SpeechService
{
    private readonly AppSettings _settings;
    private readonly ILogger _logger;
    private ClientWebSocket _ws;
    private bool _started;
    private bool _connecting;

    public event EventHandler<MediaStreamEventArgs> SendMediaBuffer; // agent audio -> call
    public event EventHandler FlushMedia;                            // barge-in: drop queued audio

    public SpeechService(AppSettings settings, ILogger logger) { _settings = settings; _logger = logger; }

    // Caller audio -> ElevenLabs
    public async Task AppendAudioBuffer(AudioMediaBuffer buffer)
    {
        if (!_started)
        {
            if (_connecting) return;            // a connect attempt is already in flight
            _connecting = true;
            try { await Connect(); _started = true; }
            catch (Exception ex) { _logger.Error(ex, "ElevenLabs connect failed; retry on next frame"); return; }
            finally { _connecting = false; }
        }
        if (_ws?.State != WebSocketState.Open || buffer.Length <= 0) return;
        var pcm = new byte[buffer.Length];
        Marshal.Copy(buffer.Data, pcm, 0, (int)buffer.Length);
        var msg = JsonSerializer.Serialize(new { user_audio_chunk = Convert.ToBase64String(pcm) });
        await _ws.SendAsync(Encoding.UTF8.GetBytes(msg), WebSocketMessageType.Text, true, default);
    }

    private async Task Connect()
    {
        _ws = new ClientWebSocket();
        // ElevenLabsOrigin: wss://api.elevenlabs.io, or a residency host (.eu./.in./.sg.)
        var url = $"{_settings.ElevenLabsOrigin}/v1/convai/conversation?agent_id={_settings.ElevenLabsAgentId}";
        await _ws.ConnectAsync(new Uri(url), default);
        await _ws.SendAsync(Encoding.UTF8.GetBytes(
            JsonSerializer.Serialize(new { type = "conversation_initiation_client_data" })),
            WebSocketMessageType.Text, true, default);
        _ = Task.Run(ReceiveLoop);
    }

    private async Task ReceiveLoop()
    {
        var buf = new byte[32768]; var sb = new StringBuilder();
        while (_ws.State == WebSocketState.Open)
        {
            sb.Clear(); WebSocketReceiveResult r;
            do { r = await _ws.ReceiveAsync(buf, default); sb.Append(Encoding.UTF8.GetString(buf, 0, r.Count)); }
            while (!r.EndOfMessage);

            using var doc = JsonDocument.Parse(sb.ToString());
            var type = doc.RootElement.GetProperty("type").GetString();
            if (type == "audio")            // ElevenLabs audio -> call
                Emit(Convert.FromBase64String(doc.RootElement
                    .GetProperty("audio_event").GetProperty("audio_base_64").GetString()));
            else if (type == "ping")
                await _ws.SendAsync(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new {
                    type = "pong", event_id = doc.RootElement.GetProperty("ping_event").GetProperty("event_id").GetInt32() })),
                    WebSocketMessageType.Text, true, default);
            else if (type == "interruption")  // barge-in: drop any agent audio still queued
                FlushMedia?.Invoke(this, EventArgs.Empty);
        }
    }

    // slice PCM into 20 ms / 640-byte frames the media platform expects
    private void Emit(byte[] pcm)
    {
        var all = new List<AudioMediaBuffer>(); long tick = DateTime.Now.Ticks;
        for (int off = 0; off < pcm.Length; off += 640)
        {
            var frame = new byte[640];
            Array.Copy(pcm, off, frame, 0, Math.Min(640, pcm.Length - off));
            all.AddRange(Utilities.CreateAudioMediaBuffers(frame, tick, _logger));
            tick += 20 * 10000;
        }
        if (all.Count > 0) SendMediaBuffer?.Invoke(this, new MediaStreamEventArgs { AudioMediaBuffers = all });
    }
}
```

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 `AudioMediaBuffer`s, annars fortsätter agenten att prata över den som ringer. Den fullständiga meddelandereferensen finns i [WebSocket-dokumentationen](/docs/sv/eleven-agents/libraries/web-sockets). Avslut av samtal och varm överföring behandlas i avsnitten nedan.

> **Note**
>
> 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](/docs/sv/overview/administration/data-residency)
> 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

1. **Aktivera Calling** på Azure Botens Teams-kanal och ställ in **webhooken för samtal** på `https://YOUR_FQDN/api/calling`:

   ```bash
   az bot msteams create -g $RG -n el-teams-agent-bot \
     --enable-calling --calling-web-hook "https://YOUR_FQDN/api/calling"
   ```

   I portalen finns detta under din Azure Bot-resurs → **Channels** → **Microsoft Teams** → fliken **Calling**:

   ![Azure Bots Channels-blad som listar Microsoft Teams-kanalen som
   felfri](/docs/_fern-img/01115d26ab645dd6ec6569a36a918cd4de0214c79dcb0070d7a3c3a5e544c93b.webp)

   ![Teams-kanalens Calling-flik med Enable calling markerat och webhooken för samtal
   inställd](/docs/_fern-img/7c4819f64878bfb152661adc948c1170f9efd48ba3d68401c4a4d4ba075951b0.webp)

2. Skapa ett **Teams-appmanifest** med `bots[0].supportsCalling: true` och 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.

![Ett aktivt Teams-samtal med ElevenLabs-agent-
boten](/docs/_fern-img/0f1fad08a091bcd20ffbbf5c3949b5503f423d8eb6298f464a870b3a0a254726.webp)

> **Note**
>
> 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.

![En Teams-chatt där ElevenLabs-agentboten svarar på text-
meddelanden](/docs/_fern-img/fb75ae17848916790d29c1c0a703051946902893e46ed62884742db36be453b2.webp)

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):

```bash
az bot update -g $RG -n el-teams-agent-bot --endpoint "https://YOUR_FQDN/api/messages"
```

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`](/docs/sv/eleven-agents/customization/events/client-to-server-events)-händelse, läs [`agent_response`](/docs/sv/eleven-agents/customization/events/client-events)-händelsen. Aktivera först fältet **first message** i agentens inställningar för [åsidosättningar](/docs/sv/eleven-agents/customization/personalization/overrides) — koden nedan åsidosätter det till tomt så att svaret besvarar användarens meddelande i stället för agentens hälsning:

**`ChatBot.cs — Teams-textchatt -> ElevenLabs (textläge)`**

```csharp title="ChatBot.cs — Teams-textchatt -> ElevenLabs (textläge)"
public class ChatBot : ActivityHandler
{
    private readonly AppSettings _settings;
    public ChatBot(AppSettings settings) => _settings = settings;

    protected override async Task OnMessageActivityAsync(
        ITurnContext<IMessageActivity> turn, CancellationToken ct)
    {
        var reply = await AskAgent(turn.Activity.Text, ct);
        await turn.SendActivityAsync(MessageFactory.Text(reply), ct);
    }

    private async Task<string> AskAgent(string text, CancellationToken ct)
    {
        using var ws = new ClientWebSocket();
        var url = $"{_settings.ElevenLabsOrigin}/v1/convai/conversation?agent_id={_settings.ElevenLabsAgentId}";
        await ws.ConnectAsync(new Uri(url), ct);
        // Suppress the agent's greeting: with no override, the first agent_response is the
        // configured first message, not the answer to this user_message.
        await Send(ws, new
        {
            type = "conversation_initiation_client_data",
            conversation_config_override = new { agent = new { first_message = "" } },
        }, ct);
        await Send(ws, new { type = "user_message", text }, ct);

        var buf = new byte[16384]; var sb = new StringBuilder();
        while (ws.State == WebSocketState.Open)
        {
            sb.Clear(); WebSocketReceiveResult r;
            do { r = await ws.ReceiveAsync(buf, ct); sb.Append(Encoding.UTF8.GetString(buf, 0, r.Count)); }
            while (!r.EndOfMessage);

            using var doc = JsonDocument.Parse(sb.ToString());
            switch (doc.RootElement.GetProperty("type").GetString())
            {
                case "agent_response":
                    return doc.RootElement.GetProperty("agent_response_event")
                              .GetProperty("agent_response").GetString();
                case "ping":
                    await Send(ws, new { type = "pong", event_id = doc.RootElement
                        .GetProperty("ping_event").GetProperty("event_id").GetInt32() }, ct);
                    break;
            }
        }
        return "Sorry, I couldn't reach the agent.";
    }

    private static Task Send(ClientWebSocket ws, object msg, CancellationToken ct) =>
        ws.SendAsync(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(msg)),
            WebSocketMessageType.Text, true, ct);
}
```

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:

```json
"bots": [
  { "botId": "YOUR_APP_ID", "supportsCalling": true, "scopes": ["personal", "team", "groupChat"] }
]
```

> **Note**
>
> 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](/docs/sv/eleven-agents/customization/personalization/overrides) — 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.

> **Tip**
>
> Om chattsvar aldrig kommer fram aktiverar du klient-
> händelsen **`agent_response`** [client event](/docs/sv/eleven-agents/customization/events/client-events) 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:

```csharp
await this.Call.DeleteAsync(); // after a short delay so the goodbye audio finishes
```

## 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:

```csharp
var target = new IdentitySet { User = new Identity { Id = humanObjectId } };
await this.Call.Participants.InviteAsync(target, replacesCallId: null);
// suppress the end-call hangup while transferring, and mute the bot
```

> **Tip**
>
> 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\`

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'\`

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).

## Användbara länkar

* [Översikt över samtals- och mötesbotar](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/calls-meetings-bots-overview)
* [Koncept för realtidsmedia](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/real-time-media-concepts)
* [Registrera en samtalsbot](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/registering-calling-bot)
* [microsoft-graph-comms-samples (EchoBot)](https://github.com/microsoftgraph/microsoft-graph-comms-samples)
* [call: transfer (konsultativ)](https://learn.microsoft.com/en-us/graph/api/call-transfer)
* [Agentens WebSocket-protokoll](/docs/sv/eleven-agents/libraries/web-sockets)