Partager via


Implémenter une compétence

S'APPLIQUE À : SDK v4

Vous pouvez utiliser des compétences pour étendre un autre bot. Une compétence est un bot qui peut effectuer un ensemble de tâches pour un autre bot.

  • Un manifeste décrit l’interface d’une compétence. Les développeurs qui n’ont pas accès au code source de la compétence peuvent utiliser les informations du manifeste pour concevoir leur consommateur de compétences.
  • Une compétence peut utiliser la validation des revendications pour gérer les bots ou les utilisateurs qui peuvent y accéder.

Cet article montre comment implémenter une compétence qui répercute l’entrée de l’utilisateur.

Certains types de consommateurs de compétences ne peuvent pas utiliser certains types de bots de compétence. Le tableau suivant décrit les combinaisons prises en charge.

  Compétence multilocataire Compétence monolocataire Compétence en matière d'identité managée affectée par l'utilisateur
Consommateur multilocataire Pris en charge Non pris en charge Non pris en charge
Consommateur d'un locataire unique Non pris en charge Pris en charge, si les deux applications appartiennent au même locataire Pris en charge, si les deux applications appartiennent au même locataire
Consommateur d'identité managée affectée par l'utilisateur Non pris en charge Pris en charge, si les deux applications appartiennent au même locataire Pris en charge, si les deux applications appartiennent au même locataire

Remarque

Les kits SDK JavaScript, C# et Python Bot Framework continueront d’être pris en charge. Toutefois, le kit de développement logiciel (SDK) Java est mis hors service avec une prise en charge finale à long terme se terminant en novembre 2023.

Les bots existants créés avec le kit de développement logiciel (SDK) Java continueront de fonctionner.

Pour la nouvelle génération de bots, envisagez d’utiliser Microsoft Copilot Studio et lisez-en plus sur le choix de la solution copilote appropriée.

Pour plus d’informations, consultez Les futures versions de bot.

Prérequis

Remarque

À compter de la version 4.11, vous n'avez pas besoin d'un ID d'application et d'un mot de passe pour tester une compétence localement dans le Bot Framework Emulator. Un abonnement Azure est toujours nécessaire pour déployer votre compétence sur Azure.

À propos de cet exemple

L’exemple de bot-à-bot simple de compétences comprend des projets pour deux bots :

  • Bot de compétences echo, qui implémente la compétence.
  • Bot racine simple, qui implémente un bot racine qui consomme la compétence.

Cet article se concentre sur la compétence, qui comprend la logique de prise en charge dans son bot et son adaptateur.

Pour plus d’informations sur le bot racine simple, découvrez comment implémenter un consommateur de compétences.

Ressources

Pour les bots déployés, l'authentification entre bots exige que chaque bot participant ait une identité valide. Toutefois, vous pouvez tester localement les compétences et les consommateurs de compétences multilocataire avec l’émulateur sans ID d’application et mot de passe.

Pour mettre la compétence à la disposition des bots en contact avec l'utilisateur, enregistrez la compétence auprès d'Azure. Pour plus d'informations, découvrez comment inscrire un bot auprès d'Azure AI Bot Service.

Configuration de l’application

Vous pouvez également ajouter les informations relatives à l'identité de la compétence à son fichier de configuration. Si la compétence ou le consommateur de compétences fournit des informations d'identité, les deux le doivent.

Le groupe d’appelants autorisés peut limiter les consommateurs de compétences pouvant accéder à la compétence. Pour accepter les appels de n’importe quel consommateur de compétences, ajoutez un élément « * ».

Remarque

Si vous testez votre compétence localement sans informations d'identité de bot, ni la compétence ni le consommateur de compétences n'exécutent le code pour effectuer la validation des revendications.

EchoSkillBot\appsettings.json

Vous pouvez également ajouter les informations relatives à l'identité de la compétence au fichier .env.

{
  "MicrosoftAppType": "",
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "MicrosoftAppTenantId": "",

  // This is a comma separate list with the App IDs that will have access to the skill.
  // This setting is used in AllowedCallersClaimsValidator.
  // Examples: 
  //    [ "*" ] allows all callers.
  //    [ "AppId1", "AppId2" ] only allows access to parent bots with "AppId1" and "AppId2".
  "AllowedCallers": [ "*" ]
}

Logique du gestionnaire d’activités

Pour accepter les paramètres d’entrée

Le consommateur de compétences peut envoyer des informations à la compétence. Une façon d’accepter ces informations consiste à les accepter via la propriété value sur les messages entrants. Une autre méthode consiste à gérer les activités d’événement et d’appel.

La compétence de cet exemple n'accepte pas les paramètres d'entrée.

