將 JavaScript v3 Bot 轉換為技能Convert a JavaScript v3 bot to a skill

適用于: SDK v4APPLIES TO: SDK v4

本文將說明如何將 2 個 JavaScript v3 Bot 範例轉換成技能,並建立可存取這些技能的 v4 技能取用者。This article describes how to convert 2 sample JavaScript v3 bots to skills and to create a v4 skill consumer that can access these skills. 若要將 .NET v3 Bot 轉換成技能,請參閱如何將 .NET v3 Bot 轉換成技能To convert a .NET v3 bot to a skill, see how to Convert a .NET v3 bot to a skill. 若要將 JavaScript Bot 從 v3 遷移至 v4,請參閱如何將 JavaScript v3 Bot 遷移至 v4 BotTo migrate a JavaScript bot from v3 to v4, see how to Migrate a Javascript v3 bot to a v4 bot.

PrerequisitesPrerequisites

  • Visual Studio Code。Visual Studio Code.
  • Node.js。Node.js.
  • Azure 訂用帳戶。An Azure subscription. 如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶If you don't have an Azure subscription, create a free account before you begin.
  • 若要測試技能,您將需要 bot 的 Bot Framework Emulator 和本機複本:To test the skills, you will need the Bot Framework Emulator and local copies of the bots:

關於 BotAbout the bots

在本文中,每個 v3 Bot 都會建立為技能。In this article, each v3 bot is created to act as a skill. 其中包含 v4 技能取用者,讓您可以測試轉換為技能的 Bot。A v4 skill consumer is included, so that you can test the converted bots as skills.

  • v3-skill-bot 會回應其所收到的訊息。The v3-skill-bot echoes back messages it receives. 技能會在收到「結束」或「停止」訊息時「完成」 。As a skill, it completes when it receives an "end" or "stop" message. 要轉換的 Bot 會以最小的 v3 Bot 作為基礎。The bot to convert is based on a minimal v3 bot.
  • v3-booking-bot-skill 可讓使用者預訂航班或旅館。The v3-booking-bot-skill allows the user to book a flight or a hotel. 技能會在完成時將收集的資訊傳回給父系。As a skill, it sends collected information back to the parent when finished.

此外,v4 技能取用者 v4-root-bot 會示範如何取用技能,並讓您進行測試。Also, a v4 skill consumer, the v4-root-bot, demonstrates how to consume the skills and allows you to test them.

若要使用技能取用者來測試技能,所有 3 個 Bot 都必須同時執行。To use the skill consumer to test the skills, all 3 bots need to be running at the same time. Bot 可以透過 Bot Framework Emulator 在本機進行測試,並讓每個 Bot 都使用不同的本機連接埠。The bots can be tested locally using the Bot Framework Emulator, with each bot using a different local port.

為 Bot 建立 Azure 資源Create Azure resources for the bots

Bot 對 Bot 驗證會要求每個參與的 Bot 都具備有效的應用程式識別碼和密碼。Bot-to-bot authentication requires that each participating bot has a valid app ID and password.

  1. 如有需要,可為 Bot 建立 Bot 通道註冊。Create a Bot Channels Registration for the bots as needed.
  2. 記錄每一個 Bot 的應用程式識別碼和密碼。Record the app ID and password for each one.

轉換 v3 botTo convert a v3 bot

