Skip to main content

Microsoft Teams Bridge for ElevenLabs Agents (Python)

CI PyPI version Python versions docs MIT License Ruff PRs Welcome

Bridge Microsoft Teams voice/video calls to an ElevenLabs Agent.

PyPI package: elevenlabs-msteams-bridge - the -py suffix is only in this repository's name, to distinguish it from the Node.js sibling repo.

This is the Python sibling of @komaa/elevenlabs-msteams-bridge (Node.js) - same wire contract, same environment variables, drop-in interchangeable behind the same .env file. The Node and Python packages version independently, so a version-number gap between them is expected; both implement the same StandIn wire protocol and interoperate with the hosted service identically. It terminates the StandIn media bridge wire protocol on one side and the ElevenLabs Agent WebSocket on the other:

  • No transcoding: both sides speak base64 PCM 16 kHz mono - the hot path is copy-only.
  • Barge-in: ElevenLabs interruptions map to playback flushes, with ghost-audio filtering.
  • On-demand vision: the agent's look client tool answers from the caller's camera or screen-share, via your own OpenAI-compatible vision endpoint (frames never persisted) or via ElevenLabs multimodal upload (gated on Teams recording).
  • Call governors: a bridge-side hard time cap with a deterministic TTS goodbye, plus the worker-side governor.
  • Hardened: HMAC-signed upgrades with replay guard, connection caps, SSRF-guarded image fetches, dead-peer detection, graceful SIGTERM drain, Prometheus /metrics.

StandIn is the hosted media bridge that joins the Teams call and dials this bridge - you run no Teams media stack yourself.

Documentation: komaa-com.github.io/elevenlabs-msteams-bridge-py (getting started, example walkthrough, configuration and library reference, wire protocol). Teams/StandIn setup lives at docs.komaa.com.

Install

pip install elevenlabs-msteams-bridge

Requires Python 3.10+.

Run

ELEVENLABS_API_KEY=sk_... \
ELEVENLABS_AGENT_ID=agent_... \
WORKER_SHARED_SECRET=... \
elevenlabs-msteams-bridge

A .env file in the working directory is loaded automatically (existing environment wins). The bridge listens on ws://0.0.0.0:8080/voice/msteams/stream by default; StandIn appends /{callId} per call. Expose the port with a tunnel and register the wss:// URL as your identity's Agent voice URL in the StandIn dashboard.

Your ElevenLabs agent's audio input and output format must be PCM 16000 Hz - the bridge ends the call with a clear error if the agent negotiates anything else.

Embed

import asyncio
from elevenlabs_msteams_bridge import load_config, start_server

async def main():
    server = await start_server(load_config())
    await asyncio.Event().wait()  # run until cancelled

asyncio.run(main())

Pass your own async vision callable to answer the agent's look tool with any model you like - the raw frame never leaves your process:

async def describe(frame: dict, question: str) -> str:
    ...  # call your vision model with frame["dataBase64"] / frame["mime"]
    return "a person holding a badge"

server = await start_server(load_config(), vision=describe)

Configuration

Everything is environment variables; names are identical to the Node package.

