# Teams Bot Service AI-powered Microsoft Teams meeting bot. Joins meetings, captures live transcripts, monitors chat, and responds via voice and/or chat messages. ## Architecture ``` ┌───────────────┐ ┌───────────────────────┐ │ │ WebSocket │ │ │ Gateway │◄──────────────────────────────────►│ Bot Service │ │ │ transcripts, status, chat, │ │ │ ● AI engine │ audioChunks, voiceGreeting │ Joins Teams meetings │ │ ● TTS │ │ as a participant │ │ ● Sessions │ playAudio, sendChatMessage, │ │ │ ● Billing │ stopAudio │ Capabilities: │ │ │ │ ├ Live transcripts │ │ │ HTTP │ ├ Chat messages │ │ │────────────────────────────────────► ├ Voice playback │ └───────────────┘ join, leave, status │ └ Audio capture │ └───────────────────────┘ ``` | Path | Protocol | Purpose | |------|----------|---------| | Gateway ↔ Bot | WebSocket | Real-time transcript, chat, audio, status exchange | | Gateway → Bot | HTTP | Session control (join, leave, status) | ## Integration Guide ### How It Works 1. Gateway sends a **POST** to the Bot with a meeting URL and optional credentials 2. Bot joins the meeting and appears as a regular participant 3. A **WebSocket** connection is established for real-time data exchange 4. Bot streams transcript segments and chat messages to the Gateway 5. Gateway can send TTS audio or chat responses back into the meeting ### Step 1: Start a Session ```http POST /api/bot Content-Type: application/json { "sessionId": "550e8400-e29b-41d4-a716-446655440000", "meetingUrl": "https://teams.microsoft.com/meet/123456789?p=abc123", "botName": "AI Assistant", "instanceId": "feature-instance-uuid", "gatewayWsUrl": "wss://gateway.example.com/api/teamsbot/ws", "language": "de-DE", "botAccountEmail": "bot@example.com", "botAccountPassword": "decrypted-password", "transferMode": "caption" } ``` | Field | Required | Description | |-------|----------|-------------| | `sessionId` | Yes | Unique session UUID (generated by Gateway) | | `meetingUrl` | Yes | Teams meeting URL (classic or short format) | | `botName` | No | Display name in meeting (default: env `BOT_NAME`) | | `instanceId` | No | Feature instance ID for Gateway WebSocket path | | `gatewayWsUrl` | No | Gateway WebSocket base URL (default: env `GATEWAY_WS_URL`) | | `language` | No | BCP-47 language code (default: `de-DE`) | | `botAccountEmail` | No | Microsoft account for authenticated join | | `botAccountPassword` | No | Decrypted password for authenticated join | | `transferMode` | No | `caption` or `audio` | If `botAccountEmail` + `botAccountPassword` are provided, the bot joins as an authenticated user. Otherwise, it joins as an anonymous guest. **Response:** ```json { "success": true, "sessionId": "550e8400-e29b-41d4-a716-446655440000", "message": "Bot deployment initiated" } ``` ### Step 2: Receive Data via WebSocket After deployment, the Bot connects to the Gateway at: ``` wss://{gatewayHost}/api/teamsbot/{instanceId}/bot/ws/{sessionId} ``` #### Messages: Bot → Gateway **Transcript segment:** ```json { "type": "transcript", "sessionId": "...", "transcript": { "speaker": "Jane Doe", "text": "Hey Bot, can you summarize this?", "timestamp": "2026-02-18T10:30:00.000Z", "isFinal": true } } ``` **Chat message:** ```json { "type": "chatMessage", "sessionId": "...", "chat": { "speaker": "Jane Doe", "text": "Please summarize the discussion", "timestamp": "2026-02-18T10:31:00.000Z" } } ``` **Status update:** ```json { "type": "status", "sessionId": "...", "status": "joined", "message": "Bot joined the meeting" } ``` Status values: `connecting` | `in_lobby` | `joined` | `left` | `error` **Voice greeting request** (bot asks Gateway for TTS): ```json { "type": "voiceGreeting", "sessionId": "...", "text": "Hello, I am ready.", "language": "de-DE" } ``` **Raw audio chunk** (`transferMode: "audio"` only): ```json { "type": "audioChunk", "sessionId": "...", "audio": { "data": "", "sampleRate": 16000, "format": "pcm16", "timestamp": "2026-02-18T10:30:00.500Z" } } ``` **Keepalive:** ```json { "type": "ping" } ``` #### Messages: Gateway → Bot **Play TTS audio:** ```json { "type": "playAudio", "sessionId": "...", "audio": { "data": "", "format": "mp3" } } ``` **Send chat message:** ```json { "type": "sendChatMessage", "sessionId": "...", "text": "Here is my summary of the discussion..." } ``` **Stop audio playback:** ```json { "type": "stopAudio", "sessionId": "..." } ``` **Keepalive response:** ```json { "type": "pong" } ``` ### Step 3: Leave the Meeting ```http POST /api/bot/:sessionId/leave ``` ```json { "success": true, "message": "Leave initiated" } ``` ### Step 4: Check Status ```http GET /api/bot/:sessionId/status ``` ```json { "sessionId": "550e8400-e29b-41d4-a716-446655440000", "state": "in_meeting", "error": null } ``` ### Health Check ```http GET /health ``` Returns `200 OK` with `{ "status": "ok", "timestamp": "..." }`. ## Meeting URL Formats Both formats are supported: ``` # Classic https://teams.microsoft.com/l/meetup-join/19%3ameeting_xxx/0?context=... # Short https://teams.microsoft.com/meet/123456789?p=abc123 ``` ## Running the Service ### Local ```bash npm install cp .env.sample .env # Configure Gateway URL, bot name, etc. npm run dev # Dev mode ``` ### Docker ```bash docker build -t teams-bot . docker run -p 4100:4100 \ -e GATEWAY_WS_URL=wss://gateway.example.com/api/teamsbot/ws \ teams-bot ``` ## Configuration | Variable | Description | Default | |----------|-------------|---------| | `PORT` | HTTP server port | `4100` | | `GATEWAY_WS_URL` | Gateway WebSocket base URL | — | | `BOT_NAME` | Default bot display name | — | | `LOG_LEVEL` | Log level (`debug`, `info`, `warn`, `error`) | `info` |