次の方法で共有


カスタム エンジン エージェントに非同期メッセージングとプロアクティブ メッセージングを実装する

この記事では、Microsoft Bot Frameworkを使用してビルドするカスタム エンジン エージェントに非同期およびプロアクティブ メッセージング パターンを実装する方法について説明します。 これらのパターンを使用すると、エージェントは遅延後、またはユーザーが開始したメッセージなしでユーザーに応答できます。

非同期メッセージングとプロアクティブ メッセージングを使用して、カスタム エンジン エージェントで次のことができます。

  • バックグラウンド処理を続行しながら、遅延後に応答します。
  • ユーザー入力なしでメッセージを開始します (システムによってトリガーされる更新プログラムなど)。

各ユーザー クエリは、15 秒以内に最初の応答を受け取る必要があります。 実行時間の長いタスクの場合、エージェントはフォローアップ メッセージを送信できます。 ストリーミング更新の間に 45 秒のタイムアウトが適用されます。

非同期メッセージ

非同期メッセージは、エージェントがユーザーによって開始されたバックグラウンド タスクを完了した後に送信されます。 このパターンは、注文の追跡や状態の更新などのシナリオに役立ちます。

たとえば、ユーザーがノート PC を注文した場合、エージェントは要求を確認し、注文が行われたときに後でフォローアップ メッセージをユーザーに送信できます。 次の例は、 Bot Framework を使用してノート PC の注文に関する非同期メッセージを送信する方法を示しています。

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 を使用して会話を開始します。
✅ メッセージの送信 メッセージを会話に投稿します。