diff --git a/src/data/nav/chat.ts b/src/data/nav/chat.ts index ad8ca06013..2a2dd27210 100644 --- a/src/data/nav/chat.ts +++ b/src/data/nav/chat.ts @@ -200,6 +200,10 @@ export default { name: 'Export chat messages', link: '/docs/guides/chat/export-chat', }, + { + name: 'Support chat', + link: '/docs/guides/chat/support-chat', + }, ], }, ], diff --git a/src/images/content/chat/support-chat.png b/src/images/content/chat/support-chat.png new file mode 100644 index 0000000000..e20705f422 Binary files /dev/null and b/src/images/content/chat/support-chat.png differ diff --git a/src/pages/docs/guides/chat/support-chat.mdx b/src/pages/docs/guides/chat/support-chat.mdx new file mode 100644 index 0000000000..5b9ef65985 --- /dev/null +++ b/src/pages/docs/guides/chat/support-chat.mdx @@ -0,0 +1,444 @@ +--- +title: "Guide: Building a support chat application with Ably" +meta_description: "Architecting support chat with Ably: from customer widget to agent dashboard. Bot automation, AI integration, multi-room management, and real-world patterns for scalable support." +meta_keywords: "support chat, help desk, customer support, agent dashboard, Ably Chat, chat SDK, realtime messaging, AI support, chatbot, dependability" +--- + +Building support chat is unlike other chat applications. There are two distinct interfaces to consider in a support chat system: the customer-facing widget and the agent dashboard. The customer-facing widget requires reliable messaging, presence detection, typing indicators, and seamless reconnection. Ably Chat handles all of these challenges for you. The agent dashboard presents a different class of complexity: managing multiple concurrent conversations, discovering new tickets in realtime, coordinating between agents. For both, integrating automation and AI is key to reducing the workload on agents and improving the customer experience. + +This guide covers both sides of a support chat system with Ably, with particular attention to the architectural patterns that make agent dashboards work at scale. + +
+```json
+{
+ "support:user-343:*": [
+ "publish",
+ "subscribe",
+ "presence"
+ ]
+}
+```
+
+
+### Typing indicators
+
+[Typing indicators](/docs/chat/rooms/typing) are a common feature in most chat applications. They show when someone is actively composing a message, helping to:
+
+* **Manage expectations:** Users know when a response is being prepared.
+* **Reduce duplicate messages:** See that someone is already addressing the question.
+* **Improve flow:** Better chat pacing.
+
+In Ably Chat typing indicators are a core feature with a simple API:
+
+
+```javascript
+const room = await chatClient.rooms.get('support-ticket-123');
+
+// show who's typing
+room.typing.subscribe((event) => {
+ console.log('Currently typing:', event.currentlyTyping);
+});
+
+// attach the room
+await room.attach();
+
+// show a typing indicator (call on every keystroke, Ably Chat SDKs throttle this to a predefined interval)
+await room.typing.keystroke();
+
+// stop the typing indicator (for example when a message is sent)
+await room.typing.stop();
+```
+
+
+### Message reactions
+
+Message reactions are a ubiquitous feature in modern chat experiences and are a great way to enhance engagement and enable users to quickly express sentiment to key points in the chat.
+
+Send a message reaction:
+
+
+```javascript
+const message; // your message
+await room.messages.reactions.send(message.serial, {name: '👍'});
+```
+
+
+Message reactions in Ably Chat come in three types: `unique`, `distinct`, and `multiple`, to suit different use cases: from one reaction per message to multiple reactions per message with or without counts. See the [Message reactions](/docs/chat/rooms/message-reactions) documentation for more details.
+
+### Message history
+
+Message history is crucial for chat, ensuring continuity and context even when participants join mid-chat or return after interruptions.
+
+Ably stores [chat history](/docs/chat/rooms/history) for 30 days by default, with options to extend up to a year on request.
+
+Message history provides users with:
+
+* **Ticket continuity:** New participants can quickly understand the current state and previous decisions, preventing repeated questions and ensuring a seamless support experience.
+* **Context preservation:** Users returning to a ticket don't lose important information.
+* **Audit trail:** Complete chat records for compliance, training, or dispute resolution.
+
+
+```javascript
+// Get the chat room
+const room = await chatClient.rooms.get('support:ticket-123');
+
+// Subscribe to messages
+const subscription = room.messages.subscribe((messageEvent) => {
+ console.log('Received:', messageEvent);
+ // handle message event to update state and UI
+});
+
+// attach the room
+await room.attach();
+
+// Load recent history for context
+// This ensures you get a complete picture without missing messages
+let historyResponse = await subscription.historyBeforeSubscription({limit: 50});
+
+// Iterate through all pages
+while (true) {
+ console.log('Messages: ', historyResponse.items);
+ if (historyResponse.hasNext()) {
+ historyResponse = await historyResponse.next();
+ } else {
+ break;
+ }
+}
+```
+
+
+### Presence: see when agents and customers are online
+
+[Presence](/docs/chat/rooms/presence) shows who is currently active in the room, enabling you to bring more live context to your application. You can display in realtime when an agent joins the room, along with their status, such as "Available" or "Gathering context, will join shortly". You can also display to the agent if the customer is still active, and attach information about the customer.
+
+Beyond online or offline status, presence can include rich information about the user, such as their name, avatar, role, and other details.
+
+
+```javascript
+// subscribe to presence events
+const { unsubscribe } = room.presence.subscribe((event) => {
+ console.log(`${event.member.clientId} entered with data: ${event.member.data}`);
+
+ const presentMembers = await room.presence.get();
+ console.log('Present members:', presentMembers);
+});
+
+// attach the room
+await room.attach();
+
+// join presence
+await room.presence.enter({ status: 'available' });
+
+// change presence data
+await room.presence.update({ status: 'will be back shortly' });
+
+// leave presence
+await room.presence.leave();
+```
+
+Presence can also be used to share data about the current user to the support agent, such as what page they are currently on, to assist them better with their query.
+
+## Assigning tickets to agents
+
+With the customer-facing widget handling message delivery and presence, the next challenge is connecting those conversations to agents. A key part of a support system is deciding how tickets reach the right agent at the right time. You can either do this on your server as tickets are created by tracking agent workload, or by broadcasting all tickets to all agents in a shared queue.
+
+How do agents know about new tickets without being attached to every room?
+
+The pattern is a dedicated Pub/Sub channel where your server publishes notifications when tickets need agent attention. Agents subscribe to this single channel to learn about all tickets requiring action, without attaching to each room individually. This approach scales efficiently because agents receive lightweight notifications rather than subscribing to every active room.
+
+
+```javascript
+const channel = realtimeClient.channels.get('support:inbox');
+
+// send new ticket info
+channel.publish('new-ticket',{
+ ticketId: "123",
+ roomName: "support:ticket-123",
+ summary: "Question about building support chat",
+ customerName: "John Doe",
+ customerId: "123",
+});
+```
+
+
+Your server publishes to this channel when:
+
+- A new ticket is created and needs agent attention (after automation).
+- A customer returns to an existing ticket.
+- AI couldn't resolve and escalates to human.
+- A human agent reassigned the ticket to another agent.
+
+Each notification includes metadata: ticket ID, room name, and a summary. This information helps agents decide which tickets to pick up. When an agent selects a ticket, they attach to that specific room to start working.
+
+Depending on how you assign tickets to agents, you may need to use a single channel for all tickets, or a separate channel for each agent, team, or department.
+
+### Server-side ticket assignment
+
+If you assign agents on your server, Ably can help you notify agents of new tickets and chats requiring attention. In this pattern, assign a Pub/Sub channel to each agent, for example `agent:inbox:
+```javascript
+const channel = realtimeClient.channels.get('agent:inbox:123');
+channel.publish('new-ticket',{
+ ticketId: "123",
+ roomName: "support:ticket-123",
+ summary: "Question about building support chat",
+ customerName: "John Doe",
+ customerId: "123",
+});
+```
+
+
+Depending on your requirements, you may choose to use more restrictive access control such that each agent can only see and join the tickets they are assigned to.
+
+### Shared inbox queue
+
+If you don't assign tickets to agents on the server, you can use a shared inbox channel, for example `support:inbox`. This Pub/Sub channel is subscribed to by all agents. When a new ticket is created, publish it to this channel:
+
+
+```javascript
+const channel = realtimeClient.channels.get('support:inbox');
+channel.publish('new-ticket',{
+ ticketId: "123",
+ roomName: "support:ticket-123",
+ summary: "Question about building support chat",
+ customerName: "John Doe",
+ customerId: "123",
+});
+```
+
+
+Optionally you can enable [push notifications](/docs/push/publish#via-channels) on this channel to alert agents of new tickets even if they don't have the app or page open.
+
+All agents receive this message and display the new ticket with a summary, without attaching to the chat room.
+
+When an agent starts working on a ticket, save the assignment in your system and publish a message on the inbox channel to remove the ticket from the queue. If the ticket needs to be reassigned, publish another message to the inbox channel to add it back to the queue.
+
+
+```javascript
+const channel = realtimeClient.channels.get('support:inbox');
+
+// publish the fact that a ticket was assigned
+channel.publish('ticket-assigned',{
+ ticketId: "123",
+ roomName: "support:ticket-123",
+});
+```
+
+
+When the agents dashboard receives this message, it removes the ticket from the inbox if it was displayed. Your server remains responsible for conflict resolution if multiple agents try to work on the same ticket. You can create an endpoint that handles assignment where only the first agent to claim a ticket succeeds. Ably provides the realtime updates after tickets have been assigned.
+
+### Team or department inbox
+
+Instead of using a channel per agent, use a channel per team or department, for example `support:sales` or `support:engineering`. Follow the same pattern as the server-side ticket assignment to decide which channel to use for each ticket, then apply the shared inbox queue pattern for tickets that reach a team or department.
+
+This hybrid approach works well for organizations with specialized teams: route tickets to the appropriate department first, then let agents within that team claim them from the shared queue.
+
+## Agent dashboard
+
+The agent dashboard is where support chat demands careful architectural thinking. Agents need to see and respond to multiple tickets, know when new tickets need attention, coordinate with other agents, and access context and AI assistance.
+
+Ably's architecture supports this complexity without requiring you to manage connection pooling, message routing, or server infrastructure. Agents can work efficiently across many tickets while Ably handles the realtime communication layer.
+
+### Multi-room management
+
+Agents handle multiple tickets, but attaching to many chat rooms simultaneously isn't practical. The pattern is to attach only to chat rooms the agent is currently viewing or working on, and detach when switching away.
+
+Each attachment maintains a subscription with new messages, typing indicators, and presence updates. Keeping attachments focused reduces client-side memory, network traffic, and cost. Attach to rooms when agents start working on the relevant ticket and detach when the ticket is resolved, paused, or reassigned.
+
+### Agent presence and availability
+
+Agents need to signal their status and availability with other agents, for the whole application or their team. This is separate to the presence information displayed to customers. We call this app-wide presence, even though it can be scoped to a team or department.
+
+**App-wide presence** uses a dedicated channel (for example, `support:agents`, or `support:agents-sales`) where agents enter presence when they sign in and update their status (available, busy, away) and current workload. Other agents and routing systems can see who is online and available.
+
+This is different to the **room-level presence** which connects the agent to individual chat rooms and customers. When an agent opens a ticket room, they enter presence with their role and name, providing reassurance that help has arrived. Agents can also see if customers are still active.
+
+### Push notifications for agents
+
+Agents aren't always watching the dashboard. You can use Ably to send [push notifications](/docs/push) to alert agents of important events, such as:
+
+- New tickets in their inbox.
+- Mentions from other agents.
+- Customer activity on tickets assigned to them.
+
+## Adding AI to the loop
+
+AI chatbots are revolutionizing the way we interact with digital platforms. Integrating an AI agent (such as an LLM) into your support chat flow can reduce the workload for your agents and provide faster responses to customers. AI can also help support agents be more effective by providing contextual information and suggested responses. Additionally, AI can help you analyze past chats for training, monitoring, and building knowledge bases.
+
+Ably's flexible [integrations](/docs/chat/integrations) make it straightforward to connect your chat system with AI services. Through Ably's integrations, you can automatically route messages to:
+
+* Serverless functions (AWS Lambda, Azure Functions, and others).
+* Event streaming services including Kafka, SQS, and Pulsar.
+* Webhooks and custom endpoints.
+* An [Ably Queue](/docs/platform/integrations/queues).
+
+### Example architecture for adding an LLM to your support chat
+
+When a customer opens a new support request, your server:
+
+1. Creates a new ticket.
+2. Issues a JWT token for Ably Chat to give the customer access to the ticket's chat room.
+3. An integration routes each message to an AI service, which responds:
+ - Directly to the customer with a message by publishing it to the chat room.
+ - Or escalates to a human agent with the full context of the chat by pushing the ticket to the agent's inbox channel.
+
+You need to signal to the integrations when the ticket is no longer handled by AI. Keep a flag in your system that controls whether AI or a human agent handles the ticket. Always check this flag before calling an AI tool.
+
+### Example architecture for aiding support agents with AI
+
+Beyond handling customer conversations directly, AI can work alongside human agents to make them more effective. AI can assist agents in several ways:
+
+- Drafting responses for agents.
+- Searching for similar tickets and how they were resolved.
+- Providing a list of common questions and answers relevant to the current chat.
+- Providing a list of knowledge base articles.
+- Summarizing the context of the ticket, such as previous tickets from this customer or recent purchase history.
+
+Implement this client-side in the agent dashboard, where each message from the chat is passed to your backend or AI service as it arrives. The responses can be rendered in a sidebar where the agent can review, copy and paste, or read the information to help answer the customer's questions faster.
+
+
+## Ticket resolution and archiving
+
+Whether resolved by AI or a human agent, every ticket eventually reaches its conclusion. When a ticket is resolved, update its status in your system, optionally collect customer feedback, and export the chat history for long-term storage.
+
+**Collecting feedback:** A straightforward approach is to send a feedback request message when the agent marks the ticket resolved. The customer responds with a rating (for example, emojis or stars), which your server captures and associates with the ticket.
+
+**Exporting chat history:** Ably Chat excels at realtime messaging, but your support system likely needs features Ably doesn't provide: full-text search across all tickets, long-term storage spanning years, analytics, and compliance reporting. This means exporting chat history from Ably into your own systems.
+
+The simplest export strategy for support is to fetch the complete message history when a ticket is closed:
+
+1. Your ticket management logic marks a ticket as resolved.
+2. This triggers an export: fetch all messages from the room using the Chat SDK's history API.
+3. Store the messages in your archive system (database, object storage, or others).
+4. Associate the archive with the ticket for future reference.
+
+If the ticket is reopened and more messages are exchanged, re-export the full history when it closes again. The complete chat history is always available via Ably's history API.
+
+For more sophisticated export patterns such as continuous ingestion and streaming, see the [exporting chat data guide](/docs/guides/chat/export-chat).
+
+## Production-ready checklist
+
+The patterns in this guide handle the core architecture. Before you go live with your support chat, review these key points to ensure your implementation is production-ready:
+
+* **Authentication strategy:** Ensure you're using token authentication for all client-side communication with appropriate capabilities for each participant. Make sure capabilities are configured correctly for each type of participant (agents and customers).
+* **Scale planning:** Confirm you are on the right Ably package for your expected volume of concurrent tickets.
+* **Error handling:** Implement proper error handling for network disruptions and ensure graceful degradation.
+* **Data retention:** Verify your message history retention policy aligns with your compliance requirements.
+* **Export strategy:** Set up a process for archiving closed tickets to your long-term storage.
+* **AI integrations:** Ensure AI integrations are configured correctly and are ready to handle the expected volume of messages.
+* **Push notifications:** Test push notifications in all scenarios and all supported platforms.
+
+
+## Next steps
+
+* **Explore Ably Chat:** Dive into the [Ably Chat documentation](/docs/chat) for comprehensive API details and advanced features.
+* **Try the examples:** Play around with [chat examples](/examples?product=chat) to see real implementations.
+* **Get started quickly:** Follow the [React UI Kit](/docs/chat/getting-started/react-ui-kit), [JavaScript/TypeScript](/docs/chat/getting-started/javascript), or [React](/docs/chat/getting-started/react) getting started guides. On mobile? Check out our [Swift](/docs/chat/getting-started/swift) and [Kotlin](/docs/chat/getting-started/android) getting started guides.
+* **Add intelligence:** Learn how to integrate [AI assistance](/docs/chat/integrations) for smarter support experiences.
+* **Secure your chats:** Understand [token authentication](/docs/auth/token#jwt) for production-ready security.
+* **Export chat data:** Implement [chat data export](/docs/guides/chat/export-chat) for compliance and analytics.
+* **Build embedded chat:** See the [embedded chat guide](/docs/guides/chat/build-embedded-chat) for additional implementation patterns.