了解活动协议

活动协议是在许多Microsoft SDK、服务和客户端中跨Microsoft使用的标准通信协议。 活动协议由智能 Microsoft 365 Copilot 副驾驶®、Microsoft Copilot Studio和Microsoft 365 智能体 SDK使用。 活动协议定义 Activity 的结构,以及消息、事件和交互如何从通道流向代码和其他各处。 代理可以连接到一个或多个通道来与用户交互,并与其他代理协作。 活动协议将与任何客户端(包括Microsoft和非Microsoft客户端)的通信协议标准化,使您无需为每个通信渠道创建自定义逻辑。

什么是活动?

Activity它是一个结构化 JSON 对象,表示用户和代理之间的任何交互。 活动不仅限于文本消息。 它们可以包括各种类型的交互,例如用户加入或离开支持多个用户的客户端、键入指示器、文件上传、卡片操作和开发人员设计的自定义事件。

每个活动都包含有关以下内容的元数据:

  • 由谁发送(发件人)
  • 谁应收到它(收件人)
  • 对话上下文
  • 其来源的通道
  • 交互的类型
  • 有效负载数据

活动架构 - 键属性

此规范定义活动协议: 活动协议 - 活动。 活动协议中定义的一些关键属性包括:

财产 Description
Id 通常由通道生成(如果它是源自通道的话)
Type 类型控制活动的含义,例如消息类型
ChannelID ChannelID 指示活动起源的通道。 例如: msteams
From 活动的发送方(可以是用户或代理)
Recipient 活动的目标接收者
Text 消息的文本内容
Attachment 丰富的内容,如卡片、文件图像

访问活动数据

若要从 TurnContext 对象中完成操作,开发人员需要访问活动中的数据。

可以在 Microsoft 365 代理 SDK 的每个语言版本中找到一个 TurnContext 类:

注释

本文中的代码片段使用 C# 。 JavaScript 和 Python 版本的语法和 API 结构类似。

TurnContext 是 Microsoft 365 智能体 SDK 中每个会话轮次中使用的重要对象。 它提供对传入活动的访问权限、发送响应的方法、会话状态管理以及处理单个会话轮次所需的上下文。 使用它来维护上下文、发送适当的响应,并有效地与其客户端或通道中的用户交互。 每次代理从通道接收新活动时,代理 SDK 都会创建一个新 TurnContext 实例,并将其传递给已注册的处理程序或方法。 此上下文对象存在于单轮次中,然后在轮次结束时释放。

一个轮次被定义为从客户端发送的消息到达您的代码并返回的往返过程。 代码处理该数据,并且可以选择性地发送响应以完成轮次。 该往返可以分为以下步骤:

  1. 传入活动:用户发送消息或执行创建活动的操作。

  2. 代码接收活动,代理使用TurnContext进行处理。

  3. 您的智能体返回一个或多个操作。

  4. 轮次结束,TurnContext 被销毁。

TurnContext 获取数据,例如:

var messageText = turnContext.Activity.Text;
var channelID = turnContext.Activity.ChannelId;

此代码片段演示完整轮次的示例:

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken) =>
{
    var userMessage = turnContext.Activity.Text;
    var response = $"you said: {userMessage}";
    await turnContext.SendActivityAsync(MessageFactory.Text(response), cancellationToken);
});

在类中 TurnContext ,常用的密钥信息包括:

活动类型

活动的类型定义活动其余部分在客户端、用户和代理之间需要或预期的内容。

这些包括:

  • 消息
  • ConversationUpdate
  • 事件
  • Invoke
  • 打字

消息

一种常见的活动类型是 消息 类型的 Activity。 此 Activity 类型可以包括文本、附件和建议的操作。

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken) =>
{
    var userMessage = turnContext.Activity.Text;
    var response = $"you said: {userMessage}";
    await turnContext.SendActivityAsync(MessageFactory.Text(response), cancellationToken);
});

ConversationUpdate

ConversationUpdate 类型的 Activity 会在成员加入或离开对话时通知您的智能体。 并非所有客户端都支持此通知,但Microsoft Teams支持。

以下代码片段在对话中问候新成员:

agent.OnActivity(ActivityTypes.ConversationUpdate, async (turnContext turnState, cancellationToken) =>
{
    var membersAdded = turnContext.Activity.MembersAdded
    if (membersAdded != null)
    {
        foreach (var member in membersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome {member.Name}!"), cancellationToken);
            }
        }
    }
})

Events

事件类型Activity是一个自定义事件,渠道或客户端用于将结构化数据发送到你的代理。 此数据未在 Activity 有效负载结构中预定义。

需要为特定 Event 类型创建方法或路由处理程序。 然后,根据以下内容管理所需的逻辑:

  • 名称:来自客户端的事件名称或标识符
  • :通常为 JSON 对象的事件有效负载
agent.OnActivity(ActivityTypes.Event, async (turnContext turnState, cancellationToken) =>
{
    var eventName = turnContext.Activity.Name;
    var eventValue = turnContext.Activity.Value;

    // custom event (E.g. a switch on eventName)
});

