Skip to main content
Config lives under plugins.entries."msteams-voice".config in your OpenClaw config. sharedSecret must match the secret you set in StandIn for the hosted bridge that connects to this plugin’s media WebSocket.

Mode selection

Set mode to "realtime" or "streaming". If omitted, the runtime auto-selects realtime when a realtime provider resolves, else streaming. Both modes honor the inbound allowlist, outbound call-backs, recording gate, and sessionScope agent memory. See Modes.
In streaming mode, TTS and the agent/model come from your OpenClaw configuration. STT uses a live transcription session - selected by stt.provider / stt.providers if set, else your openclaw-configured transcription provider; if none resolves it falls back to VAD-segmented file transcription. The realtime.* block is ignored except the echo-guard knobs (suppressInputDuringPlayback, echoSuppressionWindowMs, echoBargeInRms), which apply in both modes.

Outbound call-backs (optional, either mode)

placeCall(userObjectId, { message, mode }) is implemented on the runtime (no-answer / declined → voicemail / no-answer); the outbound block enables it.
workerBaseUrl is StandIn’s outbound API URL from your dashboard - not a server you host.

Key reference

What inboundPolicy: "pairing" actually does today. The plugin issues no pairing codes, expirations, or approval prompts for inbound calls: with "pairing", a caller is accepted only if their AAD object id (or phone number) is already in allowFrom - exactly the same check as "allowlist". A rejected caller is logged with their caller id and the call is closed. The openclaw pairing approve msteams ... flow you may know from the chat channel manages chat DM approvals only; it does not populate this voice allowFrom. Until a real call-pairing flow ships, prefer "allowlist" and manage allowFrom yourself; "pairing" is accepted so such configs keep working with identical (allowlist) behavior.
Treat sharedSecret and all provider apiKey values as secrets - keep them out of source control.

Microsoft Graph permissions

You bring your own Teams bot: register an Azure AD app + Azure Bot resource in your tenant, admin-consent the required application permissions, and point its calling webhook at StandIn (the URL is shown in your StandIn dashboard). See the canonical Graph permissions table on the Create the Azure bot page.