將現有 Bot 轉換成技能 Bot 只需要幾個步驟,如以下幾節所述。To convert an existing bot to a skill bot takes just a few steps, as outlined in the next couple sections. 如需更深入的資訊,請參閱關於技能For more in-depth information, see about skills.

  • 更新 Bot 的 .env 檔案,以設定 Bot 的應用程式識別碼和密碼,並新增「根 Bot 應用程式識別碼」 屬性。Update the bot's .env file to set the bot's app ID and password and to add a root bot app ID property.
  • 新增宣告驗證。Add claims validation. 這會限制技能的存取,僅限使用者或根 Bot 可以存取此技能。This will restrict access to the skill so that only users or your root bot can access the skill. 如需有關預設和自訂宣告驗證的詳細資訊,請參閱其他資訊一節。See the additional information section for more information about default and custom claims validation.
  • 修改 Bot 的訊息控制器,以處理來自根 Bot 的 endOfConversation 活動。Modify the bot's messages controller to handle endOfConversation activities from the root bot.
  • 修改 Bot 程式碼,使其在技能完成時傳回 endOfConversation 活動。Modify the bot code to return an endOfConversation activity when the skill completes.
  • 每當技能完成時,如果技能有交談狀態或繼續保有資源,則應該清除其交談狀態及釋出資源。Whenever the skill completes, if it has conversation state or maintains resources, it should clear its conversation state and release resources.
  • 選擇性地新增資訊清單檔。Optionally add a manifest file. 由於技能取用者不一定能夠存取技能程式碼,因此請使用技能資訊清單來描述技能可以接收和產生的活動、其輸入和輸出參數,以及技能的端點。Since a skill consumer does not necessarily have access to the skill code, use a skill manifest to describe the activities the skill can receive and generate, its input and output parameters, and the skill's endpoints. 目前的資訊清單結構描述是 skill-manifest-2.0.0.jsonThe current manifest schema is skill-manifest-2.0.0.json.

轉換回應 BotConvert the echo bot

如需已轉換成基本技能的 v3 回應 Bot 範例,請參閱 Skills/v3-skill-botSee Skills/v3-skill-bot for an example of a v3 echo bot that has been converted to a basic skill.

  1. 建立簡單的 JavaScript v3 Bot 專案,並匯入必要的模組。Create a simple JavaScript v3 bot project and import required modules.

    v3-skill-bot/app.jsv3-skill-bot/app.js

    const restify = require('restify');
    const builder = require('botbuilder');
    require('dotenv').config();
    
  2. 將 Bot 設定為在本機連接埠 3979 上執行。Set the bot to run locally on port 3979.

    v3-skill-bot/app.jsv3-skill-bot/app.js

    // Setup Restify Server
    const server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3979, function () {
       console.log('%s listening to %s', server.name, server.url); 
    });
    
  3. 在設定檔中,新增回應 Bot 的應用程式識別碼和密碼。In the configuration file, add the echo bot's app ID and password. 此外,使用簡單根 Bot 的應用程式識別碼作為其值來新增 ROOT_BOT_APP_ID 屬性。Also, add a ROOT_BOT_APP_ID property with the simple root bot's app ID as its value.

    v3-skill-bot/.envv3-skill-bot/.env

    # Bot Framework Credentials
    
    MICROSOFT_APP_ID=
    MICROSOFT_APP_PASSWORD=
    ROOT_BOT_APP_ID=
    
  4. 為 Bot 建立聊天連接器。Create the chat connector for the bot. 這會使用預設驗證設定。This one uses the default authentication configuration. enableSkills 設定為 true,以允許 Bot 作為技能使用。Set enableSkills to true to allow the bot to be used as a skill. allowedCallers 是允許使用此技能的 Bot 應用程式識別碼陣列。allowedCallers is an array of the app IDs of the bots allowed to use this skill. 如果這個陣列的第一個值是 ' * ',則任何 bot 都可以使用這項技能。If the first value of this array is '*', then any bot can use this skill.

    v3-skill-bot/app.jsv3-skill-bot/app.js

    // Create chat connector for communicating with the Bot Framework Service
    const connector = new builder.ChatConnector({
        appId: process.env.MICROSOFT_APP_ID,
        appPassword: process.env.MICROSOFT_APP_PASSWORD,
        enableSkills: true,
        allowedCallers: [process.env.ROOT_BOT_APP_ID]
    });
    
  5. 當使用者選擇結束技能時,更新訊息處理常式以傳送 endOfConversation 活動。Update the message handler to send an endOfConversation activity when the user chooses to end the skill.

    v3-skill-bot/app.jsv3-skill-bot/app.js

    // Create your bot with a function to receive messages from the user
    const bot = new builder.UniversalBot(connector, function (session) {
        switch (session.message.text.toLowerCase()) {
            case 'end':
            case 'stop':
                session.endConversation();
                break;
            default:
                session.send("Echo (JS V3) You said: %s", session.message.text);
                session.send('Say "end" or "stop" and I\'ll end the conversation and back to the parent.');
        }
    }).set('storage', inMemoryStorage); // Register in memory storage
    
  6. 由於此 Bot 不會維護對話狀態,而且不會為對話建立任何資源,因此 Bot 不需要處理從技能取用者接收的任何 endOfConversation 活動。Since this bot does not maintain conversation state and does not create any resources for the conversation, the bot does not need to handle any endOfConversation activities that it receives from the skill consumer.

  7. 針對回應 Bot 使用此資訊清單。Use this manifest for the echo bot. 將端點應用程式識別碼設定為 Bot 的應用程式識別碼。Set the endpoint app ID to the bot's app ID.

    v3-skill-bot/manifest/v3-skill-bot-manifest.jsonv3-skill-bot/manifest/v3-skill-bot-manifest.json

    {
        "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
        "$id": "v3-skill-bot",
        "name": "Echo Skill bot",
        "version": "1.0",
        "description": "This is a sample echo skill",
        "publisherName": "Microsoft",
        "privacyUrl": "https://echoskillbot.contoso.com/privacy.html",
        "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
        "license": "",
        "iconUrl": "https://echoskillbot.contoso.com/icon.png",
        "tags": [
          "sample",
          "echo"
        ],
        "endpoints": [
          {
            "name": "default",
            "protocol": "BotFrameworkV3",
            "description": "Default endpoint for the skill",
            "endpointUrl": "http://echoskillbot.contoso.com/api/messages",
            "msAppId": "00000000-0000-0000-0000-000000000000"
          }
        ]
      }
    

    如需技能-資訊清單結構描述的資訊,請參閱 skill-manifest-2.0.0.jsonFor the skill-manifest schema, see skill-manifest-2.0.0.json.

