Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
AgentApplication является центральным шаблоном агента, построенного с помощью пакета SDK агентов.
AgentApplication является точкой входа для всей входящей активности, включая сообщения от пользователей, события жизненного цикла беседы, взаимодействия с адаптивной карточкой, обратные вызовы OAuth.
Агент по своей сути является AgentApplication. Вы настраиваете его с помощью обработчиков, которые определяют поведение вашего агента. SDK отвечает за маршрутизацию, управление состоянием и инфраструктуру, необходимую для работы агента.
Как работает AgentApplication
У каждого агента есть жизненный цикл, который начинается, когда канал (Microsoft Teams, служба Bot или пользовательский клиент) доставляет активность на конечную точку вашего агента.
AgentApplication находится в центре этого жизненного цикла:
Channel → Hosting layer → AgentApplication → Your handlers
Слои обработки в агенте, созданном с помощью пакета SDK агентов, работают следующим образом:
- Хостинговый слой принимает HTTP-запрос и аутентифицирует его.
-
AgentApplicationобрабатывает входящую активность через свой конвейер. - Ваши обработчики вызываются при совпадении маршрутов.
Ваш агент загружает состояние хода до запуска ваших обработчиков. После этого агент сохраняет состояние текущего хода.
Основные понятия
Действия
В пакете SDK агентов всё обрабатывается в виде действии. Действие — это структурированное сообщение, отражающее произошедшее. У действия есть тип, например: сообщение, событие, вызов, обновление разговора (conversationUpdate) и так далее. Действие содержит полезные данные, соответствующую этому типу.
AgentApplication получает действия и направляет их к соответствующему обработчику.
Маршруты
Маршрут совмещает селектор с обработчиком. Селектор определяет, соответствует ли маршрут текущему действию. Обработчик выполняет вашу логику при соответствии маршрута.
Регистрируйте маршруты при настройке агента. Маршруты могут срабатывать на следующее:
- Сообщение с определенным текстом или соответствующее регулярному выражению
- Любое действие определенного типа
- События жизненного цикла беседы (участник добавлен, участник удален)
- Действия адаптивной карточки
- Настраиваемые условия
При поступлении действия система проверяет маршруты по очереди, пока не найдет соответствие. По умолчанию выполняется только один маршрут.
Состояние этапа
AgentApplication управляет _turn state — структурированным хранилищем, разделенным на области:
| Тип областей | Описание |
|---|---|
| Разговор | Общая для всех пользователей в разговоре, сохраняется между этапами |
| Пользователь | Относится к отдельному пользователю во всех разговорах |
| Временная | Только для текущего этапа — не сохраняется |
Система автоматически загружает состояние до запуска ваших обработчиков и сохраняет его после.
Контекст этапа
Когда обработчик выполняется, он получает контекст этапа. Контекст этапа — это снимок текущего действия, подключения адаптера и утилит для отправки ответов. Контекст этапа — это ваш интерфейс для текущего взаимодействия.
ПО промежуточного слоя
AgentApplication поддерживает конвейер ПО промежуточного слоя. ПО промежуточного слоя — это цепочка компонентов, обрабатывающих каждое взаимодействие до и после выполнения ваших обработчиков. ПО промежуточного слоя может анализировать, преобразовывать или прерывать поток действий. Распространенные применения включают логирование, проверку аутентификации и нормализацию запросов.
Создание агента
Создайте подкласс AgentApplication и зарегистрируйте обработчики в конструкторе. Хостинговый фреймворк автоматически внедряет AgentApplicationOptions.
public class MyAgent : AgentApplication
{
public MyAgent(AgentApplicationOptions options) : base(options)
{
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, WelcomeAsync);
OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
}
private async Task WelcomeAsync(ITurnContext context, ITurnState state, CancellationToken ct)
{
foreach (var member in context.Activity.MembersAdded)
{
if (member.Id != context.Activity.Recipient.Id)
{
await context.SendActivityAsync("Hello! How can I help you?", cancellationToken: ct);
}
}
}
private async Task OnMessageAsync(ITurnContext context, ITurnState state, CancellationToken ct)
{
await context.SendActivityAsync($"You said: {context.Activity.Text}", cancellationToken: ct);
}
}
Зарегистрируйте своего агента в Program.cs:
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IStorage, MemoryStorage>();
builder.Services.AddAgent<MyAgent>();
builder.Services.AddAgentAspNetAuthentication(builder.Configuration);
WebApplication app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapAgentApplicationEndpoints(requireAuth: !app.Environment.IsDevelopment());
app.Run();
Зарегистрируйте обработчики действий
Обработка сообщений
Сопоставьте сообщения по точному тексту (без учета регистра):
OnMessage("help", async (context, state, ct) =>
{
await context.SendActivityAsync("Here's what I can do...", cancellationToken: ct);
});
Сопоставление сообщений с помощью регулярного выражения:
OnMessage(new Regex(@"^order\s+\d+$", RegexOptions.IgnoreCase), async (context, state, ct) =>
{
await context.SendActivityAsync("Looking up your order...", cancellationToken: ct);
});
Обработка обновлений беседы
Регистрируйте обработчики для событий жизненного цикла беседы, таких как присоединение участников или их выход.
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, async (context, state, ct) =>
{
foreach (var member in context.Activity.MembersAdded)
{
if (member.Id != context.Activity.Recipient.Id)
{
await context.SendActivityAsync("Welcome!", cancellationToken: ct);
}
}
});
OnConversationUpdate(ConversationUpdateEvents.MembersRemoved, async (context, state, ct) =>
{
// Called when participants leave the conversation
});
Обработка действий любого типа
Сопоставление любых действий по строке типа для полного контроля маршрутизации.
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Handles all message activities
});
OnActivity(ActivityTypes.Event, async (context, state, ct) =>
{
// Handles event activities
});
Используйте константы ActivityTypes вместо строк, прописанных в коде.
Контроль порядка оценки маршрутов
Маршруты сортируются в фиксированный порядок оценки при их регистрации, а не во время выполнения. Сортировка включает два уровня:
Тип маршрута: система группирует маршруты по типу и всегда сначала оценивает маршруты более высокого приоритета, чем маршруты низкого приоритета, независимо от ранга:
Приоритет Тип маршрута 1 (самый высокий) Маршруты вызовов на основе агентов 2 Маршруты вызовов (действия адаптивных карточек, обратные вызовы OAuth и другие вызовы, чувствительные ко времени) 3 Маршруты на основе агентов 4 (самый низкий) Все остальные маршруты Ранг: внутри каждой группы типов маршрутов система упорядочивает маршруты по их значению ранга. Маршруты с наименьшими значениями ранга обрабатываются первыми.
Используйте константы RouteRank для назначения ранга при регистрации обработчика:
| Константа | Значение | Значение |
|---|---|---|
RouteRank.First |
0 |
Оценивается перед всеми остальными маршрутами в своей группе |
RouteRank.Unspecified |
32767 |
Используется по умолчанию, если ранг не указан |
RouteRank.Last |
65535 |
Оценивается после всех остальных маршрутов своей группы |
По умолчанию обработка останавливается на первом совпадающем маршруте. Используйте RouteRank.Last для универсального маршрута, который обрабатывает всё, что не охвачено более конкретными маршрутами.
// Specific handlers use the default rank
OnMessage("status", HandleStatusAsync);
OnMessage("help", HandleHelpAsync);
// Catch-all — handles anything not matched above
OnActivity(ActivityTypes.Message, HandleUnknownMessageAsync, rank: RouteRank.Last);
Перехватчики жизненного цикла этапа
Регистрируйте логику, которая выполняется на каждом ходе, перед или после сопоставления маршрутов. Эти перехватчики полезны для ведения журналов, сквозных задач и обработки ошибок.
OnBeforeTurn(async (context, state, ct) =>
{
logger.LogInformation("Turn started: {Type}", context.Activity.Type);
return true; // Return false to abort the turn
});
OnAfterTurn(async (context, state, ct) =>
{
logger.LogInformation("Turn completed");
return true; // Return false to skip state saving
});
OnTurnError(async (context, state, exception, ct) =>
{
logger.LogError(exception, "Turn error");
await context.SendActivityAsync("Something went wrong. Please try again.", cancellationToken: ct);
});
Когда OnBeforeTurn возвращает false, выполнение этапа прерывается, и ни один маршрут не запускается. Когда OnAfterTurn возвращает false, состояние этапа не сохраняется.
Использование состояния этапа
Агент автоматически загружает состояние этапа перед выполнением ваших обработчиков и сохраняет его после. Объект состояния этапа, передаваемый вашим обработчикам, предоставляет доступ к различным областям состояния, чтобы вы могли читать и записывать данные, которые сохраняются между этапами или существуют только на текущем этапе:
- Область разговора: для данных, общих для всех этапов разговора
- Область пользователя: для данных на каждого пользователя
- Временная область: для данных, которые должны существовать только на текущем этапе
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Conversation scope — persisted per conversation
var count = state.Conversation.GetValue<int>("messageCount", () => 0);
state.Conversation.SetValue("messageCount", count + 1);
// User scope — persisted per user
var name = state.User.GetValue<string>("displayName");
// Temp scope — current turn only
state.Temp.SetValue("parsedInput", context.Activity.Text?.Trim());
await context.SendActivityAsync($"Message #{count + 1}: {context.Activity.Text}", cancellationToken: ct);
});
Примечание
Используйте MemoryStorage для локальной разработки и тестирования. Для развертываний в рабочей среде, особенно при работе на нескольких экземплярах, используйте поставщик постоянного хранилища, например Azure Cosmos DB или хранилище BLOB-объектов Azure. См. статью Использование поставщиков хранилища в агенте.