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 でプロアクティブ メッセージを送信する方法を紹介します。
サンプル コード
実行手順
Microsoft 365 Agents SDK では依存関係注入 (DI) を前提としています。今回はコンソール アプリを使用するため、汎用ホストによる実装が必要です。汎用ホストについては Microsoft のドキュメントを参照してください。
appsettings.json
Microsoft 365 Agents SDK で必要となる設定を構成します。今回のサンプルでは送信するメッセージを固定としているため、Activity クラスの情報も設定に含めています。実際のシナリオでは、会話 ID をデータベースなどから取得する想定です。
{
"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 クレームについては以下の記事を参考にしてください。
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