Skip to main content
Version: Next

Messenger Handover Protocol

Since Messenger has become a critical customer support channel between brands and customers, the cooperation between Messenger Bots and human agents creates a complete customer journey on messaging business.

Here comes the Messenger handover protocol, which aims to make a smooth transition between Messenger Bots and human agents in the compact Messenger window. Technically speaking, this protocol allows a Facebook Page simultaneously owns multiple Facebook Apps, e.g., a Facebook app for auto-reply, and another Facebook app for human agents support.

Note:

  • If you are curious how to change the profile image between Messenger Bot and human agents, please check Bottender's doc, Using Persona.
  • For more information about handover protocol, please check Facebook's official doc, Handover Protocol

Thread Control: Who is Answering the Customer

Before going further, you have to know the concept of Thread Control. Assume that there are multiple Facebook Apps behind a single Facebook page. Only one Facebook owns the Thread Control of a specific customer at a time, which means only one Facebook App can reply to the customer.

Primary Receiver: The Privilege App Role

Among all the apps behind the Facebook Page, only a single app could be Primary Receiver, the rest are Secondary Receivers.

You may treat Primary Receiver as the boss. S/he is the only one who owns the privilege to allow other apps to reply. S/he can also take back Thread Control from Secondary Receivers at any moment. By default, Primary Receiver owns the thread control, i.e., all messages sent to the Primary Receiver.

You, or the Facebook Page admin, can change the app role, i,e, which app is the Primary Receiver at the Page Settings.

The default setting of App roles is a bit mysterious. It is like no app is Primary Receiver. We would suggest you check your app role settings and assign Bottender's app as the Primary Receiver to manage the Thread Control.

In the following table, you can see the difference in capability between Primary Receiver and Secondary Receiver.

Note:

Passing Thread Control

The Pass Thread Control API allows one app to pass the control of a conversation to another. The calling app can pass optional metadata to the receiving app in the API request. By the pass_thread_control webhook, an app can know if it takes the thread control.

async function App(context) {
await context.passThreadControl('target-app-id');
}

Page Inbox is a unique official app of Facebook. It is the default Facebook app for every Facebook Page to reply to messages by human agents.

Page Inbox has three default folders: Main, Done, Spam. When you set Page Inbox as Secondary Receiver, all messages sent to your bot appears in the Done folder by default.

When the Page inbox has control of the conversation, all messages from the conversation move to the Inbox folder and wait for a human agent to respond. When you move a specific customer to the Done folder, you indirectly pass the Thread Control of the customer to Primary Receiver, which is usually the Facebook App of your Bottender project.

async function App(context) {
await context.passThreadControlToPageInbox();
}

Taking Thread Control and Requesting Thread Control

Take Thread Control API allows the Primary Receiver to take control of the conversation from Secondary Receivers. It is useful when Secondary Receiver is not responding. An optional metadata string may also be sent in the request.

The Secondary Receiver app receives a messaging_handovers webhook event when it loses control of the conversation. The event contains the metadata string.

async function App(context) {
await context.takeThreadControl();
}

The Request Thread Control API allows a Secondary Receiver to notify the Primary Receiver that it wants control of the chat. The Primary Receiver can then take control of the chat if necessary, then pass control to the Secondary Receiver that sent the request. An optional metadata string may also be sent in the request.

The Primary Receiver may also ignore the request and do nothing.

async function App(context) {
await context.requestThreadControl();
}

Getting the Thread Owner

The following function helps you check which Facebook app owns the Thread Control. It is useful for bots that have complex implementations of the handover protocol, where an app's actions are dependent on whether it currently has thread control.

The Thread Owner API may be called by Primary Receiver and Secondary Receivers.

async function App(context) {
const threadOwner = await context.getThreadOwner();
console.log(threadOwner); // { appId: "thread-owner-app-id" }
}

Bottender offers a handy function, isThreadOwner, to check whether the Facebook App of Bottender code owns the thread. This function uses the appId in bottender.config.js to compare with the current App Id from getThreadOwner. So please make sure you have your appId appropriately set.

async function App(context) {
const isThreadOwner = await context.isThreadOwner();
console.log(isThreadOwner); // true or false
}
  • For more information, you can refer to Facebook's official doc, Get Thread Owner

Retrieving the List of Secondary Receivers

This API allows Primary Receiver to get the list of Secondary Receiver apps for a page.

By default, no app has been set explicitly as a Primary Receiver. We recommend you to config your Bottender app as the Primary Receiver to avoid any unexpected situations.

async function App(context) {
const secondaryReceivers = await context.client.getSecondaryReceivers();
console.log(secondaryReceivers);
// [
// {
// id: "12345678910",
// name: "David's Composer"
// },
// {
// id: "23456789101",
// name: "Messenger Rocks"
// }
// ]
}

Webhook Events

In the following section, we would like to highlight a few highly related webhook events. Please make sure you have enable corresponding Page Subscription Fields in your Facebook App Settings.

app_role

Once a role is assigned, either Primary Receiver or Secondary Receiver app gets an app_role webhook.

{
recipient: {
id: '<PSID>'
},
timestamp: 1458692752478,
appRoles: {
123456789: ['primary_receiver'],
},
}

messaging_handovers

The messaging_handovers webhook event notifies an app's webhook when the following actions happen:

  • Thread control is passed to the app
  • Thread control is taken from the app
  • App role is changed

standby

For bots using the handover protocol, this callback occurs when a message has been sent to your page, but your app is not the current thread owner.

  • For more information, you can refer to Facebook's official doc, standby

echo

This callback occurs when a message has been sent by your page.

It is helpful when your Primary Receiver app, e.g., Bottender code, has passed Thread Control to a Secondary Receiver app, e.g., Page Inbox. However, you want to make sure your bot takes Thread Control back after a certain amount of time.

You can subscribe to this callback by selecting the message_echoes field when setting up your webhook.

  • For more information, you can refer to Facebook's official doc, echo