轉換預約 BotConvert the booking bot

如需已轉換成基本技能的 v3 預約 Bot 範例,請參閱 Skills/v3-booking-bot-skillSee Skills/v3-booking-bot-skill for an example of a v3 booking bot that has been converted to a basic skill. 在轉換之前,Bot 類似於 v3 core-MultiDialogs 範例。Before conversion, the bot was similar to the v3 core-MultiDialogs sample.

  1. 匯入必要的模組。Import required modules.

    v3-booking-bot-skill/app.jsv3-booking-bot-skill/app.js

    require('dotenv').config();
    
    var builder = require('botbuilder');
    var restify = require('restify');
    const skills = require('botbuilder/skills-validator');
    const { allowedCallersClaimsValidator } = require('./allowedCallersClaimsValidator');
    
  2. 將 Bot 設定為在本機連接埠 3980 上執行。Set the bot to run locally on port 3980.

    v3-booking-bot-skill/app.jsv3-booking-bot-skill/app.js

    // Setup Restify Server
    var server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3980, function () {
        console.log('%s listening to %s', server.name, server.url);
    });
    
  3. 在設定檔中,新增預約 Bot 的應用程式識別碼和密碼。In the configuration file, add the booking bot's app ID and password. 此外,使用簡單根 Bot 的應用程式識別碼作為其值來新增 ROOT_BOT_APP_ID 屬性。Also, add a ROOT_BOT_APP_ID property with the simple root bot's app ID as its value.

    v3-booking-bot-skill/.envv3-booking-bot-skill/.env

    # Bot Framework Credentials
    
    MICROSOFT_APP_ID=
    MICROSOFT_APP_PASSWORD=
    ROOT_BOT_APP_ID=
    
  4. 為 Bot 建立聊天連接器。Create the chat connector for the bot. 這會使用自訂驗證設定。This one uses a custom authentication configuration. enableSkills 設定為 true,以允許 Bot 作為技能使用。Set enableSkills to true to allow the bot to be used as a skill. authConfiguration 包含要用於驗證和宣告驗證的自訂驗證設定物件。authConfiguration contains the custom authentication configuration object to use for authentication and claims validation.

    v3-booking-bot-skill/app.jsv3-booking-bot-skill/app.js

    // Create chat bot and listen to messages
    var connector = new builder.ChatConnector({
        appId: process.env.MICROSOFT_APP_ID,
        appPassword: process.env.MICROSOFT_APP_PASSWORD,
        enableSkills: true,
        authConfiguration: new skills.AuthenticationConfiguration([], allowedCallersClaimsValidator)
    });
    

    v3-booking-bot-skill/allowedCallersClaimsValidator.jsv3-booking-bot-skill/allowedCallersClaimsValidator.js

    這會實作自訂宣告驗證,並在驗證失敗時擲回錯誤。This implements custom claims validation and throws an error if validation fails.

    const skills = require('botbuilder/skills-validator');
    const path = require('path');
    
    // Import required bot configuration.
    const ENV_FILE = path.join(__dirname, '.env');
    require('dotenv').config({ path: ENV_FILE });
    
    // Load the AppIds for the configured callers (we will only allow responses from skills we have configured).
    // process.env.AllowedCallers is the list of parent bot Ids that are allowed to access the skill
    // to add a new parent bot simply go to the .env file and add
    // the parent bot's Microsoft AppId to the list under AllowedCallers, e.g.:
    //  AllowedCallers=195bd793-4319-4a84-a800-386770c058b2,38c74e7a-3d01-4295-8e66-43dd358920f8
    const allowedCallers = [process.env.ROOT_BOT_APP_ID]; // process.env.AllowedCallers ? process.env.AllowedCallers.split(',') : undefined;
    
    /**
     * Sample claims validator that loads an allowed list from configuration if present
     * and checks that requests are coming from allowed parent bots.
     * @param claims An array of Claims decoded from the HTTP request's auth header
     */
    const allowedCallersClaimsValidator = async (claims) => {
        if (!allowedCallers || allowedCallers.length == 0) {
            throw new Error(`DefaultAuthenticationConfiguration allowedCallers must contain at least one element of '*' or valid MicrosoftAppId(s).`);
        }
        if (!claims || claims.length < 1) {
            throw new Error(`DefaultAuthenticationConfiguration.validateClaims.claims parameter must contain at least one element.`);
        }
        // If allowedCallers is undefined we allow all calls
        // If allowedCallers contains '*' we allow all callers
        if (skills.SkillValidation.isSkillClaim(claims)) {
                    
            if(allowedCallers[0] === '*') {
                return;
            }
            // Check that the appId claim in the skill request is in the list of skills configured for this bot.
            const appId = skills.JwtTokenValidation.getAppIdFromClaims(claims);
            if (allowedCallers.includes(appId)) {
                return;
            }
            throw new Error(`Received a request from a bot with an app ID of "${ appId }". To enable requests from this caller, add the app ID to your configuration file.`);
        }
        throw new Error(`DefaultAuthenticationConfiguration.validateClaims called without a Skill claim in claims.`);
    };
    
    module.exports.allowedCallersClaimsValidator = allowedCallersClaimsValidator;
    
  5. 更新訊息處理常式,以在技能結束時傳送 endOfConversation 活動。Update the message handler to send an endOfConversation activity when the skill ends. 請注意,除了傳送 endOfConversation 活動之外,session.endConversation() 也會清除交談狀態。Note that session.endConversation() clears conversation state in addition to sending an endOfConversation activity.

    v3-booking-bot-skill/app.jsv3-booking-bot-skill/app.js

    執行 helper 函式,以設定 endOfConversation 活動的 codevalue 屬性,並清除交談狀態。Implement a helper function to set the endOfConversation activity's code and value properties and clear conversation state. 如果 Bot 有管理交談的任何其他資源,您也可以在這裡釋出這些資源。If the bot managed any other resources for the conversation, you would release them here, too.

    // Code enum can be found here: https://aka.ms/codeEnum
    function endConversation(session, value = null, code = null) {
        session.send('Ending conversation from the skill...');
        // Send endOfConversation with custom code and values
        const msg = {
            value,
            code,
            type: 'endOfConversation'
        };
        session.send(msg);
        // Call endConversation() to clear state
        session.endConversation();
    }
    

    當使用者完成此程序時,請使用 helper 方法來結束技能,並傳回使用者收集的資料。When the user completes the process, use the helper method to end the skill and return the user's collected data.

    var bot = new builder.UniversalBot(connector, [
        function (session) {
    
        },
        // Dialog has ended
        function(session, result) {
            endConversation(session, result, 'completedSuccessfully');
        }
    ]).set('storage', inMemoryStorage); // Register in memory storage
    

    如果使用者提早結束程序,仍然會叫用 helper 方法。If instead the user ends the process early, the helper method is still invoked.

    bot.recognizer({
        recognize: function (context, done) {
            var intent = { score: 0.0 };
            if (context.message.text) {
                switch (context.message.text.toLowerCase()) {
                    case 'help':
                        intent = { score: 1.0, intent: 'Help' };
                        break;
                    case 'end':
                        intent = { score: 1.0, intent: 'End' };
                        break;
                }
            }
            done(null, intent);
        }
    });
    
    // Add global endConversation() action bound to the 'Goodbye' intent
    bot.endConversationAction('endAction', "Ok... See you later.", { matches: 'End' });
    
  6. 如果技能取用者取消技能,則取用者會傳送 endOfConversation 活動。If the skill is cancelled by the skill consumer, the consumer sends an endOfConversation activity. 處理此活動並釋出與交談相關聯的任何資源。Handle this activity and release any resources associated with the conversation.

    v3-booking-bot-skill/app.jsv3-booking-bot-skill/app.js

    // Listen for endOfConversation activities from other sources
    bot.on('endOfConversation', (message) => {
        bot.loadSession(message.address, (err, session) => {
            endConversation(session, null, 'completedSuccessfully');
        });
    })
    
  7. 針對預約 Bot 使用此資訊清單。Use this manifest for the booking bot. 將端點應用程式識別碼設定為 Bot 的應用程式識別碼。Set the endpoint app ID to the bot's app ID.

    v3-booking-bot-skill/manifest/v3-booking-bot-skill-manifest.jsonv3-booking-bot-skill/manifest/v3-booking-bot-skill-manifest.json

    {
        "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
        "$id": "v3-booking-bot-skill",
        "name": "Booking Skill bot",
        "version": "1.0",
        "description": "This is a sample booking skill",
        "publisherName": "Microsoft",
        "privacyUrl": "https://bookingskillbot.contoso.com/privacy.html",
        "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
        "license": "",
        "iconUrl": "https://bookingskillbot.contoso.com/icon.png",
        "tags": [
          "sample",
          "echo"
        ],
        "endpoints": [
          {
            "name": "default",
            "protocol": "BotFrameworkV3",
            "description": "Default endpoint for the skill",
            "endpointUrl": "http://bookingskillbot.contoso.com/api/messages",
            "msAppId": "00000000-0000-0000-0000-000000000000"
          }
        ]
      }
    

    如需技能-資訊清單結構描述的資訊,請參閱 skill-manifest-2.0.0.jsonFor the skill-manifest schema, see skill-manifest-2.0.0.json.

