AgentApplication v sadě SDK pro agenty Microsoft 365

AgentApplication je ústředním stavebním blokem agenta vytvořeného pomocí Agents SDK. AgentApplication je vstupním bodem pro veškerou příchozí aktivitu, včetně zpráv od uživatelů, událostí životního cyklu konverzace, interakcí s adaptivními kartami a OAuth callbacků.

Agent je ve svém jádru AgentApplication. Konfigurujete ho pomocí obslužných rutin, které popisují, co váš agent dělá. SDK se stará o směrování, správu stavu a infrastrukturu potřebnou k provozu agenta.

Jak AgentApplication funguje

Každý agent má životní cyklus, který začíná tím, že kanál (Microsoft Teams, Bot Service nebo vlastní klient) doručí aktivitu na koncový bod vašeho agenta. AgentApplication je středobodem tohoto životního cyklu:

Channel → Hosting layer → AgentApplication → Your handlers

Vrstvy zpracování u agenta vytvořeného pomocí Agents SDK fungují následovně:

  1. Hostingová vrstva přijímá požadavek HTTP a ověří ho.
  2. AgentApplication zpracovává příchozí aktivitu prostřednictvím svého kanálu.
  3. Vaše obslužné rutiny se volají na základě odpovídajících tras.

Agent načte stav tahu před spuštěním obslužných rutin. Potom agent uloží stav tahu.

Klíčové koncepty

Aktivity

Všechno v Sadě SDK pro agenty funguje jako aktivita. Aktivita je strukturovaná zpráva, která představuje něco, co se stalo. Aktivita má typ, například message, event, invoke, conversationUpdate a podobně. Nese datovou část relevantní pro tento typ. AgentApplication přijímá aktivity a směruje je ke správné obslužné rutině.

Trasy

Trasa spojuje selektor s obslužnou rutinou. Selektor určuje, zda trasa odpovídá aktuální aktivitě. Obslužná rutina spustí logiku, když se trasa shoduje.

Registrujte trasy při konfiguraci agenta. Mohou se shodovat:

  • Zpráva obsahující specifický text nebo odpovídající regulárnímu výrazu
  • Jakákoli aktivita daného typu
  • Události životního cyklu konverzace (přidání člena, odebrání člena)
  • Akce adaptivní karty
  • Vlastní podmínky

Když aktivita dorazí, systém vyhodnocuje trasy v pořadí, dokud nenajde shodu. Ve výchozím nastavení běží pouze jedna trasa.

Stav obratu

AgentApplication spravuje stav tahu – strukturované úložiště rozdělené do oborů:

Typ oblasti Popis
Konverzace Sdílené mezi všemi uživateli v konverzaci, uchované mezi jednotlivými kroky dialogu.
Uživatelská Vázáno na jednotlivého uživatele napříč všemi konverzacemi
Dočasné Pouze aktuální tah – nikdy se neuchovávalo

Systém automaticky načte stav před spuštěním vašich obslužných rutin a po jejich ukončení jej automaticky uloží.

Kontext obratu

Když se obslužná rutina spustí, obdrží kontext tahu. Kontext tahu je snímek aktuální aktivity, připojení adaptéru a nástrojů pro odesílání odpovědí. Kontext tahu je vaše rozhraní pro aktuální interakci.

Middleware

AgentApplication podporuje kanál middlewaru. Middleware je řada komponent, které zpracovávají každou interakci před a po spuštění vašich obslužných rutin. Middleware může kontrolovat, transformovat nebo zkrátit tok aktivit. Mezi běžné způsoby využití patří protokolování, ověřování a normalizace požadavků.

Vytvořit agenta

Vytvořte podtřídu AgentApplication a zaregistrujte obslužné rutiny v konstruktoru. Hostitelský framework automaticky injektuje 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);
    }
}

Zaregistrujte svého agenta v 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();

Registrujte obslužné rutiny aktivit

