Microsoft Teams Bridge for ElevenLabs Agents
Welcome! @komaa/elevenlabs-msteams-bridge (npm: @komaa/elevenlabs-msteams-bridge) puts an ElevenLabs Agent on a real Microsoft Teams call.
It is a small Node.js service (and importable TypeScript library) that sits between two WebSockets:
flowchart LR
Teams["Microsoft Teams<br/>call"]
StandIn["StandIn media bridge<br/>(hosted service)"]
Bridge["this bridge<br/>(yours)"]
EL["ElevenLabs Agent<br/>STT + LLM + TTS + VAD"]
Teams <--> StandIn
StandIn -- "HMAC WS" --> Bridge
Bridge -- "WS" --> EL
The hosted StandIn media bridge (standin.komaa.com) joins the Teams call and dials into your bridge, one authenticated WebSocket per call. The bridge opens one ElevenLabs Agent conversation per call and relays between them. Both sides speak base64 PCM 16 kHz mono, so audio is copied verbatim in both directions: no resampling, no re-encoding, nothing added to the latency budget beyond a relay hop.
What it does
Section titled “What it does”- Realtime voice - the caller talks to your ElevenLabs agent and hears it reply. Turn-taking, VAD and interruption are the agent’s own; the bridge maps the caller’s barge-in onto the Teams side and drops stale “ghost” audio so nothing plays after an interruption.
- Per-call personalization - caller name, tenant and direction as
dynamic_variables; optional localized greeting or spoken AI disclosure; per-caller memory viauser_id(guests never share an identity). - Vision on demand - the agent’s
lookclient tool sees the caller’s camera or screen-share: your own vision model (path 2) or ElevenLabs multimodal upload (path 1, recording-gated). - Agent client tools -
end_call,express(avatar emotion),show_image(image on the bot’s tile, SSRF-guarded),look. - Two call governors - StandIn-side tier cutoffs get a spoken goodbye; a bridge-side
MAX_CALL_MINUTEShard cap protects your ElevenLabs budget. - Hardened transport - replay-proof HMAC handshake, connection and payload caps, duplicate-call rejection, graceful SIGTERM drain, and an ElevenLabs host allowlist so your API key can never be sent elsewhere.
Use the sidebar to navigate. Start with Getting Started, or jump to the Configuration Reference or Wire Protocol. There is also a runnable example project in the repository.