建立 v4 根 BotCreate the v4 root bot

簡單的根 Bot 會取用 2 個技能,並可讓您確認轉換步驟是否如預期運作。The simple root bot consumes the 2 skills and lets you verify that the conversion steps worked as planned. 此 Bot 會在本機連接埠 3978 上執行。This bot will run locally on port 3978.

  1. 在設定檔中,新增根 Bot 的應用程式識別碼和密碼。To the configuration file, add the root bot's app ID and password. 針對每個 v3 技能,新增技能的應用程式識別碼。For each of the v3 skills, add the skill's app ID.

    v4-root-bot/.envv4-root-bot/.env

    MicrosoftAppId=
    MicrosoftAppPassword=
    SkillHostEndpoint=http://localhost:3978/api/skills
    
    SkillSimpleId=v3-skill-bot
    SkillSimpleAppId=
    SkillSimpleEndpoint=http://localhost:3979/api/messages
    
    SkillBookingId=v3-booking-bot-skill
    SkillBookingAppId=
    SkillBookingEndpoint=http://localhost:3980/api/messages
    

測試根目錄 BotTest the root bot

下載並安裝最新版 Bot Framework EmulatorDownload and install the latest Bot Framework Emulator.

  1. 在您的機器上啟動這所有三個 Bot。Start all three bots locally on your machine.
  2. 使用 Emulator 連線到根 Bot。Use the Emulator to connect to the root bot.
  3. 測試技能和技能取用者。Test the skills and skill consumer.

