service-teams-browser-bot/README.md
ValueOn AG 6b4172c46a docs: add documentation, update README, add marketing page
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-18 17:51:28 +01:00

276 lines
6.7 KiB
Markdown

# 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": "<base64-encoded PCM16>",
"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": "<base64-encoded MP3>",
"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` |