AgentApplication i SDK til Microsoft 365-agenter

AgentApplication er den centrale byggeklods for en agent, der er bygget med Agents SDK. AgentApplication er indgangspunktet for alle indgående aktiviteter, herunder meddelelser fra brugere, hændelser for samtalelivscyklus, adaptive kortinteraktioner, OAuth-tilbagekald.

En agent er i sin kerne en AgentApplication. Du konfigurerer den med handlere, der beskriver, hvad din agent gør. SDK'et tager sig af routing, tilstandsstyring og den infrastruktur, der kræves for at køre den.

Sådan fungerer AgentApplication

Hver agent har en livscyklus, der starter, når en kanal (Microsoft Teams, en robottjeneste eller en brugerdefineret klient) leverer en aktivitet til din agents slutpunkt. AgentApplication sidder i midten af denne livscyklus:

Channel → Hosting layer → AgentApplication → Your handlers

Behandlingslagene i en agent, der er bygget med Agents SDK, fungerer på følgende måde:

  1. Hostinglaget modtager HTTP-anmodningen og godkender den.
  2. AgentApplication behandler den indgående aktivitet via pipelinen.
  3. Dine handlere kaldes baseret på matchende ruter.

Din agent indlæser tilstanden, før handlerne kører. Derefter gemmer agenten turn-tilstanden.

Kernebegreber

Aktiviteter

Alt i Agents SDK-flow som en aktivitet. En aktivitet er en struktureret meddelelse, der repræsenterer noget, der er sket. En aktivitet har en type, f.eks. meddelelse, hændelse, aktivering, conversationUpdate osv. Den indeholder en nyttelast, der er relevant for denne type opgave. AgentApplication modtager aktiviteter og dirigerer dem til den rette handler.

Ruter

En rute parrer en selektor med en handler. Vælgeren bestemmer, om en rute stemmer overens med den aktuelle aktivitet. Handleren kører din logik, når ruten matcher.

Registrer ruter, når du konfigurerer din agent. De kan matche:

  • En meddelelse, der indeholder bestemt tekst eller matcher et regulært udtryk
  • Enhver aktivitet af en given type
  • Hændelser for samtalelivscyklus (medlem tilføjet, medlem fjernet)
  • Handlinger på adaptivt kort
  • Brugerdefinerede betingelser

Når en aktivitet ankommer, evaluerer systemet ruterne i rækkefølge, indtil det finder et match. Som standard køres der kun én rute.

Skift tilstand

AgentApplication administrerer _turn tilstand – struktureret lager, der er partitioneret i områder:

Type af omfang Beskrivende tekst
Samtale Delt mellem alle brugere i en samtale, opretholdes mellem omgange
User Begrænset til en enkelt bruger på tværs af alle samtaler
Temp Kun aktuel tur – aldrig permanent

Systemet indlæser automatisk tilstanden, før dine handlere kører, og gemmer det automatisk bagefter.

Slå kontekst

Når en handler kører, modtager den en turn-kontekst. Turn-kontekst er et snapshot af den aktuelle aktivitet, adapterforbindelsen og hjælpeprogrammer til afsendelse af svar. Turn-konteksten er din grænseflade til den aktuelle interaktion.

Middleware

AgentApplication understøtter en middleware-pipeline. Middleware er en kæde af komponenter, der behandler hver tur før og efter, at dine handlere kører. Middleware kan inspicere, transformere eller kortslutte aktivitetsflowet. Almindelige anvendelser omfatter logføring, godkendelseskontroller og anmodning om normalisering.

Oprette en agent

Underklasse, AgentApplication og registrer dine handlere i konstruktøren. Hostingstrukturen indsætter AgentApplicationOptionsautomatisk .

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

Registrer din agent i 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();

Registrer aktivitetshandlere

Håndter meddelelser

Forskel på meddelelser efter præcis tekst (der skelnes ikke mellem store og små bogstaver):

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

Søg efter meddelelser ved hjælp af et regulært udtryk:

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

Håndter samtaleopdateringer

Registrer handlere for hændelser for samtalelivscyklus, f.eks. medlemmer, der tilmelder sig eller forlader samtalen.

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

Håndter alle aktivitetstyper

Match enhver aktivitet med dens typestreng for at få fuld kontrol over distributionen.

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

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

Brug ActivityTypes konstanter i stedet for hard-coded strenge.

Kontrollér rækkefølgen af evaluering af rute

Systemet sorterer ruter i en fast evalueringsrækkefølge, når du registrerer dem, ikke på kørselstidspunktet. Sorteringen bruger to niveauer:

  1. Rutetype: Systemet grupperer ruter efter type, og det evaluerer altid typer med højere prioritet før typer med lavere prioritet, uanset rangering:

    Prioritet Rutetype
    1 (højeste) Aktiveringsruter for agentisk
    2 Aktivér ruter (handlinger på adaptive kort, OAuth-tilbagekald og andre tidsfølsomme kald)
    3 Agentiske ruter
    4 (laveste) Alle andre ruter
  2. Rangering: I hver rutetypegruppe sorteres ruterne efter deres rangeringsværdi. Lavere numeriske værdier evalueres først.

Brug RouteRank konstanter til at angive rangering ved registrering af en handler:

Konstant Værdi Betydning
RouteRank.First 0 Evalueret før alle andre ruter i gruppen
RouteRank.Unspecified 32767 Standard, når der ikke er angivet nogen rangering
RouteRank.Last 65535 Evalueret efter alle andre ruter i gruppen

Evalueringen stopper som standard ved den første matchende rute. Brug RouteRank.Last som en catch-all fallback, der håndterer alt, der ikke stemmer overens med en mere specifik rute.

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

Drej livscykluskroge

Registrer logik, der kører på hver tur, før eller efter rutematchning. Disse kroge er nyttige til logføring, tværgående anliggender og fejlhåndtering.

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

Når OnBeforeTurn returnerer false, afbrydes omgangen, og der køres ingen ruter. Når OnAfterTurn returnerer false, gemmes turn-tilstanden ikke.

Brug turn-tilstand

Agenten indlæser automatisk turn-tilstand, før dine handlere kører, og gemmer den bagefter. Det turn state-objekt, der overføres til dine handlere, giver dig adgang til de forskellige områder, så du kan læse og skrive data, der bevares på tværs af sving eller er ephemerale for det aktuelle sving:

  • Samtaleomfang: For data, der deles på tværs af alle sving i en samtale
  • Brugerområde: For data pr. bruger
  • Temp-omfang: For data, der kun skal findes under den aktuelle omgang
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);
});

Note

Bruges MemoryStorage til lokal udvikling og test. I forbindelse med udrulninger af produktion, især udrulninger, der kører på flere forekomster, skal du bruge en vedvarende lagerudbyder, f.eks. Azure Cosmos DB eller Azure Blob Storage. Se Brug lagerudbydere i din agent.

Næste trin