この記事では、Bot Framework SDK for Node.jsから移行するために必要な変更について説明します。
前提条件
- Node.js バージョン 20 以降
- 既存の Bot Framework SDK プロジェクト
- Azure Bot Service リソース (移行中は変更されません)
NodeJS SDK コードの変更
このセクションの変更点は、Azure Bot Framework SDK と Microsoft 365 エージェント SDK JavaScript の違いによるものです。
Azureのリソース
Azure リソースは変更されません。
MicrosoftAppType、MicrosoftAppId、MicrosoftAppPassword、MicrosoftAppTenantIdの appsettings プロパティを参照する必要があります。 ただし、これらの設定名は使用されなくなり、後で削除できます。
環境の構成の詳細
最初のステップ
最初に次の変更を適用して、ほとんどの違いに対処します。 これらの変更を適用した後も、デバッグして他の違いを確認する必要があります。
パッケージの依存関係を更新する
この変更では、必要なすべての名前空間が解決されるわけではありませんが、その大部分が対象となります。
| Scenario | Bot Framework SDK(ボット フレームワーク ソフトウェア開発キット) | エージェント SDK |
|---|---|---|
| コア ホスティング | botbuilder |
@microsoft/agents-hosting |
| アクティビティ スキーマ | botframework-schema |
@microsoft/agents-activity |
| Dialogs | botbuilder-dialogs |
@microsoft/agents-hosting-dialogs |
| Azure Cosmos DB | botbuilder-azure |
@microsoft/agents-hosting-storage-cosmos |
| Azure Blob Storage | botbuilder-azure-blobs |
@microsoft/agents-hosting-storage-blob |
| 高速サーバー ユーティリティ | 手動セットアップ | @microsoft/agents-hosting-express |
Teams を使用するボット
ボットで Teams を使用している場合は、次のパッケージ依存関係を追加します。 @microsoft/agents-hosting-extensions-teams
インポートの更新/必須
検索と置換を使用して、次の変更を行います。
| Bot Framework | エージェント SDK |
|---|---|
require('botframework-schema'); |
require('@microsoft/agents-activity') |
require('botbuilder'); |
require('@microsoft/agents-hosting') |
require('botbuilder-dialogs'); |
require('@microsoft/agents-hosting-dialogs') |
Agents SDK アクティビティ クラス
@microsoft/agents-activity パッケージには、zod に基づいて解析を実行する Activity クラスが含まれています。 カスタム アクティビティは、 Activity.fromJson() を使用した JSON から、または Activity.fromObject() を使用したリテラル JavaScript オブジェクトから解析および検証できます。
さらに、 Activity クラスは、アクティビティ ペイロードに関連するすべての操作 ( getConversationReferenceなど) を一元化します。 次の表のメソッドは、 TurnContext から移動され、現在のアクティビティ インスタンスで動作するようになりました。
スタートアップと構成
Agents SDK 構成システムは、 ConfigurationBotFrameworkAuthentication クラスを AuthConfiguration インターフェイスに置き換えます。
既定の .env ファイルから構成を読み込むには、 loadAuthConfigFromEnvを使用します。
Important
構成変数については、「 JavaScript での認証の構成」を参照してください。
環境の構成
次の変数を含む .env ファイルを作成します。
# Required for Azure Bot Service
clientId=your-app-id
clientSecret=your-app-secret
tenantId=your-tenant-id
# Optional - for local debugging
PORT=3978
DEBUG=true
移行に関する注: 次の表に示すように、環境変数の名前を更新します。
| Bot Framework SDK(ボット フレームワーク ソフトウェア開発キット) | エージェント SDK |
|---|---|
MicrosoftAppId |
clientId |
MicrosoftAppPassword |
clientSecret |
MicrosoftAppTenantId |
tenantId |
認証とセキュリティ
Bot Framework SDK が受信要求を承認すると、JSON Web トークン (JWT) 承認トークンがスタックに含まれます。 エージェント SDK は動作しません。 Express などの Web サーバー ランタイムを使用する場合は、JWT ベアラー トークンに基づいて受信要求を承認するように JWT ミドルウェアを構成する必要があります。Agents SDK には、 authorizeJWT(AuthConfiguration) メソッドが用意されています。
JWT ミドルウェア (運用環境に必要):
import { authorizeJWT, loadAuthConfigFromEnv } from '@microsoft/agents-hosting'
const authConfig = loadAuthConfigFromEnv()
server.use(authorizeJWT(authConfig))
ローカル開発:
ローカル デバッグでは、JWT 検証を無効にすることができます。
// Only for local development - NEVER in production
if (process.env.NODE_ENV === 'development') {
// JWT validation disabled for local testing
} else {
server.use(authorizeJWT(authConfig))
}
サーバーセットアップオプション
Agents SDK には、サーバーを設定するための 2 つの方法が用意されています。
startServer メソッドを使用する
最小限のセットアップが必要で、カスタム ミドルウェアが必要ない場合は、この簡略化されたアプローチを新しいプロジェクトに使用します。
botbuilderから初期化コードを更新します。
const { EchoBot } = require('./bot');
const {
CloudAdapter,
ConfigurationBotFrameworkAuthentication
} = require('botbuilder');
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env);
const adapter = new CloudAdapter(botFrameworkAuthentication);
const myBot = new EchoBot();
const server = express();
server.use(express.json());
server.post('/api/messages', async (req, res) =>
await adapter.process(req, res, (context) =>
myBot.run(context));
);
startServer() でのエージェント ホスティング:
const { EchoBot } = require('./bot');
const { startServer } = require('@microsoft/agents-hosting-express')
startServer(new EchoBot());
手動による高速セットアップ
既存のボットを移行する場合、カスタム ミドルウェアが必要な場合、Express 構成を完全に制御する場合は、この方法を使用します
const { EchoBot } = require('./bot');
const {
CloudAdapter,
loadAuthConfigFromEnv, // Update
authorizeJWT // Update
} = require('@microsoft/agents-hosting'); // Update
const authConfig = loadAuthConfigFromEnv(); // Update
const adapter = new CloudAdapter(authConfig); // Update
const myBot = new EchoBot();
const server = express();
server.use(express.json());
server.use(authorizeJWT(authConfig)); // Update
server.post('/api/messages', async (req, res) =>
await adapter.process(req, res, (context) =>
myBot.run(context));
);
const port = process.env.PORT || 3978;
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
}).on('error', (err) => {
console.error('Server failed to start:', err);
process.exit(1);
});
ActivityHandler のサポート
Bot Framework SDK で作成されたほとんどのボットは、 botbuilder-core.ActivityHandler 基本クラスに基づいています。
Agents SDK には、移行を容易にするために同じ API サーフェスを維持する互換性のある agents-hosting.ActivityHandler が用意されています。
主な違い
Bot Framework SDK と Agents SDK の主な違いは次のとおりです。
ハンドラー パラメーター:
| SDK | ハンドラーの種類 |
|---|---|
| Bot Framework SDK(ボット フレームワーク ソフトウェア開発キット) | BotHandler |
| エージェント SDK | AgentHandler |
Agents SDK のその他のメソッド:
| Method | Description |
|---|---|
onMessageDelete |
メッセージ削除アクティビティを処理する |
onMessageUpdate |
メッセージ更新アクティビティを処理する |
onSignInInvoke |
サインイン呼び出しアクティビティを処理します |
Agents SDK にメソッドがありません:
| Method | 理由 |
|---|---|
onCommand |
コマンド アクティビティはサポートされていません |
onCommandResult |
コマンド結果アクティビティはサポートされていません |
onEvent |
汎用イベント処理 ( onTokenResponseEvent などの特定のイベントの種類は引き続きサポートされています) |
onTokenResponseEvent |
OAuth トークン応答イベント |
メソッド シグネチャの変更:
すべてのハンドラー メソッドは、メソッド チェーンのActivityHandlerではなく、thisを返します。 ハンドラー関数は、同じシグネチャを持つ AgentHandler 型を使用します BotHandler
移行の例:
ボットフレームワークSDK:
const { ActivityHandler } = require('botbuilder');
class MyBot extends ActivityHandler {
constructor() {
super();
this.onMessage(async (context, next) => {
await context.sendActivity('Hello!');
await next();
});
}
}
移行はほとんど簡単で、主な変更は import ステートメントとハンドラーの種類です。 既存の ActivityHandlerベースのボットのほとんどは、最小限の変更で動作する必要があります。
Important
新しいActivityHandler クラスを優先して、AgentApplicationは非推奨になりました
ActivityHandler から AgentApplication への移行
下位互換性のために ActivityHandler がサポートされていますが、 AgentApplicationを使用することをお勧めします。
ActivityHandlerの使用
import { ActivityHandler } from '@microsoft/agents-hosting'
class MyBot extends ActivityHandler {
constructor() {
super()
this.onMessage(async (context, next) => {
await context.sendActivity('Hello!')
await next()
})
this.onMembersAdded(async (context, next) => {
await context.sendActivity('Welcome!')
await next()
})
}
}
主な違い
次の表では、 ActivityHandler と AgentApplicationの主な機能の違いについて説明します。
| 特徴 | ActivityHandler |
AgentApplication |
|---|---|---|
| 状態管理 | 手動による状態管理が必要 | 提供される組み込みの状態管理 |
| イベント処理 | 汎用イベント ハンドラー ( onMembersAddedなど) |
より具体的なイベント ハンドラー ( membersAddedなど) |
| 次の関数 | ハンドラーには呼び出しが必要です next() |
ハンドラーは呼び出しを必要としません next() |
| Storage | 手動ストレージ構成 | 自動状態永続化を使用した組み込みストレージのサポート |
一般的な移行パターン
一般的な移行パターンは次のとおりです。
シンプルエコーボット
Bot Framework
const { ActivityHandler } = require('botbuilder')
class EchoBot extends ActivityHandler {
constructor() {
super()
this.onMessage(async (context, next) => {
await context.sendActivity(`You said: ${context.activity.text}`)
await next()
})
}
}
状態管理
AgentApplicationの使用
import { AgentApplication, MemoryStorage } from '@microsoft/agents-hosting'
const agent = new AgentApplication({
storage: new MemoryStorage()
})
agent.onMessage('/count', async (context, state) => {
const count = state.conversation.count ?? 0
state.conversation.count = count + 1
await context.sendActivity(`Count: ${state.conversation.count}`)
})
AgentApplication からの継承
より複雑なシナリオでは、 AgentApplicationから継承するクラスを作成できます。
import { AgentApplication, MemoryStorage, MessageFactory } from '@microsoft/agents-hosting'
class MyAgent extends AgentApplication {
constructor() {
super({
storage: new MemoryStorage()
})
this.setupRoutes()
}
setupRoutes() {
this.onMessage('/help', this.handleHelp)
this.onMessage('/status', this.handleStatus)
this.onMessage('/reset', this.handleReset)
this.onActivity('message', this.handleDefault)
this.onConversationUpdate('membersAdded', this.handleWelcome)
}
handleHelp = async (context, state) => {
const helpText = `
Available commands:
- /help - Show this help message
- /status - Show current status
- /reset - Reset conversation state
`
await context.sendActivity(MessageFactory.text(helpText))
}
handleStatus = async (context, state) => {
const messageCount = state.conversation.messageCount ?? 0
await context.sendActivity(`Messages processed: ${messageCount}`)
}
handleReset = async (context, state) => {
state.deleteConversationState()
await context.sendActivity('Conversation state has been reset.')
}
handleWelcome = async (context, state) => {
const welcomeText = 'Welcome! Type /help to see available commands.'
await context.sendActivity(MessageFactory.text(welcomeText))
}
handleDefault = async (context, state) => {
// Increment message counter
const messageCount = (state.conversation.messageCount ?? 0) + 1
state.conversation.messageCount = messageCount
const replyText = `Echo: ${context.activity.text} (Message #${messageCount})`
await context.sendActivity(MessageFactory.text(replyText))
}
}
export default new MyAgent()
このパターンの利点
| Benefit | Description |
|---|---|
| 組織の改善 | 別々のハンドラー用のメソッド |
| 再 利用 | さらに簡単に拡張または継承できます |
| テスト可能性 | 個々のメソッドを単体テストできます |
| 保守容易性 | 複雑なボットのよりクリーンなコード構造 |
| 矢印関数 |
this コンテキストを .bind() なしで自動的にバインドします |