活动协议是在许多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 类:
- .NET: TurnContext
- Python: TurnContext
- JavaScript: TurnContext
注释
本文中的代码片段使用 C# 。 JavaScript 和 Python 版本的语法和 API 结构类似。
TurnContext 是 Microsoft 365 智能体 SDK 中每个会话轮次中使用的重要对象。 它提供对传入活动的访问权限、发送响应的方法、会话状态管理以及处理单个会话轮次所需的上下文。 使用它来维护上下文、发送适当的响应,并有效地与其客户端或通道中的用户交互。 每次代理从通道接收新活动时,代理 SDK 都会创建一个新 TurnContext 实例,并将其传递给已注册的处理程序或方法。 此上下文对象存在于单轮次中,然后在轮次结束时释放。
轮次定义为从客户端发送的消息往返到您的代码。 代码处理该数据,并且可以选择性地发送响应以完成轮次。 该往返可以分为以下步骤:
传入活动:用户发送消息或执行创建活动的操作。
代码接收活动,代理使用
TurnContext进行处理。代理将一个或多个活动发送回。
轮次结束,
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 ,常用的密钥信息包括:
活动类型
活动的类型定义活动其余部分在客户端、用户和代理之间需要或预期的内容。
这些包括:
- 消息
- 对话更新
- 事件
- 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 类型的 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 类型创建方法或路由处理程序。 然后,参照以下内容管理所需的逻辑:
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/fetch 和 task/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 对象进行序列化,客户端随后根据其在客户端中的呈现方式反序列化。 从根本上说,附件是消息的一种,而引文可以引用附件,并作为有效负载中的EntitiesActivity发送的另一种对象。
渠道特定考量
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 等。
- 对某些活动类型的支持可能有限。
- 卡片渲染可能表现不同或不被支持。
- 请始终检查特定的频道文档。