Variable Required Default Meaning
ELEVENLABS_API_KEY yes - Server-side ElevenLabs key (signed URLs, file upload, TTS).
ELEVENLABS_AGENT_ID yes - The agent that answers calls.
WORKER_SHARED_SECRET yes - Must equal the shared secret from StandIn pairing (HMAC upgrade check).
PORT / BIND no 8080 / 0.0.0.0 Listen port / bind address.
MAX_CALL_MINUTES no 0 (off) Bridge-side hard cap per call; on expiry a goodbye is spoken, then the call ends.
EL_TTS_VOICE_ID no - Voice for the deterministic goodbye via standalone TTS.
EL_TTS_MODEL_ID no eleven_turbo_v2_5 TTS model for the goodbye line.
GOODBYE_TEXT / GOODBYE_GRACE_MS no (default line) / 8000 Goodbye wording and playout grace.
EL_FIRST_MESSAGE no - Greeting/disclosure override (must be allowlisted on the agent).
EL_HOST no api.elevenlabs.io Regional pins: api.us / api.eu.residency / api.in.residency / api.sg.residency .elevenlabs.io. Restricted to elevenlabs.io hosts.
EL_ENVIRONMENT / EL_AGENT_BRANCH_ID no - Staging environment / pinned agent branch.
VISION_API_URL / VISION_API_KEY / VISION_MODEL no - OpenAI-compatible chat-completions endpoint for the look tool (describe-then-inject).
HMAC_FRESHNESS_MS no 60000 Allowed clock skew + replay window for the signed upgrade.
MAX_CONNECTIONS / MAX_CONNECTIONS_PER_IP no 64 / = total Connection caps.
PRE_START_TIMEOUT_MS no 10000 Drop a worker that authenticates but never sends session.start.
WORKER_IDLE_TIMEOUT_MS no 90000 Dead-peer window (the worker heartbeats every 30 s).
TRUST_PROXY_XFF no false Trust the first X-Forwarded-For hop for the per-IP cap.
TLS_CERT_PATH / TLS_KEY_PATH no - Serve native TLS (wss). Otherwise front the plain WS with a TLS terminator.
LOG_TRANSCRIPTS no false Log transcripts - still gated on Teams recording being active.
LOG_LEVEL no info debug / info / warn / error.

Endpoints

  • GET /healthz - liveness.
  • GET /metrics - Prometheus counters (calls, rejections, relayed/dropped frames).
  • GET /{...}/{callId} + WebSocket upgrade - the worker wire, HMAC-signed with X-OpenClawTeamsBridge-Timestamp / X-OpenClawTeamsBridge-Signature over "{timestampMs}.{callId}".

Notes for operators:

  • /healthz and /metrics are unauthenticated (only the WebSocket upgrade is HMAC-gated). They expose no call content - just liveness and counters - but if you would rather not leak call volumes, keep the port behind your ingress/tunnel rules.
  • One bridge process serves one agent id (ELEVENLABS_AGENT_ID). Run one process per agent if you route multiple agents.

Vision and recording

The look tool prefers your VISION_API_URL endpoint: the frame is described transiently and only the text enters the conversation. Without one, the bridge falls back to uploading the frame to ElevenLabs (multimodal) - that persists the frame with a third party, so it is only allowed while Teams recording is active. Note that even path-2 descriptions become ElevenLabs conversation content, which ElevenLabs retains per your agent's settings; enable the agent's zero-retention mode if callers' surroundings must not be stored.

License

MIT (c) Komaa DigiTech

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elevenlabs_msteams_bridge-0.2.4.tar.gz (52.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elevenlabs_msteams_bridge-0.2.4-py3-none-any.whl (42.5 kB view details)

Uploaded Python 3

File details

Details for the file elevenlabs_msteams_bridge-0.2.4.tar.gz.

File metadata

File hashes

Hashes for elevenlabs_msteams_bridge-0.2.4.tar.gz
Algorithm Hash digest
SHA256 d82de07661bd833951260d1c0075409b06c236bc51a651d68d26045218526956
MD5 2c4bfe3517a88b4f8f0f181baac64163
BLAKE2b-256 98d4562b95bafa82c90a31e0f348cf1ffbacb653be234cf802283e2b96384e70

See more details on using hashes here.

Provenance

The following attestation bundles were made for elevenlabs_msteams_bridge-0.2.4.tar.gz:

Publisher: publish.yml on komaa-com/elevenlabs-msteams-bridge-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file elevenlabs_msteams_bridge-0.2.4-py3-none-any.whl.

File metadata

File hashes

Hashes for elevenlabs_msteams_bridge-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7d5a4f33ea7df924fef1d3d9d7b16fd91420e641b3956566030786ca702d2fbb
MD5 72ce682f8296af99e81fd91b804dd6c6
BLAKE2b-256 4d69a58e300cc642b231f56cdeaf9d999b8b1c4cd495d98f16cbc7bca8a273dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for elevenlabs_msteams_bridge-0.2.4-py3-none-any.whl:

Publisher: publish.yml on komaa-com/elevenlabs-msteams-bridge-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.6

2 files

0.2.5

2 files

This release

0.2.4 This release

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page