智能机器人对话中的邮件
对话中的每个消息都是 Activity
类型的 messageType: message
对象。 当用户发送消息时,Microsoft Teams 会将消息活动发布到机器人。 Teams 将 JSON 对象发送到机器人的消息传送终结点,Teams 仅允许一个终结点进行消息传递。 机器人会检查消息来确定其类型并作出相应响应。
基本对话通过 Bot Framework 连接器(单个 REST API)进行处理。 此 API 使机器人能够与 Teams 和其他频道通信。 Bot Builder SDK 提供以下功能:
- 轻松访问 Bot Framework 连接器。
- 用于管理聊天流和状态的功能。
- 合并认知服务的简单方法,例如自然语言处理 (NLP) 。
机器人使用 属性从 Teams 接收消息, Text
并向用户发送单个或多个消息响应。
有关详细信息,请参阅 机器人消息的用户属性。
下表列出了机器人可以接收和采取措施的活动:
类型 | 有效负载对象 | 范围 |
---|---|---|
接收消息活动 | 消息活动 | 全部 |
接收编辑消息活动 | 消息编辑活动 | 全部 |
接收取消删除消息活动 | 消息取消删除活动 | 全部 |
接收软删除消息活动 | 邮件软删除活动 | 全部 |
接收消息活动
若要接收文本消息,请使用 Text
对象的 属性 Activity
。 在机器人的活动处理程序中,使用圈上下文对象的 Activity
来读取单一消息请求。
以下代码显示了接收消息活动的示例:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
}
接收已读回执
Teams 中的 “阅读回执 ”设置允许当收件人在一对一聊天和群组聊天中阅读聊天邮件时通知聊天邮件的发件人。 收件人阅读邮件后, “已查看 ”显示在邮件旁边。 还可以选择将机器人配置为通过“已读回执”设置接收 已读回执 事件。 已读回执事件可通过以下方式帮助你增强用户体验:
如果你的应用用户未在个人聊天中阅读该消息,则可以将机器人配置为发送后续消息。
可以使用已读回执创建反馈循环来优化机器人的体验。
注意
- 仅用户到机器人聊天方案中支持已读回执。
- 机器人的已读回执不支持团队、频道和群聊范围。
- 如果租户管理员或用户禁用“ 已读回执 ”设置,机器人不会收到已读回执事件。
若要接收机器人的已读回执事件,请确保以下各项:
"webApplicationInfo": {
"id": "38f0ca43-1c38-4c39-8097e-47f62c686500",
"resource": ""
},
"authorization": {
"permissions": {
"orgwide": [],
"resourceSpecific": [
{
"name": "ChatMessageReadReceipt.Read.Chat",
"type": "Application"
}
]
}
}
还可以通过图形 API添加 RSC 权限。 有关详细信息,请参阅 consentedPermissionSet
。
使用
IsMessageRead
处理程序重写 方法OnTeamsReadReceiptAsync
。帮助
IsMessageRead
程序方法可用于确定邮件是否由收件人阅读。compareMessageId
如果 小于或等于LastReadMessageId
,则消息已读取。OnTeamsReadReceiptAsync
使用IsMessageRead
帮助程序方法重写 方法以接收已读回执:protected override async Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken) { var lastReadMessageId = readReceiptInfo.LastReadMessageId; if (IsMessageRead("{id of the message that you care}", LastReadMessageId)) { await turnContext.SendActivityAsync(MessageFactory.Text("User read the bot's message"), cancellationToken); } }
下面是机器人接收的已读回执事件请求的示例:
{ "name": "application/vnd.microsoft.readReceipt", "type": "event", "timestamp": "2023-08-16T17:23:11.1366686Z", "id": "f:b4783e72-9d7b-2ed9-ccef-ab446c873007", "channelId": "msteams", "serviceUrl": "https://smba.trafficmanager.net/amer/", "from": { "id": "29:1-8Iuh70W9pRqV8tQK8o2nVjxz33RRGDKLf4Bh7gKnrzN8s7e4vCyrFwjkPbTCX_Co8c4aXwWvq3RBLr-WkkVMw", "aadObjectId": "5b649834-7412-4cce-9e69-176e95a394f5" }, "conversation": { "conversationType": "personal", "tenantId": "6babcaad-604b-40ac-a9d7-9fd97c0b779f", "id": "a:1xlimp68NSUxEqK0ap2rXuwC9ITauHgV2M4RaDPkeRhV8qMaFn-RyilMZ62YiVdqs8pp43yQaRKvv_U2S2gOS5nM-y_pOxVe4BW1qMGPtqD0Bv3pw-nJXF0zhDlZHMZ1Z" }, "recipient": { "id": "28:9901a8b6-4fef-428b-80b1-ddb59361adeb", "name": "Test Bot" }, "channelData": { "tenant": { "id": "6babcaad-604b-40ac-a9d7-9fd97c0b779f" } }, "value": { "lastReadMessageId": "1692206589131" } }
已为机器人接收已读回执事件的租户启用“已读回执 管理员 设置”或“ 用户设置 ”。 租户管理员或用户必须启用或禁用已读回执设置。
在用户到机器人聊天方案中启用机器人后,当用户读取机器人的消息时,机器人将立即收到已读回执事件。 可以通过统计事件数来跟踪用户参与情况,还可以发送上下文感知消息。
发送消息
若要发送文本消息,请指定要作为活动发送的字符串。 在机器人的活动处理程序中,使用轮次上下文对象的 SendActivityAsync
方法发送单个消息响应。 使用 对象的 SendActivitiesAsync
方法发送多个响应。
以下代码演示了在将用户添加到对话时发送消息的示例:
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(MessageFactory.Text($"Hello and welcome!"), cancellationToken);
}
注意
在用户和机器人之间发送的消息包括消息中的内部通道数据。 此数据允许机器人在该通道上正确通信。 Bot Builder SDK 允许修改消息结构。
获取编辑消息活动
编辑消息时,机器人会收到编辑消息活动的通知。
若要在机器人中获取编辑消息活动通知,可以重写 OnTeamsMessageEditAsync
处理程序。
下面是编辑已发送邮件时使用的 OnTeamsMessageEditAsync
编辑消息活动通知的示例:
protected override async Task OnTeamsMessageEditAsync(ITurnContext<IMessageUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is updated");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
获取取消删除消息活动
取消删除消息时,机器人会收到取消删除消息活动的通知。
若要在机器人中获取取消删除消息活动通知,可以重写 OnTeamsMessageUndeleteAsync
处理程序。
下面是还原已删除消息时使用的 OnTeamsMessageUndeleteAsync
取消删除消息活动通知的示例:
protected override async Task OnTeamsMessageUndeleteAsync(ITurnContext<IMessageUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is undeleted");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
获取软删除消息活动
软删除消息时,机器人会收到软删除消息活动的通知。
若要在机器人中获取软删除消息活动通知,可以重写 OnTeamsMessageSoftDeleteAsync
处理程序。
下面是软删除邮件时使用的 OnTeamsMessageSoftDeleteAsync
软删除消息活动通知的示例:
protected override async Task OnTeamsMessageSoftDeleteAsync(ITurnContext<IMessageDeleteActivity> turnContext, CancellationToken cancellationToken)
{
var replyActivity = MessageFactory.Text("message is soft deleted");
await turnContext.SendActivityAsync(replyActivity, cancellationToken);
}
发送建议的操作
建议的操作可帮助用户根据以前的响应或对话,了解接下来要询问的内容。 机器人应向用户提供特定于上下文的建议,而不是常规建议或固定建议。 可以使用机器人的大型语言模型 (LLM) 生成最多三个建议及其响应。 然后,可以提取这些建议,并将其作为选项呈现供用户选择。
当用户选择按钮时,它在富卡上保持可见和可访问。 但是,对于建议的操作,按钮设计为在选择后消失,以防止用户选择可能不再相关的过时选项。
注意
-
SuggestedActions
仅支持具有基于文本的消息和自适应卡片的一对一聊天机器人。 -
SuggestedActions
具有任何聊天类型的附件的聊天机器人不支持。 -
imBack
是唯一受支持的操作类型,Teams 最多显示三个建议的操作。
若要向消息添加建议的操作,请指定卡操作对象的列表,这些对象表示活动对象的 属性要向用户sugestedActions
显示的按钮。
下面是实现和体验建议操作的示例:
{
"type": "message",
"from": {
"id": "12345678",
"name": "sender's name"
},
"conversation": {
"id": "abcd1234",
"name": "conversation's name"
},
"recipient": {
"id": "1234abcd",
"name": "recipient's name"
},
"text": "What are the tasks for the day.",
"inputHint": "expectingInput",
"suggestedActions": {
"actions": [
{
"type": "imBack",
"title": "Create a new query identifying overdue tasks",
"value": "Create a new query identifying overdue tasks"
},
{
"type": "imBack",
"title": "Create a new work item for this feature",
"value": "Create a new work item for this feature"
}
]
},
"replyToId": "5d5cdc723"
}
下面演示了建议的操作的示例:
Teams 频道数据
对象 channelData
包含特定于 Teams 的信息,是团队和频道 ID 的明确源。 (可选)可以缓存这些 ID 并将其用作本地存储的密钥。
TeamsActivityHandler
SDK 中的 从 channelData
对象中提取重要信息,使其可访问。 但是,始终可以从 对象访问原始数据 turnContext
。
对象 channelData
不包括在个人对话的消息中,因为这些发生在频道之外。
发送到机器人的活动中的典型 channelData
对象包含以下信息:
-
eventType
:仅在 通道修改事件的情况下传递的 Teams 事件类型。 -
tenant.id
:Microsoft Entra在所有上下文中传递的租户 ID。 -
team
:仅在频道上下文中传递,不在个人聊天中传递。-
id
:通道的 GUID。 -
name
:仅在团队 重命名事件的情况下传递的团队名称。
-
-
channel
:仅在通道上下文中传递,当机器人被提及时或对于添加机器人的团队中的频道中的事件。-
id
:通道的 GUID。 -
name
:仅在通道 修改事件的情况下传递的通道名称。
-
-
channelData.teamsTeamId
:荒废的。 仅为了向后兼容而包含此属性。 -
channelData.teamsChannelId
:荒废的。 仅为了向后兼容而包含此属性。
channelData 对象示例
以下代码显示了 channelData 对象 (channelCreated 事件) 的示例:
"channelData": {
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
},
"channel": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
"name": "My New Channel"
},
"team": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
}
}
邮件内容
从机器人接收或发送到机器人的消息可以包括不同类型的消息内容。
格式 | 从用户到机器人 | 从机器人到用户 | 注释 |
---|---|---|---|
格式文本 | ✔️ | ✔️ | 机器人可以发送格式文本、图片和卡片。 用户可以向机器人发送格式文本和图片。 |
图片 | ✔️ | ✔️ | PNG、JPEG 或 GIF 格式的最大 1024 × 1024 像素和 1 MB。 不支持动态 GIF。 |
卡片 | ❌ | ✔️ | 有关支持的卡片,请参阅 Teams 卡参考。 |
表情符号 | ✔️ | ✔️ | Teams 通过 UTF-16 支持表情符号,例如用于笑脸的 U+1F600。 |
图片消息
若要增强邮件,可以将图片作为附件包含在邮件中。 有关附件的详细信息,请参阅 向邮件添加媒体附件。
图片最多可以为 1024 × 1024 像素和 1 MB,采用 PNG、JPEG 或 GIF 格式。 不支持动态 GIF。
使用 XML 指定每个图像的高度和宽度。 在 Markdown 中,图像大小默认为 256×256。 例如:
- 使用:
<img src="http://aka.ms/Fo983c" alt="Duck on a rock" height="150" width="223"></img>
。 - 请勿使用:
![Duck on a rock](http://aka.ms/Fo983c)
。
聊天机器人可以包含可简化业务工作流的自适应卡片。 自适应卡片提供丰富的可自定义文本、语音、图像、按钮和输入字段。
自适应卡
自适应卡片可以在机器人中创作,并在多个应用(如 Teams、网站等)中显示。 有关详细信息,请参阅 自适应卡片。
以下代码演示发送简单自适应卡片的示例:
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.5",
"body": [
{
"items": [
{
"size": "large",
"text": " Simple Adaptivecard Example with a Textbox",
"type": "TextBlock",
"weight": "bolder",
"wrap": true
},
],
"spacing": "extraLarge",
"type": "Container",
"verticalContentAlignment": "center"
}
]
}
向邮件添加通知
可通过两种方式从应用程序发送通知:
- 通过在机器人消息上设置
Notification.Alert
属性。 - 通过使用图形 API发送活动源通知。
可以使用 属性向消息 Notification.Alert
添加通知。 通知会提醒用户注意应用程序中的事件,例如新任务、提及或注释。 这些警报与用户正在处理的内容或用户必须查看的内容(通过将通知插入其活动源)相关。 若要从机器人消息触发通知,请将 TeamsChannelData
objects Notification.Alert
属性设置为 true。 如果引发通知取决于单个用户的 Teams 设置,则无法替代这些设置。
如果要生成任意通知而不向用户发送消息,则可以使用 图形 API。 有关详细信息,请参阅如何使用图形 API发送活动源通知以及最佳做法。
注意
“ 摘要” 字段在源中将来自用户的任何文本显示为通知消息。
以下代码演示了向消息添加通知的示例:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Returns a simple text message.
var message = MessageFactory.Text("You'll get a notification, if you've turned them on.");
message.TeamsNotifyUser();
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync(message);
}
机器人对话 API 中的状态代码
确保在 Teams 应用中正确处理这些错误。 下表列出了生成错误的错误代码和说明:
状态代码 | 错误代码和消息值 | 说明 | 重试请求 | 开发人员操作 |
---|---|---|---|---|
400 |
代码: Bad Argument 消息:*方案特定 |
机器人提供的请求有效负载无效。 有关具体的详细信息,请参阅错误消息。 | 否 | 重新计算错误的请求有效负载。 有关详细信息,请查看返回的错误消息。 |
401 |
代码: BotNotRegistered 消息:找不到此机器人的注册。 |
找不到此机器人的注册。 | 否 | 验证机器人 ID 和密码。 确保机器人 ID (Microsoft Entra ID) 已在 Teams 开发人员门户中注册,或者在启用了“Teams”通道的情况下通过 Azure 中的 Azure 机器人通道注册进行注册。 |
403 |
代码: BotDisabledByAdmin 消息:租户管理员已禁用此机器人 |
租户管理员阻止了用户与机器人应用之间的交互。 租户管理员需要在应用策略中允许用户使用应用。 有关详细信息,请参阅 应用策略。 | 否 | 停止发布到聊天,直到聊天中的用户显式启动与机器人的交互,指示机器人不再被阻止。 |
403 |
代码: BotNotInConversationRoster 消息:机器人不是对话名单的一部分。 |
机器人不是对话的一部分。 需要在对话中重新安装应用。 | 否 | 在尝试发送另一个会话请求之前,请等待事件 installationUpdate ,该事件指示再次添加机器人。 |
403 |
代码: ConversationBlockedByUser 消息:用户阻止了与机器人的对话。 |
用户通过审查设置在个人聊天或频道中阻止了机器人。 | 否 | 从缓存中删除对话。 停止尝试发布到聊天,直到聊天中的用户显式启动与机器人的交互,指示机器人不再被阻止。 |
403 |
代码: ForbiddenOperationException 消息:机器人未安装在用户的个人范围内 |
主动消息由机器人发送,该机器人未安装在个人范围内。 | 否 | 在尝试发送另一个对话请求之前,请在个人范围内安装应用。 |
403 |
代码: InvalidBotApiHost 消息:机器人 API 主机无效。 对于 GCC 租户,请调用 https://smba.infra.gcc.teams.microsoft.com 。 |
机器人为属于 GCC 租户的会话调用公共 API 终结点。 | 否 | 将会话的服务 URL 更新为 https://smba.infra.gcc.teams.microsoft.com 并重试请求。 |
403 |
代码: NotEnoughPermissions 消息:*方案特定 |
机器人没有执行请求的操作所需的权限。 | 否 | 从错误消息中确定所需的操作。 |
404 |
代码: ActivityNotFoundInConversation 消息:找不到对话。 |
在对话中找不到提供的消息 ID。 消息不存在或已删除。 | 否 | 检查发送的消息 ID 是否为预期值。 如果 ID 已缓存,请删除该 ID。 |
404 |
代码: ConversationNotFound 消息:找不到对话。 |
找不到对话,因为它不存在或删除。 | 否 | 检查发送的对话 ID 是否为预期值。 如果 ID 已缓存,请删除该 ID。 |
412 |
代码: PreconditionFailed 消息:前置条件失败,请重试。 |
由于同一会话上的多个并发操作,某个依赖项的前置条件失败。 | 是 | 使用指数退避重试。 |
413 |
代码: MessageSizeTooBig 消息:消息大小过大。 |
传入请求的大小太大。 有关详细信息,请参阅 设置机器人消息的格式。 | 否 | 减小有效负载大小。 |
429 |
代码: Throttled 消息:请求过多。 还返回稍后重试时间。 |
机器人发送的请求过多。 有关详细信息,请参阅 速率限制。 | 是 | 使用 Retry-After 标头重试以确定回退时间。 |
500 |
代码: ServiceError 消息:*各 |
内部服务器错误。 | 否 | 在 开发人员社区中报告问题。 |
502 |
代码: ServiceError 消息:*各 |
服务依赖项问题。 | 是 | 使用指数退避重试。 如果问题仍然存在,请在 开发人员社区中报告问题。 |
503 | 服务不可用。 | 是 | 使用指数退避重试。 如果问题仍然存在,请在 开发人员社区中报告问题。 | |
504 | 网关超时。 | 是 | 使用指数退避重试。 如果问题仍然存在,请在 开发人员社区中报告问题。 |
状态代码重试指南
下表列出了每个状态代码的常规重试指南,机器人必须避免重试未指定的状态代码:
状态代码 | 重试策略 |
---|---|
403 | 通过调用 的 GCC API https://smba.infra.gcc.teams.microsoft.com 进行 InvalidBotApiHost 重试。 |
412 | 使用指数退避重试。 |
429 | 使用 Retry-After 标头重试,以确定等待时间(以秒为单位),以及请求之间的等待时间(如果可用)。 否则,请尽可能使用带线程 ID 的指数回退重试。 |
502 | 使用指数退避重试。 |
503 | 使用指数退避重试。 |
504 | 使用指数退避重试。 |
代码示例
示例名称 | Description | Node.js | .NETCore | Python | .NET | 清单 |
---|---|---|---|---|---|---|
Teams 对话自动程序 | 此示例应用演示如何使用 Bot Framework v4 中提供的不同机器人聊天事件。 | View | View | View | 不适用 | View |
Teams 应用本地化 | 此示例显示使用机器人和选项卡的 Teams 应用本地化。 | View | NA | NA | View | 不适用 |