Zpracování zpráv

Porovnávejte zprávy podle přesného textu (nerozlišuje se velká a malá písmena):

OnMessage("help", async (context, state, ct) =>
{
    await context.SendActivityAsync("Here's what I can do...", cancellationToken: ct);
});

Párujte zprávy pomocí regulárního výrazu:

OnMessage(new Regex(@"^order\s+\d+$", RegexOptions.IgnoreCase), async (context, state, ct) =>
{
    await context.SendActivityAsync("Looking up your order...", cancellationToken: ct);
});

Zpracování aktualizací konverzací

Registrujte obslužné rutiny pro události životního cyklu konverzace, jako je připojení nebo odchod členů.

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

Zpracujte jakýkoli typ aktivity

Porovná jakoukoli aktivitu podle řetězce typu pro úplnou kontrolu nad směrováním.

OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
    // Handles all message activities
});

OnActivity(ActivityTypes.Event, async (context, state, ct) =>
{
    // Handles event activities
});

Používejte konstanty ActivityTypes místo pevně zakódovaných řetězců.

Řízení pořadí vyhodnocování tras

Systém seřadí trasy do pevného pořadí vyhodnocení již při jejich registraci, nikoli až za běhu. Třídění používá dvě úrovně:

  1. Typ trasy: Systém seskupuje trasy podle typu a vždy vyhodnocuje typy s vyšší prioritou před typy s nižší prioritou, bez ohledu na hodnocení:

    Priorita Typ trasy
    1 (nejvyšší) Trasy volání agentů
    2 Volání tras (akce adaptivní karty, zpětné volání OAuth a jiná volání citlivá na čas)
    3 Agentní trasy
    4 (nejnižší) Všechny trasy
  2. Pořadí: V rámci každé skupiny typů tras systém řadí trasy podle jejich hodnoty pořadí. Trasy s nižší číselnou hodnotou pořadí jsou vyhodnoceny jako první.

Při registraci obslužné rutiny použijte konstanty RouteRank k nastavení pořadí:

Konstanta Hodnota Význam
RouteRank.First 0 Vyhodnoceno před všemi ostatními trasami ve skupině
RouteRank.Unspecified 32767 Výchozí hodnota, pokud není pořadí specifikováno
RouteRank.Last 65535 Vyhodnoceno po všech ostatních trasách ve skupině

Ve výchozím nastavení se hodnocení zastaví na první shodné trase. Použijte RouteRank.Last pro univerzální záložní řešení, které zpracuje cokoli, co neodpovídá specifičtější trase.

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

Háčky životního cyklu tahu

Registrujte kód, který se spouští při každém kroku, před nebo po vyhodnocení trasy. Tyto háčky jsou užitečné pro protokolování, průřezové zájmy a zpracování chyb.

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

Když OnBeforeTurn vrátí false, tah se přeruší a nespustí se žádné trasy. Pokud OnAfterTurn vrátí false, stav tahu se neuloží.

Použít stav tahu

Agent automaticky načte stav tahu před spuštěním vašich obslužných rutin a po jejich ukončení jej uloží. Objekt stavu tahu, který se předává vašim obslužným rutinám, vám umožňuje přístup k různým oblastem, takže můžete číst a zapisovat data, která přetrvávají i mezi tahy, nebo která jsou dočasná a platí pouze pro aktuální tah:

  • Rozsah konverzace: Pro data sdílená ve všech krocích konverzace
  • Uživatelský rozsah: Pro data na uživatele
  • Dočasný rozsah: Pro data, která musí existovat jen během aktuálního tahu
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);
});

Poznámka

Použít MemoryStorage pro místní vývoj a testování. Pro produkční nasazení, zejména při nasazení na více instancích, použijte poskytovatele trvalého úložiště, například Azure Cosmos DB nebo Azure Blob Storage. Viz Použití poskytovatelů úložiště v agentovi.

Další kroky