可以使用自适应卡片和 Bot Framework 卡上的按钮从 Microsoft Teams 机器人调用任务模块,这些按钮是用于Microsoft 365 组的英雄、缩略图和连接器。 任务模块通常是比多对话步骤更好的用户体验。 跟踪机器人状态,并允许用户中断或取消序列。
调用任务模块有两种方法:
新的调用消息
task/fetch
:使用
invoke
Bot Framework
卡的卡片操作
或
Action.Submit
自适应
卡片的卡片操作
,以及
task/fetch
,任务模块(URL 或自适应卡)将从机器人动态提取。
深层链接 URL:使用
任务模块的深层链接语法
,可以分别使用 Bot Framework 卡片的
openUrl
卡片操作
或
Action.OpenUrl
自适应
卡片的卡片操作
。 使用深层链接 URL 时,任务模块 URL 或自适应卡片正文已知,以避免服务器相对于
task/fetch
往返。
每个
url
和
fallbackUrl
都必须实现 HTTPS 加密协议。
下节提供有关使用
task/fetch
调用任务模块的详细信息。
使用 调用任务模块
task/fetch
当
invoke
卡片操作的
value
对象或
Action.Submit
已初始化,且当用户选择该按钮时,会向机器人发送一条
invoke
消息。 在对消息的
invoke
HTTP 响应中,包装器对象中嵌入了
一个 TaskInfo 对象
,Teams 使用该对象来显示任务模块。
以下步骤使用 提供调用任务模块
task/fetch
:
此图显示了 Bot Framework 主卡,其中包含
“购买
invoke
卡片”操作
。
type
属性的值是
task/fetch
,
value
对象的其余部分可自行选择。
机器人接收
invoke
HTTP POST 消息。
机器人将创建答复对象,并使用 HTTP 200 答复代码在 POST 答复正文中将其返回。 有关响应架构的详细信息,请参阅
有关任务/提交的讨论
。 以下代码提供了 HTTP 答复正文的示例,其中包含嵌入到包装器对象中的
TaskInfo 对象
:
"task": {
"type": "continue",
"value": {
"title": "Task module title",
"height": 500,
"width": "medium",
"url": "https://contoso.com/msteams/taskmodules/newcustomer",
"fallbackUrl": "https://contoso.com/msteams/taskmodules/newcustomer"
该
task/fetch
事件及其针对机器人的响应类似于
microsoftTeams.tasks.startTask()
Microsoft Teams JavaScript 客户端库中的 函数, (TeamsJS) 。
Microsoft Teams 显示任务模块。
下节提供有关提交任务模块结果的详细信息。
提交任务模块的结果
当用户完成任务模块后,将结果提交回机器人时与使用选项卡的方式类似。 有关详细信息,请参阅
提交任务模块的结果示例
。 存在一些差异,见如下所示:
HTML 或 JavaScript,即
TaskInfo.url
:验证用户输入的内容后,出于可读性目的,调用
microsoftTeams.tasks.submitTask()
下文中引用的
submitTask()
函数。 如果希望 Teams 关闭任务模块,可以调用不带任何参数的
submitTask()
,但必须将对象或字符串传递给
submitHandler
。 将其作为第一个参数
result
传递。 Teams 调用
submitHandler
,
err
是
null
,
result
是传递给
submitTask()
的对象或字符串。 如果调用带
result
参数的
submitTask()
,则必须传递
appId
或
appId
字符串的数组。 这允许 Teams 验证发送结果的应用是否与调用任务模块的相同。 机器人收到一条
task/submit
消息,包括
result
。 有关详细信息,请参阅
task/fetch
和
task/submit
消息的有效负载
。
自适应卡片是
TaskInfo.card
:当用户选择任何
Action.Submit
按钮时,用户填写的自适应卡片正文将通过
task/submit
消息发送到机器人。
下一部分详细介绍了如何响应
task/submit
消息。
响应
task/submit
消息
当用户完成从机器人调用的任务模块后,机器人始终会收到一条
task/submit invoke
消息。 答复
task/submit
消息时有多个选项,见如下所示:
HTTP 正文答复
将自适应卡片链接到序列中是一种高级应用场景。 Node.js 示例应用支持此操作。 有关详细信息,请参阅
Microsoft Teams 任务模块 Node.js
。
下节提供有关
task/fetch
和
task/submit
消息有效负载的详细信息。
和
task/submit
消息的有效
task/fetch
负载
本节定义机器人收到
task/fetch
或
task/submit
Bot Framework
Activity
对象时收到的内容架构。 下表提供了
task/fetch
和
task/submit
消息有效负载的属性:
value
是开发人员定义的有效负载。
value
对象的结构与从 Teams 发送的结构相同。 但是,在这种情况下,情况会有所不同。 它需要支持动态提取,即从机器人框架
task/fetch
,也就是
value
和自适应卡片
Action.Submit
操作,即
data
。 除了
value
或
data
中包含的内容外,还需要一种 Teams
context
与机器人通信的方法。
将“值”和“数据”组合到父对象中:
{
“context”: {
“theme”: “default” |“dark” |“contrast”,
},
“data”:[Bot Framework 卡片中的值字段] |[自适应卡片中的数据字段]
}
下节提供在 Node.js 中接收和答复
task/fetch
和
task/submit
调用消息的示例。
以下选项卡在 Node.js 和 C# 中提供
task/fetch
并
task/submit
调用消息:
Node.js
handleTeamsTaskModuleFetch(context, taskModuleRequest) {
// Called when the user selects an options from the displayed HeroCard or
// AdaptiveCard. The result is the action to perform.
const cardTaskFetchValue = taskModuleRequest.data.data;
var taskInfo = {}; // TaskModuleTaskInfo
if (cardTaskFetchValue === TaskModuleIds.YouTube) {
// Display the YouTube.html page
taskInfo.url = taskInfo.fallbackUrl = this.baseUrl + '/' + TaskModuleIds.YouTube + '.html';
this.setTaskInfo(taskInfo, TaskModuleUIConstants.YouTube);
} else if (cardTaskFetchValue === TaskModuleIds.CustomForm) {
// Display the CustomForm.html page, and post the form data back via
// handleTeamsTaskModuleSubmit.
taskInfo.url = taskInfo.fallbackUrl = this.baseUrl + '/' + TaskModuleIds.CustomForm + '.html';
this.setTaskInfo(taskInfo, TaskModuleUIConstants.CustomForm);
} else if (cardTaskFetchValue === TaskModuleIds.AdaptiveCard) {
// Display an AdaptiveCard to prompt user for text, and post it back via
// handleTeamsTaskModuleSubmit.
taskInfo.card = this.createAdaptiveCardAttachment();
this.setTaskInfo(taskInfo, TaskModuleUIConstants.AdaptiveCard);
return TaskModuleResponseFactory.toTaskModuleResponse(taskInfo);
async handleTeamsTaskModuleSubmit(context, taskModuleRequest) {
// Called when data is being returned from the selected option (see `handleTeamsTaskModuleFetch').
// Echo the users input back. In a production bot, this is where you'd add behavior in
// response to the input.
await context.sendActivity(MessageFactory.text('handleTeamsTaskModuleSubmit: ' + JSON.stringify(taskModuleRequest.data)));
// Return TaskModuleResponse
return {
// TaskModuleMessageResponse
task: {
type: 'message',
value: 'Thanks!'
setTaskInfo(taskInfo, uiSettings) {
taskInfo.height = uiSettings.height;
taskInfo.width = uiSettings.width;
taskInfo.title = uiSettings.title;
protected override Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
var asJobject = JObject.FromObject(taskModuleRequest.Data);
var value = asJobject.ToObject<CardTaskFetchValue<string>>()?.Data;
var taskInfo = new TaskModuleTaskInfo();
switch (value)
case TaskModuleIds.YouTube:
taskInfo.Url = taskInfo.FallbackUrl = _baseUrl + "/" + TaskModuleIds.YouTube;
SetTaskInfo(taskInfo, TaskModuleUIConstants.YouTube);
break;
case TaskModuleIds.CustomForm:
taskInfo.Url = taskInfo.FallbackUrl = _baseUrl + "/" + TaskModuleIds.CustomForm;
SetTaskInfo(taskInfo, TaskModuleUIConstants.CustomForm);
break;
case TaskModuleIds.AdaptiveCard:
taskInfo.Card = CreateAdaptiveCardAttachment();
SetTaskInfo(taskInfo, TaskModuleUIConstants.AdaptiveCard);
break;
default:
break;
return Task.FromResult(taskInfo.ToTaskModuleResponse());
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
var reply = MessageFactory.Text("OnTeamsTaskModuleSubmitAsync Value: " + JsonConvert.SerializeObject(taskModuleRequest));
await turnContext.SendActivityAsync(reply, cancellationToken);
return TaskModuleResponseFactory.CreateResponse("Thanks!");
private static void SetTaskInfo(TaskModuleTaskInfo taskInfo, UISettings uIConstants)
taskInfo.Height = uIConstants.Height;
taskInfo.Width = uIConstants.Width;
taskInfo.Title = uIConstants.Title.ToString();
Bot Framework 卡片操作与自适应卡片操作。提交操作
Bot Framework 卡片操作的架构不同于自适应卡片 Action.Submit
操作,调用任务模块的方式也不同。 中的 data
Action.Submit
对象包含对象 msteams
,因此它不会干扰卡片中的其他属性。 下表显示了每个卡片操作的示例:
Bot Framework 卡片操作
自适应卡片 Action.Submit 操作