The Messaging module powers live conversations between customers and staff. One namespace, one Redis-backed presence store, one queue. The same socket carries customer widget traffic and the agent admin console — role is derived from the JWT and gating happens server-side.
What's in the box
ChatGateway— Socket.IO gateway at namespace/chat. Customers and agents both connect here. JWT in the handshake; role (customervsagent) is derived from the principal datatype, never from the client.ChatService— REST endpoints under/chat/*for message CRUD, history, transcripts, file uploads, and chat config lookup.ChatPresenceService— Redis-backed online/away/offline state for agents and customers. Multi-pod safe. Identity sets, per-socket TTLs, keyspace-expiry timers for inactivity timeouts.ChatQueueService— Sorted Redis queues with priority and skill-based routing. ETA =ceil(position / availableAgents) * avgHandleTimeSeconds.- AI assistant integration —
AIAssistantServicestreams tokens straight into the chat room. AI chats can be observed live by agents and handed off viatransfer_chat_to_agent. - WebRTC bridge — Agents can broadcast audio/video to customer widgets using ICE servers from
GET /chat/ice-servers.
How a customer chat actually flows
- 1
Customer connects
The widget opens a socket to
/chatwith{ token, orgId, context }in the handshake. Server verifies the JWT, derivesrole = 'customer', joins the customer to:identity:{orgId}:customer:{email}— every tab/device for this userchat:{orgId}:{chatId}— the active conversation
If
context.configIdis set, the server resolves the chat config and sends the AI greeting on first connect. - 2
Customer sends
chat-messageIf the config has an
aiassistant and no human agent is assigned, the message goes toAIAssistantService.executeStream(). Tokens stream back aschat-streamevents (event: 'chunk' | 'tool-use' | 'tool-result' | 'end').If there's no AI configured, no assistant selected, or the chat has been transferred — the message is enqueued via
ChatQueueServiceand online agents are notified withqueue-notification. - 3
Agent picks up
An agent emits
pick-next. The customer is moved out of the queue, both parties are joined to the same chat room, an "agent has joined" system message is broadcast, and inactivity timers start ticking (4-min warning, 30-min hard close). - 4
Either side can transfer or end
Agents can
transfer-chat,takeover-chat(from AI),resume-ai, orclose-chat. Each emits structured events that update the customer widget without a reload.
Where to go next
- WebSocket API — every event the gateway accepts and emits
- Message history & search — REST CRUD over conversations
- Presence — agent and customer online state
- Queue routing — picking, skills, ETAs
- AI assistant — streaming responses and human hand-off
The chat namespace is the same across customers, staff, and broadcast viewers. Authentication and per-handler ACLs decide what each role can do — there are no separate "customer" and "agent" gateways.