Configure handoff to any generic engagement hub

Important

Power Virtual Agents capabilities and features are now part of Microsoft Copilot Studio following significant investments in generative AI and enhanced integrations across Microsoft Copilot.

Some articles and screenshots may refer to Power Virtual Agents while we update documentation and training content.

Copilot Studio lets you hand over copilot conversations seamlessly and contextually to a human agent through an engagement hub.

With some custom development, you can configure your copilot to hand off conversations to any engagement hub. This guide describes how you can do this.

Prerequisites

Important

Instructions in this section require software development from you or your developers. It is intended for experienced IT professionals, such as IT admins or developers who have a solid understanding of developer tools, utilities, and IDEs who are looking to integrate third-party engagement hubs with Copilot Studio.

Overview

ILLUSTRATION SHOWING GENERIC ADAPTER DATAFLOW.

A full handoff to an engagement hub follows this pattern:

  1. An end user interacts with the engagement hub's chat canvas.

  2. The engagement hub routes the incoming chat through built-in chat routing capabilities to a copilot.

  3. A custom adapter relays the incoming chat messages from the engagement hub to a Copilot Studio copilot.

  4. Once the end user triggers handoff, Copilot Studio starts handoff with full conversational context.

  5. The custom adapter intercepts the handoff message, parses the full conversation context, and seamlessly routes the escalated conversation to a skilled human agent, based on availability.

  6. The end user's chat is seamlessly and contextually handed off to a human agent who can resume the conversation.

To hand off the conversation to a human agent, you need to build a custom handoff adapter.

Build a custom handoff adapter

An adapter bridges conversations to and from your agent engagement hub by relaying and transforming messages between end users, copilots, and human agents.

Most popular agent engagement hubs provide SDKs or document their APIs publicly, enabling you to build such adapters.

While it is outside the scope of this document to cover what a custom adapter could contain, the following sample handoff message, based on what Copilot Studio generates as part of our standard handoff to a live agent experience, can help get you started.

These code snippets and samples allow you to extract context from the conversation to seamlessly and contextually hand off copilot conversations to any generic engagement hub.

Sample handoff message payload

Handoff is currently only supported over Direct Line. Learn more about interacting with a copilot over Direct Line. Upon handoff, an event activity called handoff.initiate is raised and sent to the adapter.

You can see a full sample handoff message activity on our GitHub site.

Extract context from handoff message

To use conversational context, you must parse the handoff.initiate event activity. The following snippet of code parses the handoff.initiate event activity and extracts the conversational context. See the full code sample on GitHub.

public void InitiateHandoff(string botresponseJson)
{
    BotResponse response = JsonConvert.DeserializeObject<BotResponse>(botresponseJson);

    // Look for Handoff Initiate Activity. This indicates that conversation needs to be handed off to agent
    Activity handoffInitiateActivity = response.Activities.ToList().FirstOrDefault(
        item => string.Equals(item.Type, ActivityTypes.Event, System.StringComparison.Ordinal)
        && string.Equals(item.Name, HandoffInitiateActivityName, System.StringComparison.Ordinal));

    if (handoffInitiateActivity != null)
    {
        // Read transcript from attachment
        if (handoffInitiateActivity.Attachments?.Any() == true)
        {
            Attachment transcriptAttachment = handoffInitiateActivity.Attachments.FirstOrDefault(a => string.Equals(a.Name.ToLowerInvariant(), TranscriptAttachmentName, System.StringComparison.Ordinal));
            if (transcriptAttachment != null)
            {
                Transcript transcript = JsonConvert.DeserializeObject<Transcript>(transcriptAttachment.Content.ToString());
            }
        }

        // Read handoff context
        HandoffContext context = JsonConvert.DeserializeObject<HandoffContext>(handoffInitiateActivity.Value.ToString());

        // Connect to Agent Hub
        // <YOUR CUSTOM ADAPTER CODE GOES HERE>
    }
}