Skip to content

Commit 803da87

Browse files
authored
Merge pull request microsoft#14 from vidrana/codesamples/handoff-activity
Adding sample code for reading handoff activity and conversation context for connecting to an engagement hub
2 parents 5bc9cb4 + c05b049 commit 803da87

4 files changed

Lines changed: 315 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//-----------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
//-----------------------------------------------------------------------------
4+
5+
using Microsoft.Bot.Schema;
6+
using Newtonsoft.Json;
7+
8+
namespace Microsoft.PVA.Handoff
9+
{
10+
/// <summary>
11+
/// Activities that are received by the user in response to their query
12+
/// </summary>
13+
public class BotResponse
14+
{
15+
/// <summary>
16+
/// Activities that are a part of the bot response
17+
/// </summary>
18+
[JsonProperty(PropertyName = "activities")]
19+
public Activity[] Activities { get; set; }
20+
}
21+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//-----------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
//-----------------------------------------------------------------------------
4+
5+
using Newtonsoft.Json;
6+
7+
namespace Microsoft.PVA.Handoff
8+
{
9+
public class HandoffContext
10+
{
11+
/// <summary>
12+
/// Scope of the activity - bot/user
13+
/// </summary>
14+
[JsonProperty(PropertyName = "va_Scope")]
15+
public string Scope { get; set; }
16+
17+
/// <summary>
18+
/// Last topic triggered in conversation
19+
/// </summary>
20+
[JsonProperty(PropertyName = "va_LastTopic")]
21+
public string LastTopic { get; set; }
22+
23+
/// <summary>
24+
/// All topics triggered in conversation
25+
/// </summary>
26+
[JsonProperty(PropertyName = "va_Topics")]
27+
public string[] Topics { get; set; }
28+
29+
/// <summary>
30+
/// Last user phrase
31+
/// </summary>
32+
[JsonProperty(PropertyName = "va_LastPhrase")]
33+
public string LastPhrase { get; set; }
34+
35+
/// <summary>
36+
/// All user phrases
37+
/// </summary>
38+
[JsonProperty(PropertyName = "va_Phrases")]
39+
public string[] Phrases { get; set; }
40+
41+
/// <summary>
42+
/// Conversation Id
43+
/// </summary>
44+
[JsonProperty(PropertyName = "va_ConversationId")]
45+
public string ConversationId { get; set; }
46+
47+
/// <summary>
48+
/// Message for agent as configured in dialog
49+
/// </summary>
50+
[JsonProperty(PropertyName = "va_AgentMessage")]
51+
public string AgentMessage { get; set; }
52+
53+
/// <summary>
54+
/// Bot Id
55+
/// </summary>
56+
[JsonProperty(PropertyName = "va_BotId")]
57+
public string BotId { get; set; }
58+
59+
/// <summary>
60+
/// Bot Name
61+
/// </summary>
62+
[JsonProperty(PropertyName = "va_BotName")]
63+
public string BotName { get; set; }
64+
65+
/// <summary>
66+
/// Language
67+
/// </summary>
68+
[JsonProperty(PropertyName = "va_Language")]
69+
public string Language { get; set; }
70+
71+
/// <summary>
72+
/// MS Caller Id
73+
/// </summary>
74+
[JsonProperty(PropertyName = "MSCallerId")]
75+
public string MSCallerId { get; set; }
76+
}
77+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//-----------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
//-----------------------------------------------------------------------------
4+
5+
using Microsoft.Bot.Schema;
6+
using Newtonsoft.Json;
7+
using System.Linq;
8+
9+
namespace Microsoft.PVA.Handoff
10+
{
11+
public static class HandoffHelper
12+
{
13+
private const string HandoffInitiateActivityName = "handoff.initiate";
14+
private const string TranscriptAttachmentName = "transcript";
15+
16+
public static void InitiateHandoff(string botresponseJson)
17+
{
18+
BotResponse response = JsonConvert.DeserializeObject<BotResponse>(botresponseJson);
19+
20+
// Look for Handoff Initiate Activity. This indicates that conversation needs to be handed off to agent
21+
Activity handoffInitiateActivity = response.Activities.ToList().FirstOrDefault(
22+
item => string.Equals(item.Type, ActivityTypes.Event, System.StringComparison.Ordinal)
23+
&& string.Equals(item.Name, HandoffInitiateActivityName, System.StringComparison.Ordinal));
24+
25+
if (handoffInitiateActivity != null)
26+
{
27+
// Read transcript from attachment
28+
if (handoffInitiateActivity.Attachments?.Any() == true)
29+
{
30+
Attachment transcriptAttachment = handoffInitiateActivity.Attachments.FirstOrDefault(
31+
a => string.Equals(a.Name.ToLowerInvariant(), TranscriptAttachmentName, System.StringComparison.Ordinal));
32+
if (transcriptAttachment != null)
33+
{
34+
Transcript transcript = JsonConvert.DeserializeObject<Transcript>(
35+
transcriptAttachment.Content.ToString());
36+
}
37+
}
38+
39+
// Read handoff context
40+
HandoffContext context = JsonConvert.DeserializeObject<HandoffContext>(handoffInitiateActivity.Value.ToString());
41+
42+
// Connect to Agent Hub
43+
// <YOUR CUSTOM ADAPTER CODE GOES HERE>
44+
}
45+
}
46+
}
47+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
{
2+
"activities": [
3+
{
4+
"type": "event",
5+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000005",
6+
"timestamp": "2020-02-10T21:51:37.4997264Z",
7+
"channelId": "directline",
8+
"from": {
9+
"id": "f074b91b-2f8c-4543-bbcc-7226e9662c01",
10+
"name": "Test501",
11+
"role": "bot"
12+
},
13+
"conversation": {
14+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o"
15+
},
16+
"attachments": [
17+
{
18+
"contentType": "application/json",
19+
"content": {
20+
"activities": [
21+
{
22+
"type": "message",
23+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000000",
24+
"timestamp": "2020-02-10T21:51:21.491453+00:00",
25+
"serviceUrl": "https://directline.botframework.com/",
26+
"channelId": "directline",
27+
"from": {
28+
"id": "pva_H1YHD_be80720b-bdb0-4561-aae2-5f891f2f02e0",
29+
"name": "C2 User",
30+
"role": "user"
31+
},
32+
"conversation": {
33+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o"
34+
},
35+
"recipient": {
36+
"id": "<REDACTED>",
37+
"name": "Contoso Bot",
38+
"role": "bot"
39+
},
40+
"textFormat": "plain",
41+
"locale": "en-US",
42+
"text": "store hours",
43+
"entities": [
44+
{
45+
"type": "ClientCapabilities",
46+
"requiresBotState": true,
47+
"supportsListening": true,
48+
"supportsTts": true
49+
}
50+
],
51+
"channelData": {
52+
"clientActivityID": "15813714814300.gevfmx9xoxc",
53+
"cci_bot_id": "<REDACTED>",
54+
"cci_tenant_id": "<REDACTED>",
55+
"cci_content_version": "e8aa9c88-4249-ea11-a812-000d3a1531ec",
56+
"cci_trace_id": "1xc8K",
57+
"traceHistory": null,
58+
"enableDiagnostics": true
59+
},
60+
"cci_bot_id": "<REDACTED>",
61+
"cci_tenant_id": "<REDACTED>",
62+
"cci_content_version": "e8aa9c88-4249-ea11-a812-000d3a1531ec"
63+
},
64+
{
65+
"type": "message",
66+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000001",
67+
"timestamp": "2020-02-10T21:51:30.6362632+00:00",
68+
"serviceUrl": "https://directline.botframework.com/",
69+
"channelId": "directline",
70+
"from": {
71+
"id": "<REDACTED>",
72+
"name": "Contoso Bot",
73+
"role": "bot"
74+
},
75+
"conversation": {
76+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o"
77+
},
78+
"recipient": {
79+
"id": "pva_H1YHD_be80720b-bdb0-4561-aae2-5f891f2f02e0",
80+
"name": "C2 User",
81+
"role": "user"
82+
},
83+
"textFormat": "markdown",
84+
"text": "I'm happy to help with store hours.",
85+
"inputHint": "acceptingInput",
86+
"attachments": [],
87+
"entities": [],
88+
"channelData": {
89+
"DialogTraceDetail": {
90+
"DialogTraces": [
91+
{
92+
"DialogId": "caf0a29a-bad7-40e0-9941-11925e17614b",
93+
"NodeId": "e901982c-a22d-4074-b8c7-f7842977a047"
94+
}
95+
]
96+
},
97+
"ConversationUnderstandingDetail": {
98+
"NormalizedQuery": "store hour",
99+
"RawQuery": "store hours",
100+
"ClarificationDetail": {
101+
"ConfirmQuestion": false
102+
},
103+
"RankedIntents": [
104+
{
105+
"IntentId": "33d51237-70ba-4dae-afae-51b361ddc80a",
106+
"Score": 1.0,
107+
"MatchedTriggerQuery": "Store hours"
108+
}
109+
]
110+
},
111+
"VariableDetail": {
112+
"Variables": {}
113+
},
114+
"CurrentMessageDetail": {
115+
"TraceId": "1xc8K",
116+
"ConversationId": "91hcXEd0ZYCBPoRwBDPHZ6-o",
117+
"CurrentProblemId": "3858486c-f1d7-415a-8678-979f725c601b",
118+
"CurrentIntentId": "33d51237-70ba-4dae-afae-51b361ddc80a",
119+
"ContentVersion": "e8aa9c88-4249-ea11-a812-000d3a1531ec",
120+
"SentTime": "2020-02-10T21:51:30.6092929+00:00"
121+
}
122+
},
123+
"replyToId": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000000"
124+
}
125+
]
126+
},
127+
"name": "Transcript"
128+
}
129+
],
130+
"entities": [],
131+
"replyToId": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000000",
132+
"value": {
133+
"va_Scope": "bot",
134+
"va_LastTopic": "Lesson 1 - A simple topic",
135+
"va_Topics": [
136+
"Lesson 1 - A simple topic"
137+
],
138+
"va_LastPhrase": "store hours",
139+
"va_Phrases": [
140+
"store hours"
141+
],
142+
"va_ConversationId": "91hcXEd0ZYCBPoRwBDPHZ6-o",
143+
"va_AgentMessage": "Transferred",
144+
"va_BotId": "<REDACTED>",
145+
"va_BotName": "Test501",
146+
"va_Language": "En-US"
147+
},
148+
"name": "handoff.initiate",
149+
"relatesTo": {
150+
"activityId": "91hcXEd0ZYCBPoRwBDPHZ6-o|0000000",
151+
"user": {
152+
"id": "pva_H1YHD_be80720b-bdb0-4561-aae2-5f891f2f02e0",
153+
"name": "C2 User",
154+
"role": "user"
155+
},
156+
"bot": {
157+
"id": "<REDACTED>",
158+
"name": "Contoso Bot",
159+
"role": "bot"
160+
},
161+
"conversation": {
162+
"id": "91hcXEd0ZYCBPoRwBDPHZ6-o"
163+
},
164+
"channelId": "directline",
165+
"serviceUrl": "https://directline.botframework.com/"
166+
}
167+
}
168+
],
169+
"watermark": "5"
170+
}

0 commit comments

Comments
 (0)