💬

Microsoft 365 Agents SDK でプロアクティブ メッセージを送信する

に公開

はじめに

Microsoft Bot Framework では ConnectorClient クラスを使って、ボットの外部からプロアクティブ メッセージを送信できます。タイマーによる定期的なメッセージ送信や、ほかのプロセスの完了通知などの用途に利用できます。

Microsoft Bot Framework での実装例を次に示します。

var serviceUrl = new Uri("https://smba.trafficmanager.net/jp/{{tenant-id}}");
var credential = new MicrosoftAppCredentials("{{client-id}}", "{{client-secret}}");
var connectorClient = new ConnectorClient(serviceUrl, credential);
var activity = new Activity()
{
    Conversation = new ConversationAccount()
    {
        Id = "{{conversation-id}}"
    },
    Type = ActivityTypes.Message,
    Text = "Hello World!",
    ChannelId = Channels.Msteams
};
await connectorClient.Conversations.SendToConversationAsync(activity);

Microsoft 365 Agents SDK でも同様のことを実現できますが、アーキテクチャが大きく変わっています。この記事では、Microsoft 365 Agents SDK でプロアクティブ メッセージを送信する方法を紹介します。

サンプル コード

https://github.com/karamem0/samples/tree/main/microsoft-365-agents-sdk-connector-client

実行手順

Microsoft 365 Agents SDK では依存関係注入 (DI) を前提としています。今回はコンソール アプリを使用するため、汎用ホストによる実装が必要です。汎用ホストについては Microsoft のドキュメントを参照してください。

https://learn.microsoft.com/ja-jp/dotnet/core/extensions/generic-host/?WT.mc_id=M365-MVP-5002941

appsettings.json

Microsoft 365 Agents SDK で必要となる設定を構成します。今回のサンプルでは送信するメッセージを固定としているため、Activity クラスの情報も設定に含めています。実際のシナリオでは、会話 ID をデータベースなどから取得する想定です。

https://learn.microsoft.com/ja-jp/microsoft-365/agents-sdk/bf-migration-dotnet/?WT.mc_id=M365-MVP-5002941

{
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "ClientSecret",
        "ClientId": "{{client-id}}",
        "ClientSecret": "{{client-secret}}",
        "TenantId": "{{tenant-id}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },
  "ConnectionsMap": [
    {
      "ServiceUrl": "*",
      "Connection": "ServiceConnection"
    }
  ],
  "Activity": {
    "Conversation": {
      "Id": "{{conversation-id}}"
    },
    "Type": "message",
    "Text": "Hello, World!"
  }
}

Program.cs

ConnectorClient クラスをインスタンス化するためのサービスを登録します。また appsettings.json から設定情報を読み込めるようにします。

var builder = Host.CreateApplicationBuilder(args);

var configuration = builder.Configuration;
_ = configuration.AddJsonFile("appsettings.json");

var services = builder.Services;

_ = services.AddHostedService<ConnectorClientService>();
_ = services.AddHttpClient();
_ = services.AddSingleton<IConnections, ConfigurationConnections>();
_ = services.AddSingleton<IChannelServiceClientFactory, RestChannelServiceClientFactory>();

builder.Build().Run();

ConnectorClientService.cs

BackgroundService を継承した ConnectorClientService クラスを作成します。このクラスでは、Program.cs で登録したサービスを DI で受け取ります。ConnectorClient クラスは、IChannelServiceClientFactory インターフェースの CreateConnectorClientAsync メソッドから生成します。このときのパラメーター型が ClaimsIdentity になっている点が大きな変更点です。現時点の実装では appid クレームの値が参照されます。合わせて ver クレームに 1.0 を指定します。ver クレームについては以下の記事を参考にしてください。

https://zenn.dev/karamem0/articles/2025_08_07_180000

ServiceUrl は Teams の場合は https://smba.trafficmanager.net/jp/{{tenantId}} です。この URL はチャネルによって異なりますので注意してください。

public class ConnectorClientService(
    IHostApplicationLifetime hostApplicationLifetime,
    IConfiguration configuration,
    IChannelServiceClientFactory channelServiceClientFactory
) : BackgroundService
{

    private readonly IHostApplicationLifetime hostApplicationLifetime = hostApplicationLifetime;

    private readonly IConfiguration configuration = configuration;

    private readonly IChannelServiceClientFactory channelServiceClientFactory = channelServiceClientFactory;

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        // クライアントを作成する
        var tenantId = this.configuration.GetValue<string>("Connections:ServiceConnection:Settings:TenantId")!;
        var clientId = this.configuration.GetValue<string>("Connections:ServiceConnection:Settings:ClientId")!;
        var claimsIdentity = new ClaimsIdentity([
            new Claim("ver", "1.0"),
            new Claim("appid", clientId)
        ]);
        var connectorClient = await this.channelServiceClientFactory.CreateConnectorClientAsync(
            claimsIdentity,
            $"https://smba.trafficmanager.net/jp/{tenantId}",
            "https://api.botframework.com/",
            cancellationToken
        );
        // メッセージを送信する
        var activity = this.configuration.GetSection("Activity").Get<Activity>();
        _ = await connectorClient.Conversations.SendToConversationAsync(activity, cancellationToken);
        // アプリケーションを終了する
        this.hostApplicationLifetime.StopApplication();
    }

}

おわりに

現時点では公式のサンプルがないため、暫定的に動作する実装になっています。今後ドキュメントが拡充され、公式の情報やサンプルが公開されることに期待しています。

Discussion