Şunlar için geçerlidir: SDK v4
Becerileri kullanarak başka bir botu genişletebilirsiniz.
Beceri, başka bir bot için bir dizi görev gerçekleştirebilen bir botdur.
- Bildirim, becerinin arabirimini açıklar. Becerinin kaynak koduna erişimi olmayan geliştiriciler, beceri tüketicilerini tasarlamak için bildirimdeki bilgileri kullanabilir.
- Bir beceri, hangi botların veya kullanıcıların erişebileceğini yönetmek için talep doğrulamasını kullanabilir.
Bu makale, kullanıcının girişini yankılayan bir becerinin nasıl uygulandığını gösterir.
Bazı beceri tüketicileri, bazı beceri botu türlerini kullanamaz.
Aşağıdaki tabloda hangi birleşimlerin desteklendiği açıklanmaktadır.
| |
Çoklu kiracılı yetenek |
Tek kiracılı beceri |
Kullanıcı tarafından atanan yönetilen kimlik becerisi |
|
Çok kiracılı tüketici |
Desteklenir |
Desteklenmez |
Desteklenmez |
|
Tek kiracılı tüketici |
Desteklenmez |
Her iki uygulama da aynı kiracıya aitse desteklenir |
Her iki uygulama da aynı kiracıya aitse desteklenir |
|
Kullanıcı tarafından atanan yönetilen kimlik kullanıcısı |
Desteklenmez |
Her iki uygulama da aynı kiracıya aitse desteklenir |
Her iki uygulama da aynı kiracıya aitse desteklenir |
Önemli
Bot Framework SDK'sı ve Bot Framework Öykünücüsü GitHub'da arşivlenmiştir. Proje artık güncelleştirilmedi veya bakım yapılmadı. Bot Framework SDK'sı için destek biletleri artık 31 Aralık 2025 itibarıyla hizmet verilmeyecektir.
Yapay zeka hizmetleri, düzenleme ve bilgi seçiminizle aracılar oluşturmak için Microsoft 365 Aracıları SDK'sını kullanmayı göz önünde bulundurun. Aracılar SDK'sı C#, JavaScript veya Python için dil desteğine sahiptir. SDK hakkında daha fazla bilgiyi aka.ms/agents adresinde bulabilirsiniz.
Bot Framework SDK'sı ile oluşturulmuş mevcut bir botunuz varsa botunuzu Aracılar SDK'sına güncelleştirebilirsiniz.
Bot Framework SDK'sını Aracılar SDK'sına geçirme kılavuzundaki temel değişiklikleri ve güncelleştirmeleri gözden geçirin.
Microsoft Teams içinde çalışmak üzere tasarlanmış bir işbirliği aracısı oluşturuyorsanız Teams SDK'sını kullanmayı göz önünde bulundurun. Teams ortamında çalışan aracılar için Teams'e özgü API'ler, uyarlamalı kart desteği ve yerleşik yapay zeka düzenlemesi sağlar.
Teams SDK'sı (Teams AI Kitaplığı) adresinden daha fazla bilgi edinebilirsiniz.
SaaS tabanlı bir aracı platformu arıyorsanız Microsoft Copilot Studio'yu göz önünde bulundurun.
Önkoşullar
Not
Sürüm 4.11'den başlayarak, Bot Framework Öykünücüsü'nde bir beceriyi yerel olarak test etmek için bir uygulama kimliğine ve parolaya ihtiyacınız yoktur. Becerinizi Azure'a dağıtmak için yine de bir Azure aboneliği gereklidir.
Bu örnek hakkında
Botlar Arası Beceriler basit örneği, iki bot için projeleri içerir:
- Beceriyi gerçekleştiren yankı beceri botu.
-
Beceriyi kullanan bir kök botu uygulayan basit kök bot.
Bu makale, bot ve bağdaştırıcısında yer alan destekleyici mantığı içeren beceriye odaklanır.
Basit kök bot hakkında bilgi için Beceri tüketicisi uygulamasını nasıl gerçekleştireceğinizi inceleyin.
Kaynaklar
Dağıtılan botlar için bot-bot kimlik doğrulaması, katılan her bot için geçerli kimlik bilgilerine sahip olmasını gerektirir.
Ancak, çok kullanıcılı yetenekleri ve yetenek tüketicilerini uygulama kimliği ve parolası olmadan Emülatör ile yerel olarak test edebilirsiniz.
Beceriyi kullanıcıya yönelik botların kullanımına açmak için beceriyi Azure'a kaydedin. Daha fazla bilgi için bkz. Azure AI Bot Hizmeti ile bot kaydetme.
Uygulama yapılandırması
İsteğe bağlı olarak, becerinin kimlik bilgilerini yapılandırma dosyasına ekleyin. Eğer beceri veya beceri tüketicisi kimlik bilgileri sağlıyorsa, her ikisi de sağlamak zorundadır.
İzin verilen arayanlar dizisi, hangi beceri tüketicilerinin beceriye erişebileceğini kısıtlamak için kullanılabilir.
Herhangi bir beceri tüketicisinden gelen çağrıları kabul etmek için bir "*" öğesi ekleyin.
Not
Becerinizi bot kimlik bilgileri olmadan yerel olarak test ediyorsanız, ne beceri ne de beceri tüketicisi talep doğrulama gerçekleştirmek için kodu çalıştırmaz.
EchoSkillBot\appsettings.jsaçık
İsteğe bağlı olarak, becerinin kimlik bilgilerini appsettings.json dosyasına ekleyin.
{
"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": [ "*" ]
}
echo-skill-bot/.env
İsteğe bağlı olarak, becerinin kimlik bilgilerini .env dosyasına ekleyin.
MicrosoftAppType=
MicrosoftAppId=
MicrosoftAppPassword=
MicrosoftAppTenantId=
AllowedCallers=*
DialogSkillBot\resources\application.properties
İsteğe bağlı olarak, becerinin uygulama kimliğini ve parolasını application.properties dosyasına ekleyin.
MicrosoftAppId=
MicrosoftAppPassword=
server.port=39783
# 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=*
İsteğe bağlı olarak, becerinin uygulama kimliğini ve parolasını config.py dosyasına ekleyin.
config.py
APP_ID = os.environ.get("MicrosoftAppId", "")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "")
APP_TYPE = os.environ.get("MicrosoftAppType", "MultiTenant")
APP_TENANTID = os.environ.get("MicrosoftAppTenantId", "")
# Callers to only those specified, '*' allows any caller.
Etkinlik işleyici mantığı
Beceri tüketicisi beceriye bilgi gönderebilir. Bu tür bilgileri kabul etmenin bir yolu, gelen iletilerde value özelliği aracılığıyla bunları kabul etmektir. Başka bir yol da olayları işlemek ve etkinlikleri çağırmaktır.
Bu örnekteki beceri giriş parametrelerini kabul etmiyor.
Konuşmaya devam etmek veya tamamlamak için
Beceri bir etkinlik gönderdiğinde, beceri tüketicisi etkinliği kullanıcıya iletmelidir.
Ancak beceri tamamlandığında bir endOfConversation etkinlik göndermeniz gerekir; aksi takdirde, beceri tüketicisi kullanıcı etkinliklerini beceriye iletmeye devam eder.
İsteğe bağlı olarak, bir dönüş değeri eklemek için etkinliğin value özelliğini kullanın ve becerinin neden sona erdiğini belirtmek için etkinliğin kod özelliğini kullanın.
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);
}
}
echo-skill-bot/bot.js
super();
// See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types.
this.onMessage(async (context, next) => {
switch (context.activity.text.toLowerCase()) {
case 'end':
case 'stop':
await context.sendActivity({
type: ActivityTypes.EndOfConversation,
code: EndOfConversationCodes.CompletedSuccessfully
});
break;
default:
await context.sendActivity(`Echo (JS) : '${ context.activity.text }'`);
await context.sendActivity('Say "end" or "stop" and I\'ll end the conversation and back to the parent.');
}
// By calling next() you ensure that the next BotHandler is run.
echoSkillBot\EchoBot.java
protected CompletableFuture<Void> onMessageActivity(TurnContext turnContext) {
if (
turnContext.getActivity().getText().contains("end") || turnContext.getActivity().getText().contains("stop")
) {
String messageText = "ending conversation from the skill...";
return turnContext.sendActivity(MessageFactory.text(messageText, messageText, InputHints.IGNORING_INPUT))
.thenApply(result -> {
Activity endOfConversation = Activity.createEndOfConversationActivity();
endOfConversation.setCode(EndOfConversationCodes.COMPLETED_SUCCESSFULLY);
return turnContext.sendActivity(endOfConversation);
})
.thenApply(finalResult -> null);
} else {
String messageText = String.format("Echo: %s", turnContext.getActivity().getText());
return turnContext.sendActivity(MessageFactory.text(messageText, messageText, InputHints.IGNORING_INPUT))
.thenApply(result -> {
String nextMessageText =
"Say \"end\" or \"stop\" and I'll end the conversation and back to the parent.";
return turnContext.sendActivity(
MessageFactory.text(nextMessageText, nextMessageText, InputHints.EXPECTING_INPUT)
);
})
.thenApply(result -> null);
}
}
echo-skill-bot/bots/echo_bot.py
async def on_message_activity(self, turn_context: TurnContext):
if "end" in turn_context.activity.text or "stop" in turn_context.activity.text:
# Send End of conversation at the end.
await turn_context.send_activity(
MessageFactory.text("Ending conversation from the skill...")
)
end_of_conversation = Activity(type=ActivityTypes.end_of_conversation)
end_of_conversation.code = EndOfConversationCodes.completed_successfully
await turn_context.send_activity(end_of_conversation)
else:
await turn_context.send_activity(
MessageFactory.text(f"Echo (python): {turn_context.activity.text}")
)
await turn_context.send_activity(
MessageFactory.text(
f'Say "end" or "stop" and I\'ll end the conversation and back to the parent.'
)
)
Beceriyi iptal etmek için
Çok aşamalı beceriler için, bir beceri tüketicisinden gelen etkinlikleri de kabul endOfConversation eder ve tüketicinin geçerli konuşmayı iptal etmesine izin verirsiniz.
Bu becerinin mantığı turdan tura değişmez. Konuşma kaynaklarını ayıran bir beceri uygularsanız, konuşma sonu işleyicisine kaynak temizleme kodu ekleyin.
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;
}
echo-skill-bot/bot.js
Konuşma sonu mantığı eklemek için onUnrecognizedActivityType yöntemini kullanın. İşleyicide tanınmayan etkinliğin type eşit endOfConversationolup olmadığını denetleyin.
});
this.onEndOfConversation(async (context, next) => {
// 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.
// By calling next() you ensure that the next BotHandler is run.
echoSkillBot\EchoBot.java
protected CompletableFuture<Void> onEndOfConversationActivity(TurnContext turnContext) {
// 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 CompletableFuture.completedFuture(null);
}
echo-skill-bot/bots/echo_bot.py
async def on_end_of_conversation_activity(self, turn_context: TurnContext):
# 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.
pass
Talep doğrulayıcı
Bu örnek, talep doğrulaması için izin verilen arayanlar listesini kullanır. Becerinin yapılandırma dosyası listeyi tanımlar. Doğrulayıcı nesnesi listeyi okur.
Kimlik doğrulama yapılandırmasına bir talep doğrulayıcı eklemeniz gerekir. Talepler kimlik doğrulama üst bilgisinden sonra değerlendirilir. Doğrulama kodunuz isteği reddetmek için bir hata veya özel durum oluşturmalıdır. Aksi takdirde kimliği doğrulanmış bir isteği reddetmek istemeniz için birçok neden vardır. Örneğin:
- Beceri, ücretli hizmetin bir parçasıdır. Veritabanında olmayan kullanıcıların erişimi olmamalıdır.
- Beceri özeldir. Beceriyi yalnızca belirli beceri kullanıcıları çağırabilir.
Önemli
Talep doğrulayıcı sağlamazsanız botunuz beceri tüketicisinden etkinlik aldıktan sonra bir hata veya özel durum oluşturur.
SDK, beceriyi çağırmasına AllowedCallersClaimsValidator izin verilen uygulamaların basit bir kimlik listesine dayalı olarak uygulama düzeyinde yetkilendirme ekleyen bir sınıf sağlar. Listede yıldız işareti (*) varsa, tüm arayanlara izin verilir. Talep doğrulayıcı, Startup.cs dosyasında yapılandırılır.
SDK, beceriyi çağırmasına allowedCallersClaimsValidator izin verilen uygulamaların basit bir kimlik listesine dayalı olarak uygulama düzeyinde yetkilendirme ekleyen bir sınıf sağlar. Listede yıldız işareti (*) varsa, tüm arayanlara izin verilir. Talep doğrulayıcı index.js'de yapılandırılır.
SDK, beceriyi çağırmasına AllowedCallersClaimsValidator izin verilen uygulamaların basit bir kimlik listesine dayalı olarak uygulama düzeyinde yetkilendirme ekleyen bir sınıf sağlar. Listede yıldız işareti (*) varsa, tüm arayanlara izin verilir. Talep doğrulayıcı, Application.java içinde yapılandırılır.
Gelen isteği reddetmek için hata oluşturan bir talep doğrulama yöntemi tanımlayın.
echo-skill-bot/authentication/allowed_callers_claims_validator.py
class AllowedCallersClaimsValidator:
config_key = "ALLOWED_CALLERS"
def __init__(self, config: DefaultConfig):
if not config:
raise TypeError(
"AllowedCallersClaimsValidator: config object cannot be None."
)
# ALLOWED_CALLERS is the setting in config.py file
# that consists of the list of parent bot ids that are allowed to access the skill
# to add a new parent bot simply go to the AllowedCallers and add
# the parent bot's microsoft app id to the list
caller_list = getattr(config, self.config_key)
if caller_list is None:
raise TypeError(f'"{self.config_key}" not found in configuration.')
self._allowed_callers = frozenset(caller_list)
@property
def claims_validator(self) -> Callable[[List[Dict]], Awaitable]:
async def allow_callers_claims_validator(claims: Dict[str, object]):
# if allowed_callers is None we allow all calls
if "*" not in self._allowed_callers and SkillValidation.is_skill_claim(
claims
):
# Check that the appId claim in the skill request is in the list of skills configured for this bot.
app_id = JwtTokenValidation.get_app_id_from_claims(claims)
if app_id not in self._allowed_callers:
raise PermissionError(
f'Received a request from a bot with an app ID of "{app_id}".'
f" To enable requests from this caller, add the app ID to your configuration file."
)
return
return allow_callers_claims_validator
Beceri uyarlayıcısı
Bir hata oluştuğunda, becerinin adaptörü, becerinin konuşma durumunu temizlemeli ve ardından beceri tüketicisine bir endOfConversation aktivitesi göndermelidir. Becerinin bir hata nedeniyle sona erdiğinin sinyalini vermek için etkinliğin kod özelliğini kullanın.
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}");
}
}
echo-skill-bot/index.js
const adapter = new CloudAdapter(botFrameworkAuthentication);
// Catch-all for errors.
adapter.onTurnError = async (context, error) => {
// This check writes out errors to the console log, instead of to app insights.
// NOTE: In a production environment, you should consider logging this to Azure
// application insights.
console.error(`\n [onTurnError] unhandled error: ${ error }`);
await sendErrorMessage(context, error);
await sendEoCToParent(context, error);
};
async function sendErrorMessage(context, error) {
try {
// Send a message to the user.
let onTurnErrorMessage = 'The skill encountered an error or bug.';
await context.sendActivity(onTurnErrorMessage, onTurnErrorMessage, InputHints.ExpectingInput);
onTurnErrorMessage = 'To continue to run this bot, please fix the bot source code.';
await context.sendActivity(onTurnErrorMessage, onTurnErrorMessage, InputHints.ExpectingInput);
// 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 context.sendTraceActivity('OnTurnError Trace', error.toString(), 'https://www.botframework.com/schemas/error', 'TurnError');
} catch (err) {
console.error(`\n [onTurnError] Exception caught in sendErrorMessage: ${ err }`);
}
}
async function sendEoCToParent(context, error) {
try {
// Send an EndOfConversation activity to the skill caller with the error to end the conversation,
// and let the caller decide what to do.
const endOfConversation = {
type: ActivityTypes.EndOfConversation,
code: 'SkillError',
text: error.toString()
};
await context.sendActivity(endOfConversation);
} catch (err) {
console.error(`\n [onTurnError] Exception caught in sendEoCToParent: ${ err }`);
echoSkillBot\SkillAdapterWithErrorHandler.java
public SkillAdapterWithErrorHandler(
Configuration configuration,
AuthenticationConfiguration authenticationConfiguration
) {
super(configuration, authenticationConfiguration);
setOnTurnError(new SkillAdapterErrorHandler());
}
private class SkillAdapterErrorHandler implements OnTurnErrorHandler {
@Override
public CompletableFuture<Void> invoke(TurnContext turnContext, Throwable exception) {
return sendErrorMessage(turnContext, exception).thenAccept(result -> {
sendEoCToParent(turnContext, exception);
});
}
private CompletableFuture<Void> sendErrorMessage(TurnContext turnContext, Throwable exception) {
try {
// Send a message to the user.
String errorMessageText = "The skill encountered an error or bug.";
Activity errorMessage =
MessageFactory.text(errorMessageText, errorMessageText, InputHints.IGNORING_INPUT);
return turnContext.sendActivity(errorMessage).thenAccept(result -> {
String secondLineMessageText = "To continue to run this bot, please fix the bot source code.";
Activity secondErrorMessage =
MessageFactory.text(secondLineMessageText, secondLineMessageText, InputHints.EXPECTING_INPUT);
turnContext.sendActivity(secondErrorMessage)
.thenApply(
sendResult -> {
// 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.
return TurnContext.traceActivity(
turnContext,
String.format("OnTurnError Trace %s", exception.toString())
);
}
);
});
} catch (Exception ex) {
return Async.completeExceptionally(ex);
}
}
private CompletableFuture<Void> sendEoCToParent(TurnContext turnContext, Throwable 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.
Activity endOfConversation = Activity.createEndOfConversationActivity();
endOfConversation.setCode(EndOfConversationCodes.SKILL_ERROR);
endOfConversation.setText(exception.getMessage());
return turnContext.sendActivity(endOfConversation).thenApply(result -> null);
} catch (Exception ex) {
return Async.completeExceptionally(ex);
}
}
}
echo-skill-bot/adapter_with_error_handler.py
# This check writes out errors to console log
# NOTE: In production environment, you should consider logging this to Azure
# application insights.
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
traceback.print_exc()
await self._send_error_message(turn_context, error)
await self._send_eoc_to_parent(turn_context, error)
async def _send_error_message(self, turn_context: TurnContext, error: Exception):
try:
# Send a message to the user.
error_message_text = "The skill encountered an error or bug."
error_message = MessageFactory.text(
error_message_text, error_message_text, InputHints.ignoring_input
)
await turn_context.send_activity(error_message)
error_message_text = (
"To continue to run this bot, please fix the bot source code."
)
error_message = MessageFactory.text(
error_message_text, error_message_text, InputHints.ignoring_input
)
await turn_context.send_activity(error_message)
# Send a trace activity, which will be displayed in Bot Framework Emulator.
await turn_context.send_trace_activity(
label="TurnError",
name="on_turn_error Trace",
value=f"{error}",
value_type="https://www.botframework.com/schemas/error",
)
except Exception as exception:
print(
f"\n Exception caught on _send_error_message : {exception}",
file=sys.stderr,
)
traceback.print_exc()
async def _send_eoc_to_parent(self, turn_context: TurnContext, error: 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.
end_of_conversation = Activity(type=ActivityTypes.end_of_conversation)
end_of_conversation.code = "SkillError"
end_of_conversation.text = str(error)
await turn_context.send_activity(end_of_conversation)
except Exception as exception:
print(
f"\n Exception caught on _send_eoc_to_parent : {exception}",
file=sys.stderr,
)
traceback.print_exc()
Hizmet kaydı
Bot Framework bağdaştırıcısı, gelen isteklerde kimlik doğrulama üst bilgisini doğrulamak için bir kimlik doğrulama yapılandırma nesnesi (bağdaştırıcı oluşturulduğunda ayarlanır) kullanır.
Bu örnek, kimlik doğrulama yapılandırmasına talep doğrulaması ekler ve beceri bağdaştırıcısını önceki bölümde açıklanan hata işleyicisi ile kullanır.
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>();
echo-skill-bot/index.js
server.get('/manifest/*', restify.plugins.serveStatic({ directory: './manifest', appendRequestPath: false }));
const allowedCallers = (process.env.AllowedCallers || '').split(',').filter((val) => val) || [];
const claimsValidators = allowedCallersClaimsValidator(allowedCallers);
// If the MicrosoftAppTenantId is specified in the environment 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.
let validTokenIssuers = [];
const { MicrosoftAppTenantId } = process.env;
if (MicrosoftAppTenantId) {
// 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 = [
`${ AuthenticationConstants.ValidTokenIssuerUrlTemplateV1 }${ MicrosoftAppTenantId }/`,
`${ AuthenticationConstants.ValidTokenIssuerUrlTemplateV2 }${ MicrosoftAppTenantId }/v2.0/`,
`${ AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV1 }${ MicrosoftAppTenantId }/`,
`${ AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV2 }${ MicrosoftAppTenantId }/v2.0/`
];
}
// Define our authentication configuration.
const authConfig = new AuthenticationConfiguration([], claimsValidators, validTokenIssuers);
const credentialsFactory = new ConfigurationServiceClientCredentialFactory({
MicrosoftAppId: process.env.MicrosoftAppId,
MicrosoftAppPassword: process.env.MicrosoftAppPassword,
MicrosoftAppType: process.env.MicrosoftAppType,
MicrosoftAppTenantId: process.env.MicrosoftAppTenantId
});
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env, credentialsFactory, authConfig);
// Create adapter.
echoSkillBot\Application.java
@Override
public AuthenticationConfiguration getAuthenticationConfiguration(Configuration configuration) {
AuthenticationConfiguration authenticationConfiguration = new AuthenticationConfiguration();
authenticationConfiguration.setClaimsValidator(
new AllowedCallersClaimsValidator(Arrays.asList(configuration.getProperties(configKey)))
);
return authenticationConfiguration;
}
echo-skill-bot/app.py
CLAIMS_VALIDATOR = AllowedCallersClaimsValidator(CONFIG)
AUTH_CONFIG = AuthenticationConfiguration(
claims_validator=CLAIMS_VALIDATOR.claims_validator
)
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = ConfigurationBotFrameworkAuthentication(
CONFIG,
auth_configuration=AUTH_CONFIG,
)
ADAPTER = AdapterWithErrorHandler(SETTINGS)
Beceri bildirimi
Beceri bildirimi, becerinin gerçekleştirebileceği etkinlikleri, giriş ve çıkış parametrelerini ve becerinin uç noktalarını açıklayan bir JSON dosyasıdır.
Bildirim, beceriye başka bir bottan erişmek için ihtiyacınız olan bilgileri içerir.
En son şema sürümü v2.1'dir.
EchoSkillBot\wwwroot\manifest\echoskillbot-manifest-1.0.jsaçık
{
"$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"
}
]
}
echo-skill-bot/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"
}
]
}
DialogSkillBot\webapp\manifest\echoskillbot-manifest-1.0.jsaçık
{
"$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"
}
]
}
echo_skill_bot/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"
}
]
}
Beceri bildirimi şeması , beceri bildiriminin şemasını açıklayan bir JSON dosyasıdır. Geçerli şema sürümü 2.1.0'dır.
Beceriyi test edin
Bu noktada Emulator'daki beceriyi normal bir bot gibi test edebilirsiniz. Ancak, beceri olarak test etmek için bir beceri tüketicisi uygulamanız gerekir.
En son Bot Framework Öykünücüsü'ni indirme ve yükleme
- Yankı beceri botunu yerel olarak makinenizde çalıştırın. Yönergelere ihtiyacınız varsa C#, JavaScript
READMEJava veya Python örneği için dosyaya bakın.
- Botu test etmek için Emülatör'ü kullanın. Beceriye bir "son" veya "durdur" iletisi gönderdiğinizde, yanıt iletisine ek olarak bir
endOfConversation etkinlik gönderir. Beceri, becerinin endOfConversation bittiğini belirtmek için etkinliği gönderir.
Hata ayıklama hakkında daha fazla bilgi
Beceri ve beceri tüketicileri arasındaki trafiğin kimliği doğrulandığından, bu tür botlarda hata ayıklama sırasında ek adımlar vardır.
- Beceri tüketicisi ve doğrudan veya dolaylı olarak tükettiği tüm beceriler çalışır durumda olmalıdır.
- Botlar yerel olarak çalışıyorsa ve botlardan herhangi birinin uygulama kimliği ve parolası varsa, tüm botların geçerli kimlikleri ve parolaları olmalıdır.
- Botların tümü dağıtıldıysa devtunnel kullanarak herhangi bir kanaldan bir botta hata ayıklamayı öğrenin.
- Botlardan bazıları yerel olarak çalışıyorsa ve bazıları dağıtıldıysa, bir beceri veya beceri tüketicisinde nasıl hata ayıklayacağınızı görün.
Aksi halde, diğer botlarda hata ayıklamada olduğu gibi, bir beceri tüketicisinde veya beceride hata ayıklayabilirsiniz. Daha fazla bilgi için Botta Hata Ayıklama ve Bot Framework Öykünücüsü ile Hata Ayıklama konularına bakın.
Sonraki adımlar