Human Handoff
As bots aren’t perfect, we allow the transfer of a conversation to an agent.
Configuration
To configure the transfer, you must first provide the session parameter.
Then you can specify a queue with withQueue
. The queue ID or name is the identifier of the queue to where you want to transfer the conversation. An ID is preferred to avoid duplicates. If this ID queue doesn't exist, the conversation is transferred to a random open queue.
Once the handoff has finished, you can specify a payload or a path to trigger the action that the bot will follow. To do so, you can use withOnFinishPayload
or withOnFinishPath
. Both are optional, although recommended.
Queue
Here’s a simple example of how to transfer the conversation to a queue with ID HUBTYPE_DESK_QUEUE_ID
. Once the human agent has solved the case, the bot will receive the payload endConversation
which will trigger the action SayGoodbye
.
src/routes.js
import SayGoodbye from './actions/say-goodbye'
import HumanHandoff from './actions/human-handoff.js'
export const routes = [
{ payload: 'endConversation', action: SayGoodbye },
{ text: 'handoff', action: HumanHandoff },
]
Note: The conversation is transferred to Hubtype Desk, so the queueId
must be the id of a queue inside Hubtype Desk. Contact us if you need to integrate with another CRM.
You can find the HUBTYPE_DESK_QUEUE_ID
by checking the URL https://app.hubtype.com/organization/queues/{HUBTYPE_DESK_QUEUE_ID}/messengers
under Edit Queue
tab.
./actions/handoff-example.js
import React from 'react'
import { Text } from '@botonic/react'
import { HandOffBuilder } from '@botonic/core'
export default class extends React.Component {
static async botonicInit({ input, session, params, lastRoutePath }) {
const handOffBuilder = new HandOffBuilder(session)
handOffBuilder.withQueue('HUBTYPE_DESK_QUEUE_ID')
handOffBuilder.withOnFinishPayload('endConversation')
await handOffBuilder.handOff()
}
render() {
return (
<Text>
Thanks for contacting us! One of our agents will respond
as soon as possible.
</Text>
)
}
}
Note: If you run withAgentId
with the agent ID or withAgentEmail
with the agent's Hubtype Desk e-mail, without passing a queue parameter, the handoff is automatically done to the first queue assigned to the agent.
Open Queues
You can get an array of all the open queues in Hubtype Desk with the simple Botonic function getOpenQueues()
.
./actions/handoff-queue-example.js
import React from 'react'
import { Text } from '@botonic/react'
import { getOpenQueues } from '@botonic/core'
export default class extends React.Component {
static async botonicInit({ input, session, params, lastRoutePath }) {
let openQueues = await getOpenQueues(session)
return { openQueues }
}
render() {
if (!this.props.openQueues.queues.length) {
return <Text>There are no open queues</Text>
} else {
return <Text>Open queues: {this.props.openQueues.queues.join(',')}</Text>
}
}
}
Note: Both features are only available when the bot is deployed. When you are in development mode (botonic serve
command), you can press the button 'Continue' in order to emulate the resolution of a case.
Case Handling
Each time a Human Handoff is done, a new case is created in Hubtype's Desk.
When creating a new case you can autoassign this case to a specific agent using getAvailableAgents
as shown below.
You can also send relevant information to Hubtype Desk by specifying the optional parameter with withCaseInfo
and withNote
.
withCaseInfo
can contain, as an example, the name of the action where the user gets stuck. It will be displayed in the case details section in Hubtype Desk.withNote
can be used to leave a message for other agents who don't have constancy of the case.
import React from 'react'
import { Text } from '@botonic/react'
import { getAvailableAgentsByQueue, HandOffBuilder } from '@botonic/core'
export default class extends React.Component {
static async botonicInit({ input, session, params, lastRoutePath }) {
let isHandOff = false
let agentEmail = ''
try {
agentEmail = (
await getAvailableAgentsByQueue(session, 'HUBTYPE_DESK_QUEUE_ID')
).filter(agent => agent == 'agent-name@hubtype.com')[0]
const handOffBuilder = new HandOffBuilder(session)
handOffBuilder.withQueue('HUBTYPE_DESK_QUEUE_ID')
handOffBuilder.withOnFinishPath('thanks-for-contacting')
handOffBuilder.withAgentEmail(agentEmail)
handOffBuilder.withCaseInfo(
'This is some case information that will be available in the new created case'
)
handOffBuilder.withNote(
'This is a note that will be attached to the case as a reminder'
)
isHandOff = true
await handOffBuilder.handOff()
} catch (e) {}
return { isHandOff: isHandOff }
}
render() {
if (this.props.isHandOff) {
return <Text>You are being transferred to an agent!</Text>
} else {
return (
<Text>
Sorry, right now we can't serve you... Please contact us later!
</Text>
)
}
}
}
Human Handoff Example
To set up human handoff, you can use the Botonic library. You can select the relevant example with a very simple use case where a user is transferred to a human agent through the chatbot. The conversation is then displayed as a new case on Hubtype Desk.
In the example below, a route in src/routes.js
that triggers the handoff when a user types "handoff" is set up:
src/routes.js
import TransferAgent from './actions/transfer-agent'
import Thanks from './actions/thanks'
export const routes = [
{ path: 'agent', text: /^handoff$/i, action: TransferAgent },
{ path: 'thanks-for-contacting', action: Thanks },
]
Then, in our src/actions/transfer-agent.js
file, we need to use the HandOffBuilder
class within botonicInit
.
Additionally, we check if the 'Customer Support' queue is open:
src/actions/transfer-agent.js
import React from 'react'
import { Text } from '@botonic/react'
import { getOpenQueues, HandOffBuilder } from '@botonic/core'
export default class extends React.Component {
static async botonicInit({ input, session, params, lastRoutePath }) {
let openQueues = await getOpenQueues(session)
let isHandOff = false
if (openQueues.queues.indexOf('Customer Support') !== -1) {
const handOffBuilder = new HandOffBuilder(session)
handOffBuilder.withQueue('Customer Support')
handOffBuilder.withOnFinishPath('thanks-for-contacting')
isHandOff = true
await handOffBuilder.handOff()
}
return { isHandOff }
}
render() {
if (this.props.isHandOff) {
return <Text>You are being transferred to an agent!</Text>
} else {
return (
<Text>
Sorry, right now we can't serve you... Please contact us later!
</Text>
)
}
}
}
Note: Remember that the full features for getOpenQueues
and HandOffBuilder
are only available when the bot is deployed!
Available Options
Here is the list of the different handoff options available to use with HandOffBuilder
.
Option | Description | Parameter | Type |
---|---|---|---|
withQueue | ID or name of the queue where the conversation is transferred. | queueNameOrId | string |
withOnFinishPath | Specify a payload or a path to trigger the action that the bot will follow after the conversation with the agent has finished. | path | string |
withAgentEmail | Agent's email. | string | |
withAgentId | Agent's ID. | agentId | string |
withNote | Leave a message for other agents to know more about the case. | note | string |
withCaseInfo | Give details about the case. | caseInfo | string |
withShadowing | Allows a bot to receive and answer messages even if there's a case created. If enabled, the bot "listens" to the conversation between the user and the agent and can give advice to the agent who is resolving the case. | shadowing. | boolean |
Note: These options are not required but recommended. If you don't use any HandOffBuilder
methods, a handoff will be performed to the first queue based on the ID sorting order.
Methods to Request Agent's Information
getOpenQueues
Get the list of all the open queues.
Property | Parameters | Response | Description |
---|---|---|---|
queues | session | { queues: string[] } | Name of the queues |
getAvailableAgentsByQueue
Get the list of all the agents who can attend a case by queue.
Property | Parameters | Response | Description |
---|---|---|---|
agents | session, queueId | { agents: string[] } | List of the agents' emails and ID of the queues |
getAvailableAgents
Get extra information from the agents, sorted by the number of cases that are attending in Hubtype Desk. When creating a new case, it enables the case autoassignment to a specific agent.
Property | Parameters | Response | Description |
---|---|---|---|
agents | session | { agents: HubtypeAgentsInfo[] } | Agent's information such as email address, number of cases attending, status (available or not) and last message sent |
Details
interface HubtypeAgentsInfo {
email: string
attending_count: number
status: string
last_message_sent: string
}
getAgentVacationRanges
Get the agent's vacation information to know their availability.
Property | Parameters | Response | Description |
---|---|---|---|
vacation_ranges | session, agentParams (only ID or Email) | { vacation_ranges: VacationRange[] } | Agent's vacation start and end dates (timestamp) |
Details
interface VacationRange {
end_date: number // timestamp
id: number
start_date: number // timestamp
}