Een vaardigheid implementeren
VAN TOEPASSING OP: SDK v4
U kunt vaardigheden gebruiken om een andere bot uit te breiden. Een vaardigheid is een bot die een set taken voor een andere bot kan uitvoeren.
- Een manifest beschrijft de interface van een vaardigheid. Ontwikkelaars die geen toegang hebben tot de broncode van de vaardigheid, kunnen de informatie in het manifest gebruiken om hun vaardigheidsgebruiker te ontwerpen.
- Een vaardigheid kan claimvalidatie gebruiken om te beheren welke bots of gebruikers er toegang toe hebben.
In dit artikel wordt uitgelegd hoe u een vaardigheid implementeert die de invoer van de gebruiker weergeeft.
Sommige typen vaardigheidsgebruikers kunnen bepaalde typen vaardigheidsbots niet gebruiken. In de volgende tabel wordt beschreven welke combinaties worden ondersteund.
Vaardigheid voor meerdere tenants | Vaardigheid met één tenant | Door de gebruiker toegewezen vaardigheden voor beheerde identiteit | |
---|---|---|---|
Consument met meerdere tenants | Ondersteund | Niet ondersteund | Niet ondersteund |
Consument met één tenant | Niet ondersteund | Ondersteund als beide apps deel uitmaken van dezelfde tenant | Ondersteund als beide apps deel uitmaken van dezelfde tenant |
Door de gebruiker toegewezen beheerde identiteitgebruiker | Niet ondersteund | Ondersteund als beide apps deel uitmaken van dezelfde tenant | Ondersteund als beide apps deel uitmaken van dezelfde tenant |
Notitie
De Sdk's voor Bot Framework JavaScript, C# en Python blijven ondersteund, maar de Java SDK wordt buiten gebruik gesteld met definitieve langetermijnondersteuning die eindigt op november 2023.
Bestaande bots die zijn gebouwd met de Java SDK blijven functioneren.
Voor het bouwen van nieuwe bots kunt u Microsoft Copilot Studio gebruiken en lezen over het kiezen van de juiste copilot-oplossing.
Zie De toekomst van botbouw voor meer informatie.
Vereisten
- Kennis van de basisbeginselen en vaardigheden van de bot.
- Een Azure-abonnement (om uw vaardigheid te implementeren). Als u nog geen abonnement hebt, maakt u een gratis account voordat u begint.
- Een kopie van het eenvoudige bot-naar-bot-voorbeeld in C#, JavaScript, Java of Python.
Notitie
Vanaf versie 4.11 hebt u geen app-id en wachtwoord nodig om een vaardigheid lokaal te testen in de Bot Framework Emulator. Er is nog steeds een Azure-abonnement vereist om uw vaardigheid in Azure te implementeren.
Over dit voorbeeld
Het eenvoudige bot-naar-bot-voorbeeld bevat projecten voor twee bots:
- De bot met echovaardigheden, waarmee de vaardigheid wordt geïmplementeerd.
- De eenvoudige hoofdbot, waarmee een hoofdbot wordt geïmplementeerd die de vaardigheid verbruikt.
Dit artikel is gericht op de vaardigheid, die ondersteuningslogica bevat in de bot en adapter.
Zie voor informatie over de eenvoudige hoofdbot hoe u een vaardigheidsconsumer implementeert.
Resources
Voor geïmplementeerde bots is verificatie van bot-naar-bot vereist dat elke deelnemende bot geldige identiteitsgegevens heeft. U kunt echter gebruikers met meerdere tenants lokaal testen met de emulator zonder app-id en wachtwoord.
Registreer de vaardigheid bij Azure om de vaardigheid beschikbaar te maken voor gebruikersgerichte bots. Zie voor meer informatie hoe u een bot registreert bij Azure AI Bot Service.
Toepassingsconfiguratie
Voeg eventueel de identiteitsgegevens van de vaardigheid toe aan het configuratiebestand. Als de gebruiker van de vaardigheid of vaardigheid identiteitsinformatie verstrekt, moeten beide informatie bevatten.
De matrix met toegestane bellers kan beperken welke vaardigheidsgebruikers toegang hebben tot de vaardigheid. Voeg een *-element toe om aanroepen van elke vaardigheidsconsumer te accepteren.
Notitie
Als u uw vaardigheid lokaal test zonder botidentiteitsgegevens, voert noch de vaardigheid noch de gebruiker van de vaardigheid de code uit om claimvalidatie uit te voeren.
EchoSkillBot\appsettings.json
Voeg desgewenst de identiteitsgegevens van de vaardigheid toe aan het appsettings.json-bestand.
{
"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": [ "*" ]
}
Logica voor activiteitshandler
Invoerparameters accepteren
De gebruiker van de vaardigheid kan informatie naar de vaardigheid verzenden. Een manier om dergelijke informatie te accepteren, is door deze te accepteren via de waarde-eigenschap voor binnenkomende berichten. Een andere manier is om gebeurtenissen te verwerken en activiteiten aan te roepen.
De vaardigheid in dit voorbeeld accepteert geen invoerparameters.
Een gesprek voortzetten of voltooien
Wanneer de vaardigheid een activiteit verzendt, moet de gebruiker van de vaardigheid de activiteit doorsturen naar de gebruiker.
U moet echter een endOfConversation
activiteit verzenden wanneer de vaardigheid is voltooid. Anders blijft de gebruiker van de vaardigheid gebruikersactiviteiten doorsturen naar de vaardigheid.
U kunt eventueel de waarde-eigenschap van de activiteit gebruiken om een retourwaarde op te nemen en de code-eigenschap van de activiteit gebruiken om aan te geven waarom de vaardigheid eindigt.
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);
}
}
De vaardigheid annuleren
Voor vaardigheden met meerdere paden accepteert endOfConversation
u ook activiteiten van een vaardigheidsconsumer, zodat de consument het huidige gesprek kan annuleren.
De logica voor deze vaardigheid verandert niet van turn-to-turn. Als u een vaardigheid implementeert die gespreksresources toewijst, voegt u code voor het opschonen van resources toe aan de handler voor het einde van het gesprek.
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;
}
Claimvalidatie
In dit voorbeeld wordt een lijst met toegestane bellers gebruikt voor claimvalidatie. Het configuratiebestand van de vaardigheid definieert de lijst. Het validatieobject leest vervolgens de lijst.
U moet een claimvalidator toevoegen aan de verificatieconfiguratie. De claims worden geëvalueerd na de verificatieheader. Uw validatiecode moet een fout of uitzondering genereren om de aanvraag te weigeren. Er zijn veel redenen waarom u een anderszins geverifieerde aanvraag wilt weigeren. Voorbeeld:
- De vaardigheid maakt deel uit van een betaalde service. De gebruiker mag geen toegang hebben tot de database.
- De vaardigheid is eigendom. Alleen bepaalde vaardigheidsconsumenten kunnen de vaardigheid aanroepen.
Belangrijk
Als u geen claimvalidator opgeeft, genereert uw bot een fout of uitzondering bij het ontvangen van een activiteit van de vaardigheidsconsumer.
De SDK biedt een AllowedCallersClaimsValidator
klasse waarmee autorisatie op toepassingsniveau wordt toegevoegd op basis van een eenvoudige lijst met id's van de toepassingen die de vaardigheid mogen aanroepen. Als de lijst een sterretje (*) bevat, zijn alle bellers toegestaan. De claimvalidator is geconfigureerd in Startup.cs.
Vaardigheidsadapter
Wanneer er een fout optreedt, moet de adapter van de vaardigheid de gespreksstatus voor de vaardigheid wissen en moet deze ook een endOfConversation
activiteit naar de gebruiker van de vaardigheid verzenden. Gebruik de code-eigenschap van de activiteit om aan te geven dat de vaardigheid is beëindigd vanwege een fout.
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}");
}
}
Serviceregistratie
De Bot Framework-adapter maakt gebruik van een verificatieconfiguratieobject (ingesteld wanneer de adapter wordt gemaakt) om de verificatieheader voor binnenkomende aanvragen te valideren.
In dit voorbeeld wordt claimsvalidatie toegevoegd aan de verificatieconfiguratie en wordt de vaardigheidsadapter gebruikt met de fouthandler die in de vorige sectie is beschreven.
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>();
Vaardigheidsmanifest
Een vaardigheidsmanifest is een JSON-bestand dat de activiteiten beschrijft die de vaardigheid kan uitvoeren, de invoer- en uitvoerparameters en de eindpunten van de vaardigheid. Het manifest bevat de informatie die u nodig hebt om toegang te krijgen tot de vaardigheid van een andere bot. De nieuwste schemaversie is 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"
}
]
}
Het manifestschema voor vaardigheden is een JSON-bestand dat het schema van het vaardigheidsmanifest beschrijft. De huidige schemaversie is 2.1.0.
De vaardigheid testen
Op dit moment kunt u de vaardigheid in de emulator testen alsof het een normale bot is. Als u het echter als vaardigheid wilt testen, moet u een vaardigheidsconsumer implementeren.
De nieuwste Bot Framework Emulator downloaden en installeren
- Voer de bot voor echovaardigheden lokaal uit op uw computer. Als u instructies nodig hebt, raadpleegt u het bestand voor het
README
C#-, JavaScript-, Java- of Python-voorbeeld. - Gebruik de emulator om de bot te testen. Wanneer u een 'end' of 'stop'-bericht naar de vaardigheid verzendt, wordt er een
endOfConversation
activiteit verzonden naast het antwoordbericht. De vaardigheid verzendt deendOfConversation
activiteit om aan te geven dat de vaardigheid is voltooid.
Meer informatie over foutopsporing
Omdat verkeer tussen vaardigheden en vaardigheidsgebruikers wordt geverifieerd, zijn er extra stappen bij het opsporen van fouten in dergelijke bots.
- De vaardigheidsconsumer en alle vaardigheden die het verbruikt, moeten direct of indirect worden uitgevoerd.
- Als de bots lokaal worden uitgevoerd en als een van de bots een app-id en wachtwoord heeft, moeten alle bots geldige id's en wachtwoorden hebben.
- Als de bots allemaal zijn geïmplementeerd, raadpleegt u hoe u fouten in een bot kunt opsporen vanuit een kanaal met behulp van devtunnel.
- Als sommige van de bots lokaal worden uitgevoerd en sommige worden geïmplementeerd, raadpleegt u hoe u fouten kunt opsporen in een vaardigheid of vaardigheidsgebruiker.
Anders kunt u fouten opsporen in een vaardigheidsconsumer of vaardigheid, net zoals bij het opsporen van fouten in andere bots. Zie Fouten opsporen in een bot en fouten opsporen met de Bot Framework Emulator voor meer informatie.