diff --git a/_posts/2025-11-27-copilot-studio-handover-live-agent.md b/_posts/2025-11-27-copilot-studio-handover-live-agent.md
new file mode 100644
index 0000000..f31d9e2
--- /dev/null
+++ b/_posts/2025-11-27-copilot-studio-handover-live-agent.md
@@ -0,0 +1,675 @@
+---
+layout: post
+title: "Handing Over Copilot Studio Agent Conversations to Live Agents"
+date: 2025-11-27
+categories: [copilot-studio, tutorial, integration]
+tags: [handover, escalation, live-chat, skills, proactive-messaging, microsoft-teams]
+description: Build a seamless handover from Copilot Studio agents to external live chat systems using skills and MS Teams proactive messaging.
+author: placeholder
+---
+
+# Why Hand Over to Live Agents?
+
+AI agents excel at handling routine queries efficiently, but complex scenarios often require human expertise. The challenge: how do you seamlessly escalate from bot to human while maintaining conversation context and enabling bidirectional communication?
+
+This post demonstrates a production-ready pattern for handing over Copilot Studio conversations to third-party live chat systems and returning them back to the agent—complete with full context preservation and real-time message exchange.
+
+## What You'll Build
+
+- A Copilot Studio skill that bridges agent conversations to live chat systems
+- Bidirectional message flow using MS Teams proactive messaging
+- Conversation state management across systems
+- A mock live chat app demonstrating the integration pattern (adaptable to your own system)
+
+> This pattern uses Microsoft Teams proactive messaging, limiting it to the Teams channel. Other channels don't support the async communication required for live agent responses.
+{: .prompt-warning }
+
+## Prerequisites
+
+- .NET 9.0 SDK installed
+- Copilot Studio environment with agent creation permissions
+- Microsoft Teams channel enabled for your agent
+- Azure AD tenant with App Registration permissions
+- [Dev tunnel](https://learn.microsoft.com/azure/developer/dev-tunnels/get-started) for local development and testing
+
+## Solution Overview
+
+The handover pattern consists of three interconnected components:
+
+### 1. HandoverToLiveAgentSample (.NET 9.0 Skill)
+
+A Copilot Studio skill that acts as the bridge between your agent and external live chat systems. This skill handles:
+
+- **Event processing**: Responds to `startConversation` and `endConversation` events from Copilot Studio
+- **Message forwarding**: The `OnMessageAsync` handler sends user messages from Teams to the live chat system
+- **Conversation mapping**: Maintains bidirectional relationships between Copilot and live chat conversation IDs
+- **Proactive messaging**: Sends live agent responses back to MS Teams users
+
+**Key components:**
+- `CopilotStudioAgent.cs`: Main agent handling Copilot Studio activities
+- `ConversationManager.cs`: Manages conversation ID mappings and metadata
+- `LiveChatService.cs`: Communicates with the external live chat API
+- `LiveChatWebhookController.cs`: Receives webhook messages from live agents
+- `MsTeamsProactiveMessage.cs`: Handles MS Teams proactive messaging
+
+### 2. ContosoLiveChatApp (Mock Live Chat System)
+
+A simple demonstration app simulating a third-party customer service platform. **This is where you'll plug in your own live chat system.**
+
+The mock app provides:
+- REST API for starting/ending conversations
+- Message receiving endpoint for incoming user messages
+- Webhook sender for outgoing agent responses
+- Simple web UI for live agents to view and respond to conversations
+
+### 3. HandoverAgentSample.zip (Copilot Studio Solution)
+
+Pre-built Copilot Studio agent with customized topics:
+- **"Escalate to Live Chat"**: Triggers the handover using `startConversation` and `sendMessage` skills
+- **"Goodbye Live Chat"**: Ends the handover session and returns control to the agent
+
+## How It Works
+
+Understanding the message flow is crucial for implementing this pattern. Here's the complete sequence from escalation to resolution:
+
+```mermaid
+sequenceDiagram
+ participant User as MS Teams User
+ participant CS as Copilot Studio
+ participant Skill as Agent Skill
+ participant LC as Live Chat API
+ participant Agent as Live Agent
+
+ User->>CS: "I want to talk with a person"
+ CS->>Skill: Event: startConversation
+ Skill->>LC: POST /api/chat/start
+ LC-->>Skill: conversationId
+ Note over Skill: Store mapping
(copilotId ↔ liveChatId)
+ Skill-->>CS: EndOfConversation (success)
+
+ User->>CS: Send message
+ CS->>Skill: Message activity
+ Note over Skill: Update mapping
with activity details
+ Skill->>LC: POST /api/chat/receive
+ LC-->>Agent: Display message
+
+ Agent->>LC: Send response
+ LC->>Skill: POST /api/livechat/messages (webhook)
+ Skill->>CS: Proactive message (MS Teams)
+ CS-->>User: Display response
+
+ User->>CS: "Good bye"
+ CS->>Skill: Event: endConversation
+ Skill->>LC: POST /api/chat/end
+ Note over Skill: Remove mapping
+ Skill-->>CS: EndOfConversation (success)
+```
+
+The key insight: the skill maintains a persistent mapping between the Copilot Studio conversation and the live chat session, enabling messages to flow in both directions asynchronously.
+
+## Setup Steps
+
+### Step 1: Setup Dev Tunnel
+
+For local development, create a dev tunnel to expose your local endpoints:
+
+```powershell
+# Authenticate with your Microsoft account
+devtunnel login
+
+# Create a tunnel (replace with a unique identifier)
+devtunnel create --allow-anonymous
+
+# Create port forwarding for the skill endpoint
+devtunnel port create -p 5001
+
+# Start hosting the tunnel
+devtunnel host
+```
+
+Note the generated URL—you'll need it in later configuration steps.
+
+### Step 2: Run the Applications
+
+Open two terminal windows and run both applications:
+
+**Terminal 1 - HandoverToLiveAgentSample (Skill):**
+```powershell
+dotnet run --project .\HandoverToLiveAgentSample\HandoverToLiveAgentSample.csproj
+```
+Available at: `http://localhost:5001`
+
+**Terminal 2 - ContosoLiveChatApp (Mock Live Chat):**
+```powershell
+dotnet run --project .\ContosoLiveChatApp\ContosoLiveChatApp.csproj
+```
+Available at: `http://localhost:5000`
+
+### Step 3: Import Solution to Copilot Studio
+
+1. Download `HandoverAgentSample.zip` from the repository
+2. Navigate to your Copilot Studio environment
+3. Import the solution and configure environment variables:
+ - `[Contoso Agent] Handoff Skill endpointUrl`: `https://-5001.euw.devtunnels.ms/api/messages`
+ - `[Contoso Agent] Handoff Skill msAppId`: (use your new `LiveChatSample` app registration AppID explained in the step below)
+
+### Step 4: Configure App Registrations
+
+This sample uses **two separate service principals (SPNs)** for enhanced security and proper service URL routing. You'll need to configure both:
+
+#### App Registration 1: CopilotStudioBot (Auto-created by Copilot Studio)
+
+After importing the solution, Copilot Studio automatically creates an Azure AD App Registration for your agent:
+
+1. Find the App Registration with Client ID matching your Agent App ID (found in Copilot Studio > Settings > Advanced > Metadata)
+2. Navigate to "Certificates & secrets"
+3. Create a new client secret and copy its value
+4. Note the **Client ID** and **Client Secret** for later use
+
+#### App Registration 2: LiveChatSample (Custom Service Principal)
+
+Create a second App Registration for the live chat integration:
+
+1. In Azure Portal, go to **Entra ID** > **App registrations** > **New registration**
+2. Name it `LiveChatSample`
+3. Select "Accounts in this organizational directory only"
+4. Click **Register**
+5. Navigate to "Branding & properties" and set "Home page URL" to: `https://-5001.euw.devtunnels.ms/api/messages`
+6. Navigate to "Certificates & secrets"
+7. Create a new client secret and copy its value
+8. Note the **Client ID** (Application ID) and **Client Secret**
+
+> Store both client secrets securely—you won't be able to view them again. For production, use Azure Key Vault.
+{: .prompt-danger }
+
+### Step 5: Update Configuration Files
+
+Now configure the skill with authentication details for **both service principals**:
+
+**appsettings.json** (in HandoverToLiveAgentSample project):
+```json
+{
+ "LiveChatSettings": {
+ "BaseUrl": "http://localhost:5000"
+ },
+ "Connections": {
+ "LiveChat": {
+ "ConnectionType": "AzureAD",
+ "Settings": {
+ "TenantId": "your-tenant-id",
+ "ClientId": "your-livechat-app-id",
+ "ClientSecret": "your-livechat-client-secret",
+ "Scopes": ["https://api.botframework.com/.default"]
+ }
+ },
+ "CopilotStudioBot": {
+ "ConnectionType": "AzureAD",
+ "Settings": {
+ "TenantId": "your-tenant-id",
+ "ClientId": "your-bot-app-id",
+ "ClientSecret": "your-bot-client-secret",
+ "Scopes": ["https://api.botframework.com/.default"]
+ }
+ }
+ },
+ "ConnectionsMap": [
+ {
+ "ServiceUrl": "https://smba*",
+ "Connection": "CopilotStudioBot"
+ },
+ {
+ "ServiceUrl": "https://pvaruntime*",
+ "Connection": "LiveChat"
+ }
+ ]
+}
+```
+
+**Understanding the Two-SPN Pattern:**
+
+The `ConnectionsMap` section is critical—it maps service URL patterns to specific credentials:
+
+- **SMBA URLs** (`https://smba*`): MS Teams proactive messaging uses the **CopilotStudioBot** SPN (Copilot Studio's app registration)
+- **PVA Runtime URLs** (`https://pvaruntime*`): Direct Copilot Studio runtime uses the **LiveChat** SPN (your custom app registration)
+
+This dual-SPN approach provides:
+1. **Security isolation**: Separate credentials for different runtime contexts
+2. **Proper authentication**: Each service URL gets the correct App ID for proactive messaging
+3. **Flexibility**: Easy to add more service URL patterns as needed
+
+**skill-manifest.json** (in HandoverToLiveAgentSample/wwwroot):
+```json
+{
+ "endpointUrl": "https://-5001.euw.devtunnels.ms/api/messages",
+ "msAppId": "your-livechat-app-id"
+}
+```
+
+Use the **LiveChatSample** App ID here (not the CopilotStudioBot App ID). This determines which credentials the skill uses when Copilot Studio initially invokes it.
+
+> If you modify skill-manifest.json after initial setup, refresh the skill in Copilot Studio for changes to take effect.
+{: .prompt-tip }
+
+### Step 6: Publish and Test
+
+1. Publish your agent in Copilot Studio
+2. Add it to the "Teams and Microsoft 365 Copilot" channel
+3. Open Microsoft Teams and start a conversation
+4. Trigger the escalation by saying "I need to talk to a person"
+5. Open the Contoso Live Chat app at `http://localhost:5000`
+6. Respond as a live agent and watch messages flow bidirectionally
+
+## Key Implementation Details
+
+Let's examine the core code patterns that make this handover work.
+
+### Handling Conversation Events
+
+The skill responds to two special events from Copilot Studio:
+
+```csharp
+// HandoverToLiveAgentSample/CopilotStudio/CopilotStudioAgent.cs
+
+private async Task OnEventAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken ct)
+{
+ if (turnContext.Activity.Name == "startConversation")
+ {
+ // User wants to escalate - create a new live chat session
+ var liveChatConversationId = await liveChatService.StartConversationAsync();
+
+ // Store the mapping between Copilot and live chat IDs
+ await conversationManager.UpsertMappingByCopilotConversationId(
+ turnContext.Activity, liveChatConversationId);
+
+ // Signal success back to Copilot Studio
+ await turnContext.SendActivityAsync(new Activity
+ {
+ Type = ActivityTypes.EndOfConversation,
+ Name = "startConversation",
+ Code = EndOfConversationCodes.CompletedSuccessfully
+ }, ct);
+ }
+ else if (turnContext.Activity.Name == "endConversation")
+ {
+ // User is done with live agent - clean up
+ var mapping = await conversationManager.GetMapping(
+ turnContext.Activity.Conversation!.Id);
+
+ await liveChatService.EndConversationAsync(
+ mapping.LiveChatConversationId);
+
+ await conversationManager.RemoveMappingByCopilotConversationId(
+ turnContext.Activity.Conversation!.Id);
+ }
+}
+```
+
+The `startConversation` event initiates the handover, while `endConversation` cleans up when the user returns to the agent.
+
+### Managing Conversation Mappings
+
+The `ConversationManager` maintains the critical bidirectional mapping:
+
+```csharp
+// HandoverToLiveAgentSample/CopilotStudio/ConversationManager.cs
+
+public class ConversationMapping
+{
+ // Core identifiers for bidirectional lookup
+ public string CopilotConversationId { get; set; }
+ public string LiveChatConversationId { get; set; }
+
+ // Metadata needed for proactive messaging
+ public string UserId { get; set; }
+ public string? ChannelId { get; set; }
+ public string? ServiceUrl { get; set; }
+ public string? BotId { get; set; }
+ public string? BotName { get; set; }
+}
+```
+
+This mapping stores everything needed to send proactive messages back to Teams. The `ServiceUrl` is particularly important—it identifies the MS Teams SMBA region and determines which credentials to use.
+
+> The sample uses in-memory storage with static dictionaries. For production, replace this with Redis, Azure Cosmos DB, or another persistent store.
+{: .prompt-warning }
+
+### Receiving Messages from Live Agents
+
+When a live agent responds, the webhook controller receives the message and routes it back to Teams:
+
+```csharp
+// HandoverToLiveAgentSample/LiveChat/LiveChatWebhookController.cs
+
+[HttpPost("messages")]
+public async Task ReceiveMessageAsync([FromBody] MessageRequest request)
+{
+ // Look up which Copilot conversation this live chat session belongs to
+ var mapping = await _conversationManager.GetMapping(request.ConversationId);
+
+ // Send the agent's message back to Teams using proactive messaging
+ await _proactiveMessenger.SendTextAsync(
+ mapping, request.Message, request.Sender);
+
+ return Ok();
+}
+```
+
+The webhook pattern decouples the live chat system from the skill—the live chat system just needs to POST to this endpoint when agents send messages.
+
+### Service Principal Routing
+
+The skill uses different service principals depending on the runtime context. The `ResolveAppIdForServiceUrl` method in `MsTeamsProactiveMessage.cs` dynamically selects credentials:
+
+```csharp
+// HandoverToLiveAgentSample/CopilotStudio/MsTeamsProactiveMessage.cs
+
+private string? ResolveAppIdForServiceUrl(string serviceUrl)
+{
+ if (_configuration is null) return null;
+ var map = _configuration.GetSection("ConnectionsMap");
+ if (!map.Exists()) return null;
+
+ // Iterate through ConnectionsMap entries
+ foreach (var entry in map.GetChildren())
+ {
+ var pattern = entry.GetValue("ServiceUrl");
+ var connectionName = entry.GetValue("Connection");
+
+ // Check if service URL matches the pattern (supports wildcards)
+ if (WildcardMatch(serviceUrl, pattern))
+ {
+ // Retrieve the ClientId from the matched connection
+ var conn = _configuration.GetSection("Connections").GetSection(connectionName);
+ var clientId = conn.GetSection("Settings").GetValue("ClientId");
+ return clientId;
+ }
+ }
+ return null;
+}
+```
+
+**Why Two SPNs?**
+
+1. **Different runtime contexts**: MS Teams uses SMBA (Service Manager Bot API) URLs, while direct Copilot Studio calls use PVA runtime URLs
+2. **Authentication requirements**: Each runtime expects specific App IDs for token validation
+3. **Security best practices**: Separate credentials for different service boundaries
+
+**Service URL Patterns:**
+- `https://smba.trafficmanager.net/...`: MS Teams conversations (uses CopilotStudioBot SPN)
+- `https://pvaruntime.microsoft.com/...`: Copilot Studio runtime (uses LiveChat SPN)
+
+### Proactive Messaging to Teams
+
+Sending messages back to Teams requires proactive messaging capabilities:
+
+```csharp
+// HandoverToLiveAgentSample/CopilotStudio/MsTeamsProactiveMessage.cs
+
+public async Task SendTextAsync(ConversationMapping mapping, string text, string? senderName)
+{
+ // Resolve which App ID to use based on service URL
+ var appId = ResolveAppId(mapping.ServiceUrl);
+
+ // Create conversation reference for proactive messaging
+ var conversationReference = new ConversationReference
+ {
+ Conversation = new ConversationAccount { Id = mapping.CopilotConversationId },
+ ServiceUrl = mapping.ServiceUrl,
+ ChannelId = mapping.ChannelId,
+ Bot = new ChannelAccount { Id = mapping.BotId, Name = mapping.BotName },
+ User = new ChannelAccount { Id = mapping.UserId }
+ };
+
+ // Format message with sender's name
+ var formattedText = string.IsNullOrEmpty(senderName)
+ ? text
+ : $"**{senderName}**: {text}";
+
+ // Send proactive message
+ await _channelAdapter.ContinueConversationAsync(
+ appId,
+ conversationReference,
+ async (turnContext, ct) =>
+ {
+ await turnContext.SendActivityAsync(
+ MessageFactory.Text(formattedText), ct);
+ },
+ default);
+}
+```
+
+This method handles the complexity of MS Teams SMBA regions and ensures messages appear in the correct conversation.
+
+### Dependency Injection Setup
+
+The skill uses scoped and singleton services appropriately:
+
+```csharp
+// HandoverToLiveAgentSample/Program.cs
+
+builder.Services.AddScoped();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+
+// Register the main agent class
+builder.AddAgent();
+```
+
+`ConversationManager` is singleton to maintain state across requests, while `LiveChatService` is scoped for per-turn processing. The `CopilotStudioAgent` class must use scoped service resolution to access `LiveChatService` correctly.
+
+## Extending to Your Live Chat System
+
+The Contoso Live Chat app is a **mock example** demonstrating the integration pattern. Here's how to adapt it to your own live chat platform.
+
+### Understanding the Integration Contract
+
+Your live chat system needs to implement these capabilities:
+
+**1. Start Conversation API**
+When a user escalates, the skill calls this to create a new live chat session:
+
+```csharp
+// Your implementation of ILiveChatService
+public async Task StartConversationAsync()
+{
+ // Call your live chat API to create a session
+ // Example: POST https://your-livechat.com/api/sessions
+
+ var response = await _httpClient.PostAsync(
+ "https://your-livechat.com/api/sessions",
+ new StringContent("{}", Encoding.UTF8, "application/json"));
+
+ var data = await response.Content.ReadFromJsonAsync();
+
+ // Return the session ID from your system
+ return data.SessionId;
+}
+```
+
+**2. Send Message API**
+When users send messages through Teams, forward them to your live chat system:
+
+```csharp
+public async Task SendMessageAsync(string conversationId, string message, string userId)
+{
+ // Call your live chat API to deliver the user's message
+ // Example: POST https://your-livechat.com/api/sessions/{id}/messages
+
+ var payload = new
+ {
+ message = message,
+ senderId = userId,
+ senderType = "customer"
+ };
+
+ await _httpClient.PostAsJsonAsync(
+ $"https://your-livechat.com/api/sessions/{conversationId}/messages",
+ payload);
+}
+```
+
+**3. End Conversation API**
+When users return to the agent, clean up the live chat session:
+
+```csharp
+public async Task EndConversationAsync(string conversationId)
+{
+ // Call your live chat API to close the session
+ // Example: DELETE https://your-livechat.com/api/sessions/{id}
+
+ await _httpClient.DeleteAsync(
+ $"https://your-livechat.com/api/sessions/{conversationId}");
+}
+```
+
+### Configuring Webhooks
+
+Your live chat system must send agent responses back to the skill via webhook. Configure your platform to POST to:
+
+```
+https:///api/livechat/messages
+```
+
+**Expected webhook payload:**
+```json
+{
+ "conversationId": "live-chat-session-id",
+ "message": "Hello, I'm here to help!",
+ "sender": "Agent Name"
+}
+```
+
+Most enterprise live chat platforms (Salesforce Service Cloud, Zendesk, Intercom, etc.) support webhook notifications when agents send messages. Consult your platform's documentation for webhook configuration.
+
+### Authentication Considerations
+
+If your live chat API requires authentication:
+
+```csharp
+// Add authentication headers in your ILiveChatService implementation
+private async Task GetAuthenticatedClient()
+{
+ var client = _httpClientFactory.CreateClient();
+
+ // Option 1: API Key authentication
+ client.DefaultRequestHeaders.Add("X-API-Key", _apiKey);
+
+ // Option 2: Bearer token authentication
+ // var token = await GetAccessToken();
+ // client.DefaultRequestHeaders.Authorization =
+ // new AuthenticationHeaderValue("Bearer", token);
+
+ return client;
+}
+```
+
+> Store API keys and secrets in Azure Key Vault or environment variables, never in source code.
+{: .prompt-danger }
+
+### Adapting the UI
+
+If you want live agents to use a custom interface:
+
+1. **Embed in existing tools**: Most enterprise platforms provide webhooks and APIs—you may not need a separate UI
+2. **Build custom UI**: Use the Contoso app as a starting point, modify the HTML/JS to match your branding
+3. **Mobile apps**: Call the same REST APIs from mobile applications
+
+The key is ensuring agents can view incoming messages and send responses that trigger the webhook back to the skill.
+
+## Limitations and Considerations
+
+### Microsoft Teams Channel Only
+
+This pattern requires proactive messaging to send live agent responses back to users asynchronously. Currently, only the Microsoft Teams channel in Copilot Studio supports this capability reliably.
+
+**Impact**: Users on web chat, mobile app, or other channels cannot use this handover pattern.
+
+**Workaround**: Consider implementing different escalation strategies for non-Teams channels (email notifications, callback requests, etc.).
+
+### In-Memory Storage
+
+The sample uses static dictionaries in `ConversationManager` for conversation mappings.
+
+**Impact**:
+- State is lost on application restart
+- Cannot scale to multiple instances (no shared state)
+- Not suitable for production environments
+
+**Solution**: Replace with persistent storage:
+```csharp
+// Example: Azure Cosmos DB implementation
+public class CosmosConversationManager : IConversationManager
+{
+ private readonly Container _container;
+
+ public async Task UpsertMappingByCopilotConversationId(
+ Activity activity, string liveChatId)
+ {
+ var mapping = new ConversationMapping
+ {
+ CopilotConversationId = activity.Conversation.Id,
+ LiveChatConversationId = liveChatId,
+ // ... other properties
+ };
+
+ await _container.UpsertItemAsync(mapping,
+ new PartitionKey(mapping.CopilotConversationId));
+ }
+}
+```
+
+### Multiple Simultaneous Sessions
+
+The current implementation allows one MS Teams chat to create multiple live chat sessions without UI disambiguation.
+
+**Impact**: If a user escalates multiple times without closing previous sessions, messages may be received simultaneously from multiple agents.
+
+**Solution**: Implement session management UI or enforce one-session-per-user policies in your `ConversationManager`.
+
+### Skill Manifest Refresh
+
+Changes to `skill-manifest.json` require refreshing the skill in Copilot Studio.
+
+**Process**:
+1. Update the manifest file
+2. Navigate to Copilot Studio > Settings > Skills
+3. Find the handover skill
+4. Click "Refresh" to reload the manifest
+
+## Summary Checklist
+
+When implementing live agent handover:
+
+1. **Set up infrastructure**: Dev tunnel or production endpoint, .NET 9.0 runtime, Teams channel
+2. **Configure authentication**: App Registration with client secret, proper scopes for Bot Framework
+3. **Implement ILiveChatService**: Start conversation, send message, end conversation methods
+4. **Configure webhooks**: Ensure your live chat system POSTs agent messages to the skill
+5. **Set up conversation mapping storage**: Replace in-memory storage with persistent database
+6. **Handle proactive messaging**: Configure `ConnectionsMap` for MS Teams SMBA regions
+7. **Create Copilot Studio topics**: Use `startConversation` and `endConversation` events
+8. **Test end-to-end**: Verify messages flow bidirectionally without loss
+
+## Key Takeaways
+
+- The skill pattern enables seamless handover to any third-party live chat system
+- Conversation mapping is the critical component for bidirectional message routing
+- MS Teams proactive messaging enables asynchronous agent responses
+- The Contoso app is a template—replace it with your real live chat integration
+- Production deployments require persistent storage and proper secret management
+- Only Microsoft Teams channel currently supports this pattern fully
+
+## Try It Yourself
+
+Ready to implement live agent handover? Clone the complete sample:
+
+**Repository**: [HandoverToLiveAgent Sample](https://github.com/microsoft/CopilotStudioSamples/tree/main/HandoverToLiveAgent)
+
+1. Clone the repository
+2. Follow the setup steps above
+3. Test with the mock Contoso app
+4. Replace `ILiveChatService` with your own live chat integration
+5. Deploy to production with persistent storage
+
+---
+
+*Questions about integrating with your specific live chat platform? Have you implemented a similar handover pattern? Share your experience in the comments below!*