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.

  • L’interface d’une compétence est décrite par un manifeste. 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 Prise 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 de développement logiciel (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. Seuls les correctifs de sécurité critiques et de bogues dans ce référentiel seront appliqués.

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

Pour la nouvelle version de bot, envisagez d'utiliser Power Virtual Agents et découvrez comment choisir la solution de bot conversationnel 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 les compétences multilocataires et les consommateurs de compétences localement 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. Ajoutez un élément « * » pour accepter les appels de n'importe quel consommateur de compétences.

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 activité endOfConversation lorsque la compétence se termine ; sinon, le consommateur de compétences continue de transférer les activités de l’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. La liste est définie dans le fichier de configuration de la compétence et est lue dans l’objet validateur lors de sa création.

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. Nombreuses sont les raisons pour lesquelles vous pouvez souhaiter refuser une demande authentifiée autrement. 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. Utilisez la propriété code de l’activité pour signaler que la compétence s’est terminée en raison d’une erreur.

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. Utilisez l’émulateur pour tester le bot comme indiqué ci-dessous. 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 qu’elle est terminée.

Example transcript showing the end-of-conversation activity.

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.

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