本文介绍如何在使用 Microsoft Bot Framework 生成的自定义引擎代理中实现异步和主动消息传递模式。 这些模式允许代理在延迟或不使用用户发起的消息后响应用户。
可以使用异步和主动消息传送使自定义引擎代理能够:
- 在继续后台处理时延迟后做出响应。
- 在没有用户输入的情况下启动消息 (例如,系统触发的更新) 。
每个用户查询应在 15 秒内收到初始响应。 对于长时间运行的任务,代理可以发送后续消息。 流式处理更新之间应用 45 秒的超时。
异步消息
异步消息在代理完成用户启动的后台任务后发送。 此模式对于订单跟踪或状态更新等方案非常有用。
例如,如果用户订购了笔记本电脑,则代理可以确认请求,并在下订单后向用户发送后续消息。 以下示例演示如何使用 Bot Framework 发送有关笔记本电脑订单的异步消息。
app.message(
CustomMessageTypes.orderLaptopSelected.toString(),
async (context: TurnContext, _state) => {
return new Promise(async (resolve) => {
await context.sendActivity({
text: "Thank you for order laptop. I will keep you posted with updates.",
});
setTimeout(async () => {
await context.sendActivity({
text: "Great! I have successfully placed your order #1292. I'll notify you when it's delivered.",
attachments: [
{
contentType: "application/vnd.microsoft.card.adaptive",
content: deliveredCard,
},
],
});
resolve();
}, 10 * 1000);
});
}
);
下表总结了异步消息过程。
| 任务 | 说明 |
|---|---|
| ✅ 初始确认 | 发送消息以确认请求。 |
| ✅ 后台处理 | 以异步方式执行任务。 |
| ✅ 后续消息 | 任务完成时通知用户。 |
主动邮件
主动消息由系统启动,而不是由用户发起。 这些消息通过专用会话线程发送。
例如,代理可以向用户发送有关事件或更新的通知,而无需用户查询。 以下示例演示如何使用 createConversation API 获取会话信息并通过专用线程发送主动消息。
export async function getToken() {
const url =
"https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token";
const params = new URLSearchParams();
params.append("grant_type", "client_credentials");
params.append("client_id", config.MicrosoftAppId);
params.append("client_secret", config.MicrosoftAppPassword);
params.append("scope", "https://api.botframework.com/.default");
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params.toString(),
});
if (!response.ok) {
throw new Error(`Error! status: ${response.status}`);
}
const data = await response.json();
return data;
}
let accessToken;
try {
accessToken = getToken();
if (!accessToken) {
console.log("No access token found, fetching a new one");
const tokenResponse = await getToken();
accessToken = tokenResponse.access_token;
if (!accessToken) {
throw new Error("Failed to obtain access token");
}
setAccessToken(accessToken);
}
} catch (error) {
console.error("Error retrieving access token:", error);
await context.sendActivity(
"Failed to send proactive message due to authentication error"
);
return;
}
const createConversationBody = {
members: [{ id: context.activity.from.aadObjectId }],
tenantId: context.activity.conversation.tenantId,
channelData: {
productContext: "Copilot",
conversation: {
conversationSubType: "AgentProactive",
},
},
};
const createConversationResponse = await fetch(
"https://canary.botapi.skype.com/teams/v3/conversations",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(createConversationBody),
}
);
const createConversationResponseData =
await createConversationResponse.json();
console.log("Create conversation response", createConversationResponseData);
const body = {
text: "Hello proactive world",
type: "message",
};
const response = await fetch(
`https://canary.botapi.skype.com/teams/v3/conversations/${createConversationResponseData.id}/activities`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(body),
}
);
下表总结了主动消息过程。
| 任务 | 说明 |
|---|---|
| ✅ 获取令牌 | 使用 OAuth2 进行身份验证。 |
| ✅ 创建对话 | 使用 Bot Framework API 启动对话。 |
| ✅ 发送消息 | 向对话发布消息。 |