Pour continuer ou terminer une conversation

Quand la compétence envoie une activité, le consommateur de compétences doit transférer l’activité à l’utilisateur.

Toutefois, vous devez envoyer une endOfConversation activité lorsque la compétence se termine ; sinon, le consommateur de compétences continue de transférer les activités utilisateur à la compétence. Si vous le souhaitez, utilisez la propriété value de l’activité pour inclure une valeur de retour, puis utilisez la propriété code de l’activité pour indiquer pourquoi la compétence se termine.

EchoSkillBot\Bots\EchoBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    if (turnContext.Activity.Text.Contains("end") || turnContext.Activity.Text.Contains("stop"))
    {
        // Send End of conversation at the end.
        var messageText = $"ending conversation from the skill...";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput), cancellationToken);
        var endOfConversation = Activity.CreateEndOfConversationActivity();
        endOfConversation.Code = EndOfConversationCodes.CompletedSuccessfully;
        await turnContext.SendActivityAsync(endOfConversation, cancellationToken);
    }
    else
    {
        var messageText = $"Echo: {turnContext.Activity.Text}";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput), cancellationToken);
        messageText = "Say \"end\" or \"stop\" and I'll end the conversation and back to the parent.";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput), cancellationToken);
    }
}

Pour annuler la compétence

Pour les compétences multitours, vous pouvez aussi accepter les activités endOfConversation d’un consommateur de compétences pour permettre à celui-ci d’annuler la conversation en cours.

La logique de cette compétence ne change pas d'un tour à l'autre. Si vous implémentez une compétence qui alloue des ressources de conversation, ajoutez le code de nettoyage des ressources au gestionnaire de fin de conversation.

EchoSkillBot\Bots\EchoBot.cs

protected override Task OnEndOfConversationActivityAsync(ITurnContext<IEndOfConversationActivity> turnContext, CancellationToken cancellationToken)
{
    // This will be called if the root bot is ending the conversation.  Sending additional messages should be
    // avoided as the conversation may have been deleted.
    // Perform cleanup of resources if needed.
    return Task.CompletedTask;
}

Validateur de revendications

Cet exemple utilise une liste d’appelants autorisés pour la validation des revendications. Le fichier de configuration de la compétence définit la liste. L’objet validateur lit ensuite la liste.

Vous devez ajouter un validateur de revendications à la configuration de l'authentification. Les revendications sont évaluées après l’en-tête d’authentification. Votre code de validation doit lever une erreur ou une exception pour refuser la demande. Il existe de nombreuses raisons pour lesquelles vous souhaiterez peut-être rejeter une demande authentifiée. Par exemple :

  • La compétence fait partie d’un service payant. L'utilisateur ne figurant pas dans la base de données ne doit pas y avoir accès.
  • La compétence est privée. Seuls certains consommateurs de compétences peuvent appeler la compétence.

Important

Si vous ne fournissez pas de validateur de revendications, votre bot génère une erreur ou une exception lors de la réception d'une activité du consommateur de compétences.

Le kit de développement logiciel (SDK) fournit une classe AllowedCallersClaimsValidator qui ajoute une autorisation au niveau de l'application en fonction d'une liste simple d'ID des applications autorisées à appeler la compétence. Si la liste contient un astérisque (*), tous les appelants sont autorisés. Le validateur de revendications est configuré dans Startup.cs.

Adaptateur de compétences

Lorsqu’une erreur se produit, l’adaptateur de la compétence doit effacer l’état de la conversation de la compétence et doit aussi envoyer une activité endOfConversation au consommateur de compétences. Pour signaler que la compétence s’est terminée en raison d’une erreur, utilisez la propriété de code de l’activité.

EchoSkillBot\SkillAdapterWithErrorHandler.cs

private async Task HandleTurnError(ITurnContext turnContext, Exception exception)
{
    // Log any leaked exception from the application.
    _logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

    await SendErrorMessageAsync(turnContext, exception);
    await SendEoCToParentAsync(turnContext, exception);
}

private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
{
    try
    {
        // Send a message to the user.
        var errorMessageText = "The skill encountered an error or bug.";
        var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput);
        await turnContext.SendActivityAsync(errorMessage);

        errorMessageText = "To continue to run this bot, please fix the bot source code.";
        errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
        await turnContext.SendActivityAsync(errorMessage);

        // Send a trace activity, which will be displayed in the Bot Framework Emulator.
        // Note: we return the entire exception in the value property to help the developer;
        // this should not be done in production.
        await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
    }
}

