This is a standalone Node service, not a framework plugin. You do not install it into an
agent runtime - you run the bridge and point StandIn at it. ElevenLabs hosts the agent itself.
Prefer Python? The same bridge exists as a Python package:
elevenlabs-msteams-bridge on PyPI
(pip install elevenlabs-msteams-bridge), with its own
docs site and
repo. Same wire protocol, same
environment variables, same hardening - pick the runtime that fits your stack. This page follows
the Node package.How it works
Audio is relayed verbatim - both sides speak base64 PCM 16 kHz, so there is no transcoding on the call path. The bridge opens one ElevenLabs Agent WebSocket per call (wss://api.elevenlabs.io/v1/convai/conversation), mints a short-lived signed URL for private
agents, maps caller barge-in to ElevenLabs interruptions, and injects caller context.
ElevenLabs agent conversations are realtime WebSocket connections (one socket per call), not
webhooks. ElevenLabs post-call webhooks are a separate, optional feature for pushing a transcript
or analysis to your own server after a call ends - unrelated to the live audio path, and not
required by the bridge.
Requirements
- Node.js
>= 20. - An ElevenLabs agent (Agents dashboard) with its audio input and output format set to PCM 16000 Hz, plus an API key.
- A StandIn subscription (standin.komaa.com, free package works) - the hosted media bridge that joins the Teams call and connects to this service. See Architecture.
- Your own Microsoft Teams bot connected to StandIn - the Teams setup walks through the Azure bot, the app package, and the upload. To try it without one, use the sandbox.
Run
Env-configured, no install step needed:npm i @komaa/elevenlabs-msteams-bridge) and embed it - see the
library API for the
programmatic surface and a custom vision hook.
The bridge serves one endpoint:
PORT moves the port; the default is 9442. There is no path variable: the bridge reads the
last path segment of the upgrade URL as the callId and accepts whatever base path you
register, so use /msteams/calling - the same path OpenClaw, Hermes and LiveKit use, so one StandIn
identity URL shape works for every backend. /healthz and /metrics stay at the root.
Voice only. This bridge has no chat lane. It serves the calling WebSocket,
/healthz and
/metrics, and nothing else - there is no /api/messages, so leave the Agent messages URL
empty on the identity. Teams chat comes from a runtime that has its own messaging channel
(OpenClaw or Hermes).Expose the WebSocket (Agent calling URL)
StandIn connects to the bridge from the internet, so the endpoint must be reachable - a public host, or a tunnel. Expose your agent carries the mount commands, the other tunnels (cloudflared, ngrok, devtunnel), and the probes that tell a working mount from a registered one. Use the LiveKit / ElevenLabs tab: this bridge is voice only, so it needs/msteams/calling on port
9442 and no /api/messages.
Your Agent calling URL is then - note there is no port:
Path routing lets a second bridge share the same machine on its own path. Whole-port mounts and
the other tunnels, which publish the port rather than the path, are covered in
Expose your agent.
Connect it to StandIn
Register that URL (with a matching shared secret) on your identity in the dashboard, or use the sandbox to try it without your own Teams bot:- Set the identity’s Agent calling URL to where the bridge listens. Leave the Agent messages URL empty - this bridge has no chat lane.
- Set
BRIDGE_SECRETto the shared secret from pairing - both sides must match exactly, or the WebSocket handshake is rejected with401. - Place a Teams call (or join the sandbox meeting). StandIn joins, connects to the bridge, and your ElevenLabs agent answers.
Try the runnable example
The fastest way to understand the bridge is to run its example project - a minimal, working embedding you can copy straight into your own repo.Run the example, step by step
Clone
examples/basic-bridge, fill in three environment variables, expose the port, connect it
to StandIn, and place a call - with the vision hook explained along the way.Next: the full configuration reference - every environment variable,
the call governor, and vision. Deep protocol and library docs live on the
project site.