Implementar um skill

aplica-se a: SDK v4

Você pode usar skills para estender outro bot. Um skill é um bot que pode executar um conjunto de tarefas para outro bot.

  • A interface de um skill é descrita por um manifesto. Os desenvolvedores que não têm acesso ao código-fonte do skill podem usar as informações do manifesto para criar um consumidor de skill.
  • Um skill pode usar a validação de declarações para gerenciar quais bots ou usuários podem acessá-lo.

Este artigo demonstra como implementar um skill que ecoa a entrada do usuário.

Pré-requisitos

Observação

A partir da versão 4.11, você não precisa de uma ID de aplicativo e senha para testar uma habilidade localmente no Emulator. Uma assinatura do Azure ainda é necessária para implantar sua habilidade no Azure.

Sobre este exemplo

O exemplo bot para bot de skills simples inclui projetos para dois bots:

  • O bot skill de eco, que implementa o skill.
  • O bot raiz simples, que implementa um bot raiz que consome o skill.

Este artigo se concentra no skill, que inclui a lógica de suporte em seu bot e adaptador.

Para obter informações sobre o bot raiz simples, consulte como Implementar um consumidor de skills.

Recursos

Para bots implantados, a autenticação de bot para bot requer que cada bot participante tenha uma ID de aplicativo e uma senha válidas. No entanto, você pode testar habilidades e consumidores de habilidades localmente com o Emulator sem uma ID de aplicativo e senha.

Para disponibilizar a habilidade para bots voltados para o usuário, registre a habilidade no Azure. Você pode usar um Registro de Canais de Bot. Para obter mais informações, veja como registrar um bot com o Serviço de Bot do Azure.

Configuração de aplicativo

Opcionalmente, adicione a ID do aplicativo e a senha da habilidade ao arquivo de configuração da habilidade. (Se o consumidor de habilidades ou habilidades usar uma ID do aplicativo e uma senha, ambos deverão.)

A matriz de chamadores permitidos pode restringir quais consumidores de skills podem acessar o skill. Adicione um elemento "*" para aceitar chamadas de qualquer consumidor de habilidades.

Observação

Se você estiver testando sua habilidade localmente sem uma ID de aplicativo e senha, nem a habilidade nem o consumidor de habilidades executarão o código para executar a validação de declarações.

EchoSkillBot\appsettings.json

Adicione a ID do aplicativo e a senha do skill ao arquivo appsettings.json.

{
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",

  // 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": [ "*" ]
}

Lógica do manipulador de atividades

Para aceitar parâmetros de entrada

O consumidor de skills pode enviar informações para o skill. Uma maneira de aceitar essas informações é aceitá-las por meio da propriedade valor em mensagens de entrada. Outra maneira é manipular atividades de evento e invocação.

A habilidade neste exemplo não aceita parâmetros de entrada.

Para continuar ou concluir uma conversa

Quando o skill envia uma atividade, o consumidor de skills deve encaminhar a atividade para o usuário.

No entanto, você precisa enviar uma atividade endOfConversation quando o skill for concluído; caso contrário, o consumidor de skills continuará a encaminhar as atividades do usuário para o skill. Opcionalmente, use a propriedade valor da atividade para incluir um valor retornado e use a propriedade código da atividade para indicar por que o skill está terminando.

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);
    }
}

Para cancelar o skill

Para skills de vários ciclos, você também aceitará atividades endOfConversation de um consumidor de skills, para permitir que o consumidor cancele a conversa atual.

A lógica dessa habilidade não muda de turno para turno. Se você implementar um skill que aloque recursos de conversa, adicione o código de limpeza de recurso ao manipulador de fim de conversa.

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;
}

Validador de declarações

Este exemplo usa uma lista de chamadores permitidos para validação de declarações. A lista é definida no arquivo de configuração do skill e é lida no objeto do validador quando ele é criado.

Você deve adicionar um validador de declarações à configuração de autenticação. As declarações são avaliadas após o cabeçalho de autenticação. O código de validação deve gerar um erro ou uma exceção para rejeitar a solicitação. Há muitos motivos pelos quais você pode rejeitar uma solicitação autenticada de outra forma. Por exemplo:

  • O skill faz parte de um serviço pago. O usuário não está no banco de dados não deve ter acesso.
  • O skill é proprietário. Somente determinados consumidores de skills podem chamar o skill.

Importante

Se você não fornecer um validador de declarações, seu bot gerará um erro ou exceção ao receber uma atividade do consumidor de habilidades.

O SDK fornece uma classe que adiciona autorização no nível do aplicativo com base em uma lista simples de IDs dos aplicativos que têm permissão para AllowedCallersClaimsValidator chamar a habilidade. Se a lista contiver um asterisco (*), todos os chamadores serão permitidos. O validador de declarações é configurado em Startup.cs.

Adaptador de skill

Quando ocorre um erro, o adaptador do skill deve limpar o estado da conversa para o skill e também deve enviar uma atividade endOfConversation para o consumidor de skills. Use a propriedade código da atividade para sinalizar que o skill foi encerrado devido a um erro.

EchoSkillBot\SkillAdapterWithErrorHandler.cs

public SkillAdapterWithErrorHandler(IConfiguration configuration, ICredentialProvider credentialProvider, AuthenticationConfiguration authConfig, ILogger<BotFrameworkHttpAdapter> logger)
    : base(configuration, credentialProvider, authConfig, logger: logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    OnTurnError = HandleTurnError;
}

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}");
    }
}

Registro do serviço

O adaptador do Bot Framework usa um objeto de configuração de autenticação (definido quando o adaptador é criado) para validar o cabeçalho de autenticação em solicitações de entrada.

Este exemplo adiciona validação de declarações à configuração de autenticação e usa o adaptador de habilidade com o manipulador de erros descrito na seção anterior.

EchoSkillBot\Startup.cs

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

// Create the Bot Framework Adapter with error handling enabled.
services.AddSingleton<IBotFrameworkHttpAdapter, SkillAdapterWithErrorHandler>();

Manifesto de skills

Um manifesto de skill é um arquivo JSON que descreve as atividades que o skill pode executar, seus parâmetros de entrada e saída e os pontos de extremidade do skill. O manifesto contém as informações necessárias para acessar o skill por meio de outro bot. A versão mais recente do esquema é a 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"
    }
  ]
}

O esquema de manifesto do skill é um arquivo JSON que descreve o esquema do manifesto de skill. A versão atual do esquema é 2.1.0.

Testar o skill

Neste ponto, você pode testar o skill no Emulador como se fosse um bot normal. No entanto, para testá-lo como um skill, você precisaria implementar um consumidor de skills.

Baixe e instale o Bot Framework Emulator mais recente

  1. Execute o bot skill de eco localmente em seu computador. Se você precisar de instruções, consulte o README arquivo para o exemplo C#, JavaScript, Javaou Python.
  2. Use o Emulador para testar o bot, conforme mostrado abaixo. Quando você envia uma mensagem "end" ou "stop" para a habilidade, ela envia uma endOfConversation atividade além da mensagem de resposta. O skill envia a atividade endOfConversation para indicar que o skill foi concluído.

testar o skill de eco

Próximas etapas