private async Task SendEoCToParentAsync(ITurnContext turnContext, Exception exception)
{
    try
    {
        // Send an EndOfConversation activity to the skill caller with the error to end the conversation,
        // and let the caller decide what to do.
        var endOfConversation = Activity.CreateEndOfConversationActivity();
        endOfConversation.Code = "SkillError";
        endOfConversation.Text = exception.Message;
        await turnContext.SendActivityAsync(endOfConversation);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Exception caught in SendEoCToParentAsync : {ex}");
    }
}

Inscription du service

L’adaptateur Bot Framework utilise un objet de configuration d’authentification (défini quand l’adaptateur est créé) pour valider l’en-tête d’authentification sur les demandes entrantes.

Cet exemple ajoute la validation des revendications à la configuration de l’authentification et utilise l’adaptateur de compétences avec le gestionnaire d’erreurs décrit dans la section précédente.

EchoSkillBot\Startup.cs

    options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
});

// Register AuthConfiguration to enable custom claim validation.
services.AddSingleton(sp =>
{
    var allowedCallers = new List<string>(sp.GetService<IConfiguration>().GetSection("AllowedCallers").Get<string[]>());

    var claimsValidator = new AllowedCallersClaimsValidator(allowedCallers);

    // If TenantId is specified in config, add the tenant as a valid JWT token issuer for Bot to Skill conversation.
    // The token issuer for MSI and single tenant scenarios will be the tenant where the bot is registered.
    var validTokenIssuers = new List<string>();
    var tenantId = sp.GetService<IConfiguration>().GetSection(MicrosoftAppCredentials.MicrosoftAppTenantIdKey)?.Value;

    if (!string.IsNullOrWhiteSpace(tenantId))
    {
        // For SingleTenant/MSI auth, the JWT tokens will be issued from the bot's home tenant.
        // Therefore, these issuers need to be added to the list of valid token issuers for authenticating activity requests.
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV1, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV2, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV1, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV2, tenantId));
    }

    return new AuthenticationConfiguration
    {
        ClaimsValidator = claimsValidator,
        ValidTokenIssuers = validTokenIssuers
    };
});

// Create the Bot Framework Authentication to be used with the Bot Adapter.
services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

Manifeste de compétence

Un manifeste de compétence est un fichier JSON qui décrit les activités que la compétence peut effectuer, ses paramètres d’entrée et de sortie, ainsi que ses points de terminaison. Le manifeste contient les informations dont vous avez besoin pour accéder à la compétence d’un autre bot. La version la plus récente du schéma est v2.1.

EchoSkillBot\wwwroot\manifest\echoskillbot-manifest-1.0.json

{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
  "$id": "EchoSkillBot",
  "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"
    }
  ]
}

Le schéma de manifeste de compétence est un fichier JSON qui décrit le schéma du manifeste de compétence. La version actuelle du schéma est 2.1.0.

Tester la compétence

À ce stade, vous pouvez tester la compétence dans l’émulateur comme s’il s’agissait d’un bot normal. Toutefois, pour la tester en tant que compétence, vous devez implémenter un consommateur de compétences.

Téléchargez et installez la dernière version de Bot Framework Emulator.

  1. Exécutez le bot de compétences echo localement sur votre ordinateur. Si vous avez besoin d'instructions, reportez-vous au fichier README de l'échantillon C#, JavaScript, Java ou Python.
  2. Utiliser l’émulateur pour tester le bot. Lorsque vous envoyez un message « fin » ou « arrêter » à la compétence, cela envoie une activité endOfConversation en plus du message de réponse. La compétence envoie l’activité endOfConversation pour indiquer que la compétence est terminée.

Exemple de transcription montrant l’activité de fin de conversation.

Plus d'informations sur le débogage

Étant donné que le trafic entre les compétences et les consommateurs de compétences est authentifié, des étapes supplémentaires sont nécessaires pour déboguer ces bots.

  • Le consommateur de compétences et toutes les compétences qu'il consomme, directement ou indirectement, doivent être en cours d'exécution.
  • Si les bots s'exécutent localement et si l'un des bots a un ID d'application et un mot de passe, tous les bots doivent avoir des identifiants et des mots de passe valides.
  • Si les bots sont tous déployés, découvrez comment déboguer un bot à partir de n’importe quel canal à l’aide de devtunnel.
  • Si certains des bots s'exécutent localement et que d'autres sont déployés, découvrez comment déboguer une compétence ou un consommateur de compétences.

Dans le cas contraire, vous pouvez déboguer un consommateur de compétences ou une compétence comme vous déboguez d'autres bots. Pour plus d'informations, consultez Débogage d'un bot et Débogage avec Bot Framework Emulator.

Étapes suivantes