Partilhar via


Implementar uma habilidade

APLICA-SE A: SDK v4

Você pode usar habilidades para estender outro bot. Uma habilidade é um bot que pode executar um conjunto de tarefas para outro bot.

  • Um manifesto descreve a interface de uma habilidade. Os desenvolvedores que não têm acesso ao código-fonte da habilidade podem usar as informações no manifesto para projetar seu consumidor de habilidades.
  • Uma habilidade pode usar a validação de declarações para gerenciar quais bots ou usuários podem acessá-la.

Este artigo demonstra como implementar uma habilidade que ecoa a entrada do usuário.

Alguns tipos de utilizadores de competências não são capazes de utilizar alguns tipos de bots de competências. A tabela a seguir descreve quais combinações são suportadas.

  Habilidade multicliente Habilidade de inquilino único Habilidade de identidade gerenciada atribuída pelo usuário
Consumidor multilocatário Suportado Não suportado Não suportado
Consumidor exclusivo Não suportado Suportado se ambas as aplicações pertencerem ao mesmo inquilino Suportado se ambas as aplicações pertencerem ao mesmo inquilino
Consumidor de identidade gerenciada atribuído pelo usuário Não suportado Suportado se ambas as aplicações pertencerem ao mesmo inquilino Suportado se ambas as aplicações pertencerem ao mesmo inquilino

Importante

O Bot Framework SDK e o Bot Framework Emulator foram arquivados no GitHub. O projeto já não é atualizado nem mantido. Os tíquetes de suporte para o SDK do Bot Framework não serão mais atendidos a partir de 31 de dezembro de 2025.

Para criar agentes com sua escolha de serviços, orquestração e conhecimento de IA, considere usar o SDK de agentes do Microsoft 365. O SDK Agents tem suporte para C#, JavaScript ou Python. Você pode saber mais sobre o SDK de agentes em aka.ms/agents. Se você tiver um bot existente criado com o SDK do Bot Framework, poderá atualizar seu bot para o SDK de agentes. Consulte as alterações e atualizações principais na orientação de migração do Bot Framework SDK para o SDK dos Agentes.

Se você estiver procurando por uma plataforma de agente baseada em SaaS, considere o Microsoft Copilot Studio.

Pré-requisitos

Nota

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

Sobre este exemplo

O exemplo de habilidades simples entre bots inclui projetos para dois bots:

  • O bot de habilidade do Echo, que implementa a habilidade.
  • O bot raiz simples, que implementa um bot raiz que consome a competência.

Este artigo se concentra na habilidade, que inclui lógica de suporte em seu bot e adaptador.

Para obter informações sobre o bot raiz simples, veja como implementar um consumidor de competências.

Recursos

Para bots implantados, a autenticação de bot para bot requer que cada bot participante tenha informações de identidade válidas. No entanto, é possível testar funcionalidades multicliente e os seus utilizadores localmente com o emulador, sem necessidade de um ID de aplicação e senha.

Para disponibilizar a habilidade para bots voltados para o usuário, registre a habilidade no Azure. Para obter mais informações, consulte como registar um bot com o Serviço de Bots do Azure AI.

Configuração da aplicação

Opcionalmente, adicione as informações de identidade da habilidade ao seu arquivo de configuração. Se a habilidade ou o consumidor de habilidade fornecer informações de identidade, ambos devem fazê-lo.

A matriz de chamadores permitidos pode restringir quais competências os utilizadores podem acessar. Para aceitar chamadas de qualquer consumidor qualificado, adicione um elemento "*".

Nota

Se estiver a testar a sua competência localmente sem informações de identidade do bot, nem a competência nem o consumidor de competência executarão o código para validar as declarações.

EchoSkillBot\appsettings.jsativado

Opcionalmente, adicione as informações de identidade da habilidade ao arquivo appsettings.json.

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

Lógica do manipulador de atividades

Para aceitar parâmetros de entrada

