Skip to content

Configuration Reference

All options live under plugins.entries."msteams-voice".config. The schema is additionalProperties: false, so an unknown key is rejected. Defaults below come from the config resolver; secret-valued keys accept either a literal string or an OpenClaw secret reference.

KeyTypeDefaultMeaning
enabledbooltrueMaster on/off.
portint (1-65535)9442WebSocket server port.
bindAddressstring127.0.0.1Bind address. Use 0.0.0.0 so the hosted StandIn bridge can connect.
pathstring/voice/msteams/streamWebSocket route; StandIn connects to {path}/{callId}.
sharedSecretstring | secret-ref-HMAC secret; must match StandIn. Fails closed - a non-string coerces to empty and rejects all handshakes.
requireRecordingStatusbooltrueHold media processing until Teams reports recording is active.
inboundPolicyenumunset (deny all)disabled | allowlist | pairing | open. Unset or disabled rejects every inbound call - you must set a policy to receive calls. pairing currently behaves like allowlist.
allowFromstring[][]Allowlisted callers, matched by AAD object id (case-insensitive) or phone number (digits only). Empty + allowlist = deny all.
inboundGreetingstring-Opening line the agent speaks on answer.
modeenumautorealtime | streaming. Auto-selects realtime if a realtime provider resolves.
sessionScopeenum-Conversation continuity: per-phone | per-call | per-thread.
maxConcurrentCallsint4Concurrent active-call cap.
maxDurationSecondsint0 (unlimited)Hard cap on a single answered call’s duration.
staleCallReaperSecondsint120Tear down calls that stop being serviced after this long.
maxVisionPerMinuteint-Per-call vision spend cap.
meetingRecapbool-Post an end-of-call recap / minutes.
bilingualbool-Enable English/Arabic handling.
KeyTypeDefaultMeaning
groupCall.requireAddressbool-In meetings (2+ humans), speak only when addressed.
groupCall.wakePhrasesstring[]-Wake words that address the agent.
groupCall.followUpWindowMsint-After being addressed, keep listening for follow-ups for this long.

1:1 calls always answer regardless of these settings.

KeyTypeDefaultMeaning
realtime.providerenumopenaiThe realtime provider.
realtime.providers.<id>.apiKeysecret-Provider API key.
realtime.providers.<id>.modelstring-Model, e.g. gpt-realtime.
realtime.providers.<id>.azureEndpointstring-Azure OpenAI endpoint (selects Azure).
realtime.providers.<id>.azureDeploymentstring-Azure deployment name.
realtime.instructionsstring-System instructions for the voice agent.
realtime.toolPolicyenumnoneWhich agent tools the voice model may call: safe-read-only | owner | none.
realtime.suppressInputDuringPlaybackbool-Echo guard: ignore input while the agent is speaking.
realtime.echoSuppressionWindowMsint-Echo-guard window.
realtime.echoBargeInRmsint-RMS threshold above which caller speech counts as barge-in.
KeyTypeDefaultMeaning
stt.providerstring-Transcription provider id (streaming mode).
stt.providers.<id>.apiKeysecret-STT provider key.

In streaming mode, TTS and the agent come from your OpenClaw configuration. If stt.provider is unset, the plugin uses your configured transcription provider, then a VAD-segmented file fallback.

KeyTypeDefaultMeaning
outbound.enabledbool-Enable outbound call-backs.
outbound.workerBaseUrlstring-StandIn outbound API base URL.
outbound.tenantIdstring-Your AAD tenant id for outbound.
outbound.answerTimeoutMsint120000No-answer timeout before voicemail/cancel.
outbound.defaultModeenum-notify (speak and hang up) | conversation.

See Outbound Calls.

These accept a literal string or an OpenClaw secret reference: sharedSecret, realtime.providers.*.apiKey, stt.providers.*.apiKey. Prefer secret references in production.

{
"plugins": {
"entries": {
"msteams-voice": {
"config": {
"enabled": true,
"mode": "realtime",
"bindAddress": "0.0.0.0",
"port": 9442,
"path": "/voice/msteams/stream",
"sharedSecret": "<same secret as in StandIn>",
"requireRecordingStatus": true,
"inboundPolicy": "allowlist",
"allowFrom": ["<caller AAD object id>"],
"inboundGreeting": "Hi, you've reached the assistant. How can I help?",
"sessionScope": "per-thread",
"maxConcurrentCalls": 4,
"maxVisionPerMinute": 30,
"meetingRecap": true,
"groupCall": {
"requireAddress": true,
"wakePhrases": ["assistant", "hey team"],
"followUpWindowMs": 8000
},
"realtime": {
"provider": "openai",
"providers": {
"openai": { "apiKey": "<key>", "model": "gpt-realtime" }
},
"toolPolicy": "safe-read-only",
"suppressInputDuringPlayback": true
}
}
}
}
}
}
"realtime": {
"provider": "openai",
"providers": {
"openai": {
"apiKey": "<azure-key>",
"azureEndpoint": "https://<resource>.cognitiveservices.azure.com",
"azureDeployment": "gpt-realtime"
}
}
}
"mode": "streaming",
"stt": {
"provider": "<your-stt-provider>",
"providers": { "<your-stt-provider>": { "apiKey": "<key>" } }
}