了解活动协议

活动协议是许多Microsoft SDK、服务和客户端中跨Microsoft使用的通信协议和标准协议。 这包括 Microsoft 365 Copilot、Microsoft Copilot Studio 和 Microsoft 365 代理 SDK。 活动协议定义了 Activity 的结构,以及消息、活动和交互如何从通道流向您的代码以及其间的所有环节。 代理可以连接到一个或多个通道来与用户交互,并与其他代理协作。 活动协议可标准化你正在使用的任何客户端之间的通信协议,包括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 Agents 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 ,常用的密钥信息包括:

活动类型

活动的类型很重要,因为它定义了客户端、用户和代理之间的其余活动所需的或预期内容。

Message

一种常见的活动类型是 消息 类型 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.Reciepient.Id)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome {member.Name}!"), cancellationToken);
            }
        }
    }
})

事件

事件类型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

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 通常生存期较短,因此不要假设它们会保留在那里,因此,如果需要稍后参考,则迁移到自己的存储非常重要。

引文

请务必知道 附件引文 不是相同的对象类型。 引用由客户端(如 Microsoft Teams)以各自的方式处理,使用实体属性Activity,可通过 activity.Entities.Add 添加,并创建具有基于客户端特定 Entity 定义的新 Citation 对象。 它将作为 JSON 对象进行序列化,客户端随后会根据它在客户端中的呈现方式反序列化。 本质上,附件属于消息范畴,引用可指向附件,并作为 Entities 有效负载的 Activity 中另一对象发送。

渠道特定考量

Microsoft 365 代理 SDK 构建为“中心”,使开发人员能够创建可与 任何 客户端配合使用的代理,包括我们支持的客户端,并为开发人员提供使用同一框架生成自己的通道适配器的工具。 这为开发人员在代理方面提供了多样化的选择,并为客户端的连接提供了扩展性。该中心可以连接一个或多个客户端,例如Microsoft Teams、Slack等平台。

不同的通道具有不同的功能和限制,以下是使用常见客户端时的注意事项摘要。

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

渠道包含特定数据,这些数据不符合所有频道通用的 Activity 有效负载规范,可通过 TurnContext.Activity.ChannelData 访问,并需显式转换为变量供代码使用。

Microsoft Teams

  • 支持具备高级功能的丰富自适应卡片
  • 支持消息更新和删除
  • 提供 Teams 专属渠道数据(提及、会议信息等)
  • 支持任务模块的调用活动

Microsoft 365 Copilot

  • 主要侧重于消息相关活动
  • 支持在回答中使用文献和参考资料
  • 需要流式传输响应
  • 对富卡/自适应卡的有限支持

WebChat/DirectLine

网上聊天是一种 HTTP 协议,用于代理通过 HTTPS 进行通信

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

第三方频道

其中包括 Slack、Facebook 等。

  • 对某些活动类型的支持可能有限
  • 卡渲染的方式可能不同或可能不受支持
  • 请务必查阅具体渠道文档