從4.11 版開始,您不需要應用程式識別碼和密碼,即可在模擬器中本機測試技能和技能取用者。Starting with version 4.11, you don't need an app ID and password to test a skill and skill consumer locally in the Emulator. 將您的技能部署至 Azure 時,仍需要 Azure 訂用帳戶。An Azure subscription is still required to deploy your skill to Azure.

其他資訊Additional information

Bot 對 Bot 驗證Bot-to-bot authentication

根和技能會透過 HTTP 進行通訊。The root and skill communicate over HTTP. 其架構會使用持有人權杖和 Bot 應用程式識別碼來驗證每個 Bot 的身分識別。The framework uses bearer tokens and bot application IDs to verify the identity of each bot. 並使用驗證設定物件,來驗證傳入要求的驗證標題。It uses an authentication configuration object to validate the authentication header on incoming requests. 您必須將宣告驗證程式新增至驗證設定。You must add a claims validator to the authentication configuration. 宣告會在驗證標題之後進行評估。The claims are evaluated after the authentication header. 您的驗證程式碼應該會擲回錯誤或例外狀況,以拒絕要求。Your validation code should throw an error or exception to reject the request.

建立聊天連接器時,請在 settings 參數中包含 allowedCallersauthConfiguration 屬性,以啟用「Bot 對 Bot」驗證。When creating a chat connector, include either an allowedCallers or an authConfiguration property in the settings parameter to enable bot-to-bot authentication.

聊天連接器的預設宣告驗證程式會使用 allowedCallers 屬性。The default claims validator for the chat connector uses the allowedCallers property. 其值應為 Bot 的應用程式識別碼陣列,表示這些 Bot 可以呼叫技能。Its value should be an array of the application IDs of the bots that are allowed to call the skill. 將第一個元素設定為 ' * ',以允許任何 bot 呼叫技能。Set the first element to '*' to allow any bot to call the skill.

若要使用自訂宣告驗證函式,請將 authConfiguration 欄位設定為您的驗證函式。To use a custom claims validation function, set the authConfiguration field to your validation function. 此函式應接受宣告物件的陣列,並在驗證失敗時擲回錯誤。This function should accept an array of claim objects and throw an error if validation fails. 預約 Bot 一節的步驟 4 包含宣告驗證程式範例。Step 4 of the convert the booking bot section has an example claims validator.