Customer Service
The Customer Service plugin provides 1v1 real-time audio/video customer service capabilities for Monibuca V6. It is suitable for online customer support, remote consultation, after-sales support, and similar scenarios.
Core Features
Section titled “Core Features”- 1v1 calls: Each session is limited to 2 participants (agent + customer), based on Room Service’s
max_users: 2constraint - No-login customer side: Customers can enter the call directly via link without account registration
- Agent management: Five-state machine (Offline/Online/Ready/Ringing/Busy), supports check-in/check-out, ready/busy
- Queue & dispatch system: Visitor queuing → FIFO auto-assignment → agent acceptance complete workflow
- Incoming call ringing: Agent receives call notification with 30s countdown, supports audio/video accept or reject
- Call transfer: Agent can transfer the call to another available agent without disconnecting the customer
- Satisfaction rating: Customers can provide 1-5 star ratings after call ends, backend provides rating statistics
- Audio mixing: Agent side can mix local audio files into the stream (e.g., background music, notification sounds)
- Admin dashboard: Complete session management interface with session creation, user link/QR code generation
How to Enable
Section titled “How to Enable”Set enable: true under the customer-service section in config.yaml (included in official binaries; depends on the built-in Room service).
Architecture Design
Section titled “Architecture Design”graph TB subgraph CS["CustomerService Plugin"] SM["SessionManager<br/>Session management (DashMap + SQLite)"] AP["AgentPool<br/>Agent pool (Round-Robin)"] VQ["VisitorQueue<br/>Queue (FIFO)"] RM["RingManager<br/>Ring management"] HTTP["HTTP API<br/>/customer-service/*"] Signal["WebSocket Signaling<br/>AcceptCall / EndCall / Transfer"] end
subgraph RS["Room Service (Engine Built-in)"] Room["Room Management<br/>max_users: 2"] WS["WebSocket<br/>Signaling"] end
subgraph Client["Clients"] Agent["Agent Side<br/>Account login"] Customer["Customer Side<br/>No login required"] end
CS -->|"register_callbacks<br/>RoomType::CustomerService"| RS HTTP --> SM HTTP --> AP HTTP --> VQ Agent -->|"WebRTC (WHIP)"| Room Customer -->|"WebRTC (WHIP)"| Room Agent <-->|"WebSocket"| WS Customer <-->|"WebSocket"| WSSession Lifecycle
Section titled “Session Lifecycle”Waiting → Active → Ended| Status | Description |
|---|---|
Waiting | Session created, waiting for agent/customer to join |
Active | Both parties have joined, call in progress |
Ended | Call has ended |
Agent State Machine
Section titled “Agent State Machine”Offline → Online → Ready → Ringing → Busy ↑ │ └──────────────────┘| Status | Description |
|---|---|
Offline | Not logged in / checked out |
Online | Checked in but not ready (break, wrap-up) |
Ready | Ready to accept calls (dispatch target) |
Ringing | Call offered, awaiting accept/reject (default 30s timeout) |
Busy | Currently in a call |
State transitions:
- Agent registers →
Ready - Call dispatched →
Ringing(30s timeout auto-returns toReady, visitor re-queued) - Accept →
Busy - Call ended →
Ready - Reject →
Ready(visitor re-queued) - Go offline →
Offline
Queue & Dispatch
Section titled “Queue & Dispatch”- FIFO queue: Visitors queue in arrival order, max queue size configurable (default 200)
- Polling dispatch: Backend checks queue every 500ms, uses Round-Robin algorithm to select ready agents
- Two-phase dispatch: Dequeue → agent enters Ringing → accept to establish call
- Instant dispatch: If an agent is available when visitor joins, queue is skipped
- Timeout cleanup: Queue entries removed after timeout (default 10 minutes)
HTTP API
Section titled “HTTP API”All endpoints are prefixed with /customer-service/.
Session Management
Section titled “Session Management”| Method | Path | Description |
|---|---|---|
GET | /sessions | Get session list |
GET | /sessions/{id} | Get session details |
POST | /sessions | Create new session |
DELETE | /sessions/{id} | Close/delete session |
POST | /sessions/{id}/assign | Manually assign agent |
POST | /sessions/{id}/transfer | Transfer call to another agent |
POST | /sessions/{id}/rate | Submit satisfaction rating |
GET | /sessions/{id}/rating | Get session rating |
Agent Management
Section titled “Agent Management”| Method | Path | Description |
|---|---|---|
POST | /agents/register | Register agent (go online/ready) |
POST | /agents/{id}/offline | Agent go offline |
POST | /agents/{id}/available | Set agent to ready |
POST | /agents/{id}/accept | Accept incoming call |
POST | /agents/{id}/reject | Reject incoming call |
GET | /agents | List all agents |
GET | /agents/available | List ready agents |
GET | /agents/stats | Agent pool statistics |
Queue Management
Section titled “Queue Management”| Method | Path | Description |
|---|---|---|
POST | /queue/join | Visitor join queue (instant dispatch if agent available) |
POST | /queue/leave | Visitor leave queue |
GET | /queue/status | Queue status snapshot |
GET | /queue/position/{visitor_id} | Get queue position |
Statistics
Section titled “Statistics”| Method | Path | Description |
|---|---|---|
GET | /stats | Combined statistics (sessions + agents + queue + ratings) |
GET | /stats/ratings | Rating statistics (total, average, distribution) |
GET | /stats/trend?days=7 | Daily session trend |
Per-endpoint details
Section titled “Per-endpoint details”Default base URL: http://localhost:8180
1) Create session
Section titled “1) Create session”POST /customer-service/sessionsContent-Type: application/jsonRequest body:
{ "title": "After-sales inquiry", "customer_id": "cust_001", "customer_name": "John"}| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Session title |
customer_id | string | Yes | Customer ID |
customer_name | string | No | Customer display name |
1.1) Session list
Section titled “1.1) Session list”GET /customer-service/sessionsResponse fields:
| Field | Type | Description |
|---|---|---|
sessions | array | Session list |
count | int | Total sessions |
1.2) Session details
Section titled “1.2) Session details”GET /customer-service/sessions/{id}| Param | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Session ID |
Response (example):
{ "session_id": "cs_abc123", "status": "waiting", "created_at": "2026-05-07T19:05:00+08:00"}2) Register agent
Section titled “2) Register agent”POST /customer-service/agents/registerContent-Type: application/jsonRequest body:
{ "agent_id": "agent_001", "agent_name": "Agent Wang"}2.1) Agent list and availability
Section titled “2.1) Agent list and availability”GET /customer-service/agentsGET /customer-service/agents/availableGET /customer-service/agents/stats3) Join queue
Section titled “3) Join queue”POST /customer-service/queue/joinContent-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
visitor_id | string | Yes | Visitor ID |
visitor_name | string | No | Visitor name |
preferred_skill | string | No | Optional skill group |
Queue responses can be assigned (immediate dispatch) or queued.
3.1) Queue status and position
Section titled “3.1) Queue status and position”GET /customer-service/queue/statusGET /customer-service/queue/position/{visitor_id}| Param | Type | Required | Description |
|---|---|---|---|
visitor_id | string | Conditional | Required for position lookup |
4) Transfer session
Section titled “4) Transfer session”POST /customer-service/sessions/{id}/transferContent-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
target_agent_id | string | Yes | Target agent ID |
5) Submit rating
Section titled “5) Submit rating”POST /customer-service/sessions/{id}/rateContent-Type: application/jsonRequest body:
{ "rating": 5, "comment": "Great service"}| Field | Type | Required | Description |
|---|---|---|---|
rating | int | Yes | Score from 1 to 5 |
comment | string | No | Text feedback |
6) Statistics endpoints
Section titled “6) Statistics endpoints”GET /customer-service/statsGET /customer-service/stats/ratingsGET /customer-service/stats/trend?days=7| Param | Type | Required | Description |
|---|---|---|---|
days | int | No | Trend range days, default 7 |
Error responses
Section titled “Error responses”| HTTP Status | Scenario |
|---|---|
400 | Missing/invalid fields |
404 | Session/agent not found |
409 | State conflict (e.g. agent not Ready) |
429 | Queue limit exceeded or too frequent requests |
Quick call example
Section titled “Quick call example”Authoritative field definitions and error codes are in the detailed section above.
Minimal example:
curl -X POST http://localhost:8180/customer-service/sessions \ -H "Content-Type: application/json" \ -d '{"title":"After-sales inquiry","customer_id":"cust_001"}'WebSocket Signaling
Section titled “WebSocket Signaling”Customer service calls use dedicated WebSocket signaling, which is forwarded to the plugin through the Room Service’s on_message callback.
Signaling Types
Section titled “Signaling Types”| Action | Direction | Description |
|---|---|---|
accept_call | C→S | Agent accepts the call |
reject_call | C→S | Agent rejects the incoming call |
end_call | C→S | Either party hangs up |
transfer_call | C→S | Agent transfers to another agent |
mute_user | C→S | Mute a participant |
unmute_user | C→S | Unmute a participant |
incoming_call | S→C | Incoming call notification (with visitor_name, timeout_secs) |
ring_timeout | S→C | Ring timeout notification |
call_accepted | S→C | Notify that the call has been answered |
call_ended | S→C | Notify that the call has ended |
call_transferred | S→C | Notify that the call has been transferred |
transfer_failed | S→C | Transfer failed notification |
agent_assignment | S→C | Agent assignment notification |
Signaling Example
Section titled “Signaling Example”{ "type": "control", "data": { "type": "AcceptCall" }}{ "type": "control", "data": { "type": "TransferCall", "data": { "target_agent_id": "agent_002" } }}Configuration
Section titled “Configuration”customer_service: max_sessions: 1000 # Maximum concurrent sessions session_timeout_secs: 3600 # Session timeout (seconds), default 1 hour max_queue_size: 200 # Maximum queue size dispatch_interval_ms: 500 # Auto-dispatch polling interval (ms) queue_timeout_secs: 600 # Queue timeout (seconds), default 10 minutes accept_timeout_secs: 30 # Incoming call accept timeout (seconds), default 30s auto_record: false # Enable call recording recording_dir: "/tmp/cs-recordings" # Recording output directoryWebSocket Connection
Section titled “WebSocket Connection”Clients join customer service calls via the standard Room WebSocket connection:
ws://host:port/room?type=customer_serviceThe room ID format is customer-service/{session_id}, using a prefix to distinguish different room types.
Web-SDK Integration
Section titled “Web-SDK Integration”Web Components
Section titled “Web Components”The customer service demo is built on Monibuca Web-SDK’s Web Components:
<!-- Room container --><mb-room id="room"></mb-room>
<!-- Local publisher --><mb-publisher id="publisher"></mb-publisher>
<!-- Remote subscriber --><mb-subscriber id="subscriber"></mb-subscriber>Initialize Connection
Section titled “Initialize Connection”const room = document.getElementById('room') as MbRoom;const publisher = document.getElementById('publisher') as MbPublisher;
// Set up WebSocket connectionroom.setAttribute('ws-url', 'ws://localhost:8180/room?type=customer_service');room.setAttribute('room-id', 'customer-service/session_001');
// Start publishingawait publisher.startCapture({ audio: true, video: true });await publisher.startPublish();Audio Mixing
Section titled “Audio Mixing”The agent side supports mixing local audio files into the stream, such as background music or waiting notification sounds:
const publisher = document.getElementById('publisher') as MbPublisher;
// Mix in a local audio filepublisher.mixAudio('bgm', '/audio/background-music.mp3', 0.3);
// Adjust mix volume (0.0 ~ 1.0)publisher.setMixVolume('bgm', 0.5);
// Remove mix sourcepublisher.unmixAudio('bgm');Mixing principle:
graph LR Mic["Microphone<br/>MediaStream"] --> GainA["GainNode<br/>Mic volume"] BGM["Audio File<br/>MediaElement"] --> GainB["GainNode<br/>Mix volume"] GainA --> Dest["Destination<br/>Combined output"] GainB --> Dest Dest --> WHIP["WHIPClient<br/>WebRTC publish"]Internally, the SDK uses the Web Audio API’s AudioContext to mix multiple audio sources (microphone + mix files) through GainNode into a single MediaStreamAudioDestinationNode, which is then output to the WebRTC stream.
Call State Management
Section titled “Call State Management”It is recommended to use a state machine to manage the call flow:
type CallStage = 'waiting' | 'connecting' | 'connected' | 'ended';
// waiting → Waiting for the other party to join (display waiting UI, pulse animation)// connecting → WebRTC connection being established// connected → Call in progress (display video, timer, control bar)// ended → Call ended (display call duration, satisfaction rating)Admin Dashboard
Section titled “Admin Dashboard”The customer service module provides a complete management interface in the Admin dashboard.
Agent Workstation
Section titled “Agent Workstation”- Auto-ready: Agent automatically registers as ready when entering the workstation
- Real-time dashboard: Queue length, ready agents, busy agents shown in real-time
- Auto-dispatch: System auto-assigns visitors, agent enters call without manual action
- Manual entry: Fallback option to manually enter session ID
Call Features
Section titled “Call Features”- Call controls: Microphone/camera toggle, screen sharing
- Call transfer: Click “Transfer” button during call, select an available agent
- Text chat: Real-time text chat panel during call
- Call statistics: Bitrate, packet loss, RTT displayed in real-time
Session Management
Section titled “Session Management”- Statistics cards: Total sessions, active calls, waiting for connection
- Session list: Supports status filtering, search, batch operations, rating display
- Create session: Enter title and description, auto-assign agent
- Assign agent: Manually assign a session to a specific agent
- Generate link: Generate dedicated entry links and QR codes for customers/agents
Satisfaction Statistics
Section titled “Satisfaction Statistics”- Average rating: Dashboard displays average satisfaction rating across all sessions
- Rating distribution: 1-5 star distribution chart
- Session list rating column: Each ended session shows customer rating stars
Room Report Statistics
Section titled “Room Report Statistics”Customer service room data is collected through the Room Service’s reporting system and automatically filtered by the customer-service/ prefix for display in the Admin.
Demo Project
Section titled “Demo Project”The complete customer service demo is located at web-sdk/packages/demo/customer-service/:
customer-service/├── src/│ ├── pages/│ │ ├── Lobby/index.tsx # Entry: role selection│ │ ├── CallRoom/index.tsx # Call: 1v1 video, controls, chat, rating│ │ ├── AgentConsole/index.tsx # Agent workstation: queue monitor, incoming call│ │ └── QueueWaiting/index.tsx # Customer queue waiting page│ ├── services/api.ts # API wrapper│ └── types/index.ts # Type definitions├── package.json # port: 5476└── vite.config.tsStart the Demo
Section titled “Start the Demo”cd web-sdk/packages/demo/customer-servicepnpm installpnpm dev# Visit http://localhost:5476Customer Entry
Section titled “Customer Entry”Customers enter the call directly via a parameterized link without logging in:
http://localhost:5476?session=cs_abc123&role=customerAgent Entry
Section titled “Agent Entry”Agents need to log in with credentials and enter the agent workstation:
http://localhost:5476?session=cs_abc123&role=agentAgent Workstation
Section titled “Agent Workstation”After login, the agent enters the AgentConsole page:
- Click “Go Online” to register as ready
- Real-time display of queue length and online agent count
- Incoming call triggers a full-screen ring panel (30-second countdown)
- Supports “Video Accept”, “Audio Accept”, “Reject” actions
- After accepting, automatically navigates to the CallRoom
Mobile Adaptation
Section titled “Mobile Adaptation”The demo automatically detects device type. On mobile devices:
- Top-bottom split video layout
- Fixed bottom control bar (with safe area adaptation)
- Touch-optimized interactions