Invoke

调用类型Activity是客户端调用代理以执行命令或操作的特定类型的活动。 这不仅仅是一条消息。 这些类型的活动示例在 Microsoft Teams for task/fetchtask/submit 中很常见。 并非所有频道都支持这些类型的活动。

打字

打字类型Activity是一种活动分类,用于指示某人在对话中正在打字。 例如,这种活动在 Microsoft Teams 客户端中的人与人之间的对话中很常见。 每个客户端都不支持键入活动。 值得注意的是,智能 Microsoft 365 Copilot 副驾驶®不支持键入活动。

await turnContext.SendActivityAsync(new Activity { Type = ActivityTypes.Typing }, cancellationToken); 
await Task.Delay(2000);
await turnContext.SendActivityAsync(MessageFactory.Text("Here is your answer..."), cancellationToken);

创建和发送活动

若要发送响应,提供了TurnContext多种方法,用于将响应发送回用户。

agent.OnActivity(ActivityTypes.Message, async (turnContext, turnState, cancellationToken))
{
    await turnContext.SendActivityAsync("hello!", cancellationToken: CancellationToken); // uses string directly
    await turnContext.SendActivityAsync(MessageFactory.Text("Hello"), cancellationToken); // uses Message Factory
    await turnContext.SendActivitiesAsync(activities, cancellationToken); // send multiple activities in an Activity array
}

使用附件

代理通常使用用户(甚至其他代理)提交的附件。 客户端发送包含 Message 附件的活动(不是特定类型的活动)。 代码需要处理使用附件接收消息、读取元数据,并从客户端提供的 URL 安全地提取文件。 通常,将文件移动到自己的存储。

接收附件

以下代码演示如何接收附件。

agent.OnActivity(ActivityTypes.Message, async(turnContext, turnState, cancellationToken)) =>
{
    var activity = turnContext.Activity;
    if (activity.Attachments != null && activity.Attachments.Count > 0)
    {
        foreach (var attachment in activity.Attachments)
        {
            // get metadata as required e.g. attachment.ContextType or attachment.ContentUrl
            // use the URL to securely download the attachment and complete your business logic
        };
    }
}

通常,为了接收附件的文档,客户端会发送经过 GET 身份验证的请求来检索实际内容。 每个适配器都有自己的获取数据的方法。 例如,Teams、OneDrive等。 还必须知道这些 URL 通常生存期较短,因此不要假定 URL 长时间有效。 如果以后需要参考内容,则此限制是为什么迁移到自己的存储非常重要。

引文

请务必知道 附件引文 不是相同的对象类型。 客户端(如Microsoft Teams)以自己的方式处理引文。 它们使用 Activity实体属性。 可以使用 activity.Entities.Add 添加引文,并根据客户的特定 Entity 定义添加一个新的 Citation 对象。 它作为 JSON 对象进行序列化,客户端随后根据其在客户端中的呈现方式反序列化。 从根本上讲,附件是消息,而引用可以引用附件,并且是 Activity 有效负载 Entities 中发送的另一个对象。

渠道特定考量

Microsoft 365 智能体 SDK构建为开发人员用来创建可与 any 客户端(包括我们支持的客户端)配合使用的代理的“中心”。 它为开发人员提供了使用同一框架生成自己的通道适配器的工具。 这种架构为开发人员提供了广泛的智能体选择,并为客户端提供了可扩展性以连接到该中心,该中心可以是一个或多个客户端,如 Microsoft Teams、Slack 等。

不同的通道具有不同的功能和限制。

可以通过检查 channelId 中的 Activity 属性来确认接收到活动的通道。

通道包含特定数据,该数据不符合所有通道中的通用Activity有效负载。 您可以通过将其转换为变量来访问 TurnContext.[Activity.ChannelData](/dotnet/api/microsoft.agents.core.models.activity.channeldata) 属性中的数据,以便在代码中使用。

以下部分总结了使用常见客户端时的注意事项。

Microsoft Teams

  • 支持具有高级功能的丰富自适应卡片
  • 支持消息更新和删除。
  • 包含 Teams 功能的特定频道数据,例如提及和会议信息。
  • 支持任务模块的调用操作。

智能 Microsoft 365 Copilot 副驾驶®

  • 主要侧重于消息传递活动。
  • 在响应中支持引文和参考文献。
  • 需要流式传输响应。
  • 对丰富卡片和自适应卡片的支持有限。

Web 聊天/DirectLine

Web 聊天是一种 HTTP 协议,代理可用于通过 HTTPS 进行通信。

  • 完全支持所有活动类型。
  • 支持自定义通道数据。

非Microsoft通道

这些频道包括 Slack、Facebook 等。

  • 对某些活动类型的支持可能有限。
  • 卡片渲染可能表现不同或不被支持。
  • 请始终检查特定的频道文档。

后续步骤