O utilizador da competência pode enviar informações para a competência. Uma maneira de aceitar essas informações é aceitá-las por meio da propriedade value nas mensagens recebidas. Outra maneira é gerir eventos e invocar atividades.

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

Para continuar ou concluir uma conversa

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

No entanto, você precisa enviar uma endOfConversation atividade quando a habilidade terminar; caso contrário, o consumidor da habilidade continuará a encaminhar as atividades do usuário para a habilidade. Opcionalmente, use a propriedade value da atividade para incluir um valor de retorno e use a propriedade code da atividade para indicar por que a habilidade 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 a habilidade

Para habilidades multiturno, deverias aceitar também endOfConversation atividades de um utilizador da habilidade, para permitir que o utilizador interrompa a conversa atual.

A lógica para esta habilidade não muda de turno para turno. Se você implementar uma habilidade que aloca recursos de conversa, adicione o código de limpeza de recursos 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. O arquivo de configuração da habilidade define a lista. Em seguida, o objeto validador lê a lista.

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. Seu código de validação deve gerar um erro ou exceção para rejeitar a solicitação. Há muitos motivos pelos quais você pode querer rejeitar uma solicitação autenticada de outra forma. Por exemplo:

  • A habilidade faz parte de um serviço pago. O usuário que não está no banco de dados não deve ter acesso.
  • A habilidade é exclusiva. Apenas certos consumidores de habilidades podem chamar a habilidade.

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 AllowedCallersClaimsValidator 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 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 habilidades

Quando ocorre um erro, o adaptador da competência deve limpar o estado de conversação da competência e também deve enviar uma endOfConversation atividade para o consumidor da competência. Para indicar que a habilidade terminou devido a um erro, utilize a propriedade code da atividade.

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

Registo do serviço

O adaptador 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 habilidades com manipulador de erros descrito na seção anterior.

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

Manifesto de habilidades

Um manifesto de habilidade é um arquivo JSON que descreve as atividades que a habilidade pode executar, seus parâmetros de entrada e saída e os pontos de extremidade da habilidade. O manifesto contém as informações que você precisa para acessar a habilidade de outro bot. A versão mais recente do esquema é v2.1.

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

{
  "$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 de habilidade é um arquivo JSON que descreve o esquema do manifesto de habilidade. A versão atual do esquema é 2.1.0.

Teste a habilidade

Neste ponto, você pode testar a habilidade no emulador como se fosse um bot normal. No entanto, para testá-lo como uma habilidade, você precisaria implementar um consumidor de habilidades.

Baixe e instale o mais recente Bot Framework Emulator

  1. Execute o bot de habilidade de eco localmente na sua máquina. Se precisar de instruções, consulte o README arquivo para o exemplo de C#, JavaScript, Java ou Python.
  2. Use o emulador para testar o bot. Quando você envia uma mensagem de "fim" ou "parar" para a habilidade, ela envia uma endOfConversation atividade além da mensagem de resposta. A habilidade envia a atividade endOfConversation para indicar que a habilidade está concluída.

Exemplo de transcrição mostrando a atividade de fim de conversa.

Mais sobre depuração

Como o tráfego entre habilidades e consumidores de habilidades é autenticado, há etapas extras ao depurar esses bots.

  • O consumidor de competências e todas as competências que consome, direta ou indiretamente, devem estar a funcionar.
  • Se os bots estiverem sendo executados localmente e se algum deles tiver um ID de aplicativo e senha, todos os bots deverão ter IDs e senhas válidas.
  • Se todos os bots estiverem implantados, veja como Depurar um bot de qualquer canal usando devtunnel.
  • Se alguns dos bots estiverem a ser executados localmente e alguns forem implantados, veja como Depurar uma habilidade ou um cliente de habilidade.

Caso contrário, tu podes depurar um consumidor de competências ou uma competência da mesma forma que depuras outros bots. Para obter mais informações, consulte Depurando um bot e Depurando com o emulador do Bot Framework.

Próximos passos