| title | Quickstart | ||||||
|---|---|---|---|---|---|---|---|
| description | Install the plugin, connect it to StandIn, and place a test Teams call. | ||||||
| keywords |
|
Pick your runtime. Both paths get you to a live Teams call where your agent answers in voice.
- A working OpenClaw or Hermes Agent install (the host).
- A StandIn account (standin.komaa.com) - the hosted media bridge that joins the Teams call and connects to your plugin. No worker to run. A paid plan is not required to start: the free identity gives you one BYO-bot identity with 5 minutes of call time per day included.
- Your own Microsoft Teams bot (an Azure AD app) connected to StandIn - see the Teams setup to create and upload it.
The installer detects your OpenClaw or Hermes install, adds the matching plugin, and prompts for the settings (mode, shared secret, provider API key + model, inbound call policy). On a re-run every prompt defaults to your current configuration, so pressing Enter keeps each value.
Linux / macOS / WSL
curl -fsSL https://standin.komaa.com/install.sh | bashWindows (PowerShell)
irm https://standin.komaa.com/install.ps1 | iexIt also runs non-interactively - pass flags (--runtime, --mode, --secret, --provider,
--api-key, --model, --port) or set the matching STANDIN_* environment variables.
Pairing is the zero-config way to connect a subscribed identity: the installer exposes your voice
endpoint, sends StandIn the exact wss://host:<voicePort> URL, and delivers the generated shared secret back
to the installer automatically. There are no ports to configure and nothing to copy by hand, which avoids
the most common first-call issue (a domain saved without its voice port, so StandIn dials the wrong port and
the bot silently never joins).
Two free ways to run StandIn - pick by whether you have an Azure bot:
- You run the official
msteamschannel plugin (so you already have an Azure Bot App ID + secret; this is the normal OpenClaw/Hermes Teams journey): use a Free identity. It is the same BYO-bot setup as paid - your own bot, your own tenant, inbound calls to your own Teams identity - with 5 minutes of call time per day included, one free identity per account, held alongside any paid identities. - You have no Azure bot (you never installed the msteams channel plugin and just want to hear your agent talk): use the sandbox (community tier). A shared StandIn bot joins a public meeting StandIn generates - zero Azure setup.
`. **Hermes** replies to an unknown sender with a
**pairing code** instead of silence - approve it with `hermes pairing approve teams `; only
when `TEAMS_ALLOWED_USERS` is set are unlisted senders dropped silently. See
[Troubleshooting](/troubleshooting#the-bot-answers-calls-but-ignores-teams-chat-dm-pairing).
Prefer not to pipe a script straight into your shell? Download it, review it, then run it:
Download:
```bash
curl -fsSL https://standin.komaa.com/install.sh -o install.sh
```
Review it:
```bash
less install.sh
```
Run it:
```bash
bash install.sh
```
Download:
```powershell
irm https://standin.komaa.com/install.ps1 -OutFile install.ps1
```
Review it:
```powershell
notepad install.ps1
```
Run it:
```powershell
./install.ps1
```
Always fetch over HTTPS from standin.komaa.com. The installer never transmits your secrets; they
are only written to your local plugin config.
Prefer to wire it up by hand? Pick your runtime:
```bash
openclaw plugins install npm:@komaa/openclaw-msteams-bridge
```
The package ships prebuilt (v0.1.10+), so there is no build step - install and go.
Also on ClawHub: `openclaw plugins install clawhub:@komaa/openclaw-msteams-bridge` (OpenClaw falls back to
npm automatically if the ClawHub fetch fails). See the
[plugin README](https://github.com/komaa-com/openclaw-msteams-bridge#install).
Add a `msteams-voice` entry to your OpenClaw config - `sharedSecret` must match the value you set in StandIn:
```jsonc
{
"plugins": {
"entries": {
"msteams-voice": {
"config": {
"enabled": true,
"mode": "realtime",
"port": 9442,
"path": "/voice/msteams/stream",
"sharedSecret": "",
"inboundPolicy": "allowlist",
"allowFrom": [""],
"realtime": {
"provider": "openai",
"providers": {
"openai": { "apiKey": "", "model": "gpt-realtime" }
}
}
}
}
}
}
}
```
Full reference → [OpenClaw configuration](/openclaw/configuration).
Start the gateway (`openclaw gateway run`), then in your StandIn dashboard register your
**Agent voice URL** (`wss://:8443/voice/msteams/stream` via the funnel; local bind `ws://:9442/...`) and the matching secret. Place a Teams call to your bot.
Into the **same Python environment as Hermes**:
```bash
uv pip install --python /path/to/hermes/venv/bin/python hermes-msteams-bridge
```
Then enable the plugin:
```bash
hermes plugins enable teams_voice
```
In `~/.hermes/config.yaml` under `plugins.entries.teams_voice.config` (secrets in `.env`):
```yaml
plugins:
enabled: [teams_voice]
entries:
teams_voice:
config:
shared_secret: ${TEAMS_VOICE_SHARED_SECRET} # must match the secret set in StandIn
host: 127.0.0.1
port: 8443
# Inbound caller policy: Hermes has no `inboundPolicy` key and no
# pairing mode for calls - the allowlist IS the policy. Empty means
# deny all inbound callers (set `allow_all: true` to opt out).
allowlist: [""]
realtime:
backend: azure
azure_endpoint: https://.cognitiveservices.azure.com
azure_deployment: gpt-realtime
api_key: ${AZURE_FOUNDRY_API_KEY}
```
Full reference → [Hermes configuration](/hermes/configuration).
```bash
hermes teams-voice serve --handler realtime
```
In your StandIn dashboard, register your **Agent voice URL** (`wss://:8443/voice/msteams/stream` via the funnel; local bind `ws://:8443/...`)
and the matching secret, then place a Teams call to your bot.
**StandIn connects to your plugin from the internet**, so its WebSocket must be reachable - expose it
via a public URL or a tunnel (e.g. Tailscale), not loopback-only. Default ports **9442** (OpenClaw) /
**8443** (Hermes); path `/voice/msteams/stream`. A `sharedSecret` mismatch fails the HMAC handshake
**silently** - the most common first-call issue.
Streaming mode (no realtime key needed) is a one-line change - see [Modes](/concepts/modes).