智能机器人对话中的邮件

对话中的每个消息都是 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 中的 “阅读回执 ”设置允许当收件人在一对一聊天和群组聊天中阅读聊天邮件时通知聊天邮件的发件人。 收件人阅读邮件后, “已查看 ”显示在邮件旁边。 还可以选择将机器人配置为通过“已读回执”设置接收 已读回执 事件。 已读回执事件可通过以下方式帮助你增强用户体验:

  • 如果你的应用用户未在个人聊天中阅读该消息,则可以将机器人配置为发送后续消息。

  • 可以使用已读回执创建反馈循环来优化机器人的体验。

注意

  • 仅用户到机器人聊天方案中支持已读回执。
  • 机器人的已读回执不支持团队、频道和群聊范围。
  • 如果租户管理员或用户禁用“ 已读回执 ”设置,机器人不会收到已读回执事件。

若要接收机器人的已读回执事件,请确保以下各项:

  • 应用清单中添加 RSCChatMessageReadReceipt.Read.Chat 权限,如下所示:
    
"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);
}

注意

  • 在同一活动有效负载中发送短信和附件时,会发生消息拆分。 Teams 将此活动拆分为两个单独的活动,一个活动包含短信,另一个包含附件。 拆分活动时,不会在响应中收到消息 ID,该 ID 用于主动 更新或删除 消息。 建议发送单独的活动,而不是根据消息拆分。
  • 可以本地化发送的消息以提供个性化设置。 有关详细信息,请参阅 本地化应用

在用户和机器人之间发送的消息包括消息中的内部通道数据。 此数据允许机器人在该通道上正确通信。 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); 
} 

发送建议的操作

建议的操作使机器人能够显示用户可以选择提供输入的按钮。 建议的操作可让用户通过选择按钮来回答问题或做出选择,而不是使用键盘键入响应,从而增强用户体验。 当用户选择按钮时,它在富卡中保持可见和可访问,但对于建议的操作则不可见。 这可以防止用户在对话中选择过时的按钮。

若要向消息添加建议的操作,请设置suggestedActions活动对象的 属性,以指定表示要呈现给用户的按钮的卡操作对象的列表。 有关详细信息,请参阅 sugestedActions

下面是建议操作的实现和体验的示例:

"suggestedActions": {
    "actions": [
      {
        "type": "imBack",
        "title": "Action 1",
        "value": "Action 1"
      },
      {
        "type": "imBack",
        "title": "Action 2",
        "value": "Action 2"
      }
    ],
    "to": [<list of recepientIds>]
  }

下面演示了建议的操作的示例:

机器人建议的操作

注意

  • SuggestedActions 仅支持具有基于文本的消息和自适应卡片的一对一聊天机器人。
  • SuggestedActions 具有任何聊天类型的附件的聊天机器人不支持。
  • imBack 是唯一受支持的操作类型,Teams 最多显示三个建议的操作。

Teams 频道数据

对象 channelData 包含特定于 Teams 的信息,是团队和频道 ID 的明确源。 (可选)可以缓存这些 ID 并将其用作本地存储的密钥。 TeamsActivityHandler SDK 中的 从 channelData 对象中提取重要信息,使其可访问。 但是,始终可以从 对象访问原始数据 turnContext

对象 channelData 不包括在个人对话的消息中,因为这些发生在频道之外。

发送到机器人的活动中的典型 channelData 对象包含以下信息:

  • eventType:仅在 通道修改事件的情况下传递的 Teams 事件类型。
  • tenant.id:Microsoft Entra在所有上下文中传递的租户 ID。
  • team:仅在频道上下文中传递,不在个人聊天中传递。
    • id:通道的 GUID。
    • name:仅在团队 重命名事件的情况下传递的团队名称。
  • channel:仅在通道上下文中传递,当机器人被提及时或对于添加机器人的团队中的频道中的事件。
  • 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 开发人员门户中或通过 Azure 中的 Azure 机器人通道注册(启用了“Teams”通道)注册。
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 不适用

后续步骤

另请参阅