活动协议是许多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 类:
- .NET: TurnContext
- Python: TurnContext
- JavaScript: TurnContext
注释
本文中的代码片段使用 C# 。 JavaScript 和 Python 版本的语法和 API 结构类似。
TurnContext是 Microsoft 365 Agents 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 ,常用的密钥信息包括:
活动类型
活动的类型很重要,因为它定义了客户端、用户和代理之间的其余活动所需的或预期内容。
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/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 通常生存期较短,因此不要假设它们会保留在那里,因此,如果需要稍后参考,则迁移到自己的存储非常重要。
引文
请务必知道 附件 和 引文 不是相同的对象类型。 引用由客户端(如 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 等。
- 对某些活动类型的支持可能有限
- 卡渲染的方式可能不同或可能不受支持
- 请务必查阅具体渠道文档