在自定义引擎代理中实现异步和主动消息传送

本文介绍如何在使用 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 启动对话。
✅ 发送消息 向对话发布消息。