Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
AgentApplication ist die zentrale Komponente eines mit dem Agents SDK entwickelten Agents.
AgentApplication ist der Einstiegspunkt für alle eingehenden Aktivitäten, einschließlich Nachrichten von Benutzern, Unterhaltungslebenszyklusereignisse, Interaktionen mit adaptiven Karten, OAuth-Rückrufe.
Ein Agent ist im Kern ein AgentApplication. Sie konfigurieren ihn mit Handlern, die beschreiben, was Ihr Agent tut. Das SDK kümmert sich um Routing, Zustandsmanagement und die Infrastruktur, die für den Betrieb erforderlich ist.
Funktionsweise von AgentApplication
Der Lebenszyklus eines jeden Agents beginnt, sobald ein Kanal (Microsoft Teams, ein Bot Service oder ein benutzerdefinierter Client) eine Aktivität an den Endpunkt Ihres Agents übermittelt.
AgentApplication steht im Zentrum dieses Lebenszyklus:
Channel → Hosting layer → AgentApplication → Your handlers
Die Verarbeitungsschichten in einem Agent, der mit dem Agents SDK gebaut wurde, funktionieren wie folgt:
- Die Hosting-Schicht empfängt die HTTP-Anforderung und authentifiziert sie.
- Die
AgentApplicationverarbeitet die eingehende Aktivität durch ihre Pipeline. - Ihre Handler werden basierend auf übereinstimmenden Routen aufgerufen.
Ihr Agent lädt den Zustand, bevor Ihre Handler laufen. Anschließend speichert der Agent den Dialogschrittstatus.
Wichtige Konzepte
Aktivitäten
Alles im Agents SDK fließt als eine Aktivität. Eine Aktivität ist eine strukturierte Nachricht, die etwas darstellt, das geschehen ist. Eine Aktivität hat einen Typ, zum Beispiel Message, Event, Aufruf, conversationUpdate und so weiter. Es trägt eine für diesen Typ relevante Nutzlast.
AgentApplication nimmt Aktivitäten entgegen und leitet sie an den passenden Handler weiter.
Arbeitspläne
Eine Route verbindet einen Selektor mit einem Handler. Der Selektor bestimmt, ob eine Route mit der aktuellen Aktivität übereinstimmt. Der Handler führt Ihre Logik aus, wenn die Route übereinstimmt.
Registrieren Sie Routen, wenn Sie Ihren Agent konfigurieren. Folgendes kann abgeglichen werden:
- Eine Nachricht, die einen bestimmten Text enthält oder mit einem regulären Ausdruck übereinstimmt
- Jede Aktivität eines bestimmten Typs
- Unterhaltungslebenszyklus-Ereignisse (Mitglied hinzugefügt, Mitglied entfernt)
- Aktionen für adaptive Karten
- Benutzerdefinierte Bedingungen
Wenn eine Aktivität empfangen wird, prüft das System die Routen der Reihe nach, bis es eine Übereinstimmung findet. Standardmäßig wird nur eine Route ausgeführt.
Turn-Zustand
AgentApplication verwaltet den Turn-Zustand—ein strukturierter Speicher, der in Umfänge aufgeteilt ist:
| Bereichstyp | Beschreibung des Dataflows |
|---|---|
| Unterhaltung | Geteilt von allen Nutzern in einer Unterhaltung, über mehrere Runden hinweg gespeichert |
| Benutzer | Gültig für einen einzelnen Nutzer über alle Unterhaltungen hinweg |
| Temp. | Nur aktueller Dialogschritt – wird nie beibehalten |
Das System lädt den Status automatisch, bevor Ihre Handler ausgeführt werden, und speichert ihn danach automatisch.
Durchlaufkontext
Wenn ein Handler ausführt, erhält er einen Zug-Kontext. Der Dialogschrittkontext ist eine Momentaufnahme der aktuellen Aktivität, der Adapterverbindung und der Hilfsprogramme zum Senden von Antworten. Der Dialogschrittkontext ist Ihre Schnittstelle zur aktuellen Interaktion.
Middleware
AgentApplication unterstützt eine Middleware-Pipeline. Middleware ist eine Kette von Komponenten, die jeden Dialogschritt vor und nach der Ausführung der Handler verarbeiten. Middleware kann den Aktivitätsfluss inspizieren, transformieren oder kurzschließen. Häufige Anwendungen sind Protokollierung, Authentifizierungsprüfungen und Normalisierung von Anfragen.
Einen Agent erstellen
Leiten Sie AgentApplication ab und registrieren Sie Ihre Handler im Konstruktor. Das Hosting-Framework injiziert AgentApplicationOptions automatisch.
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);
}
}
Registrieren Sie Ihren Agent in 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();
Aktivitätshandler registrieren
Nachrichten verarbeiten
Nachrichten anhand des exakten Texts (groß-/kleinschreibungsunabhängig) abgleichen:
OnMessage("help", async (context, state, ct) =>
{
await context.SendActivityAsync("Here's what I can do...", cancellationToken: ct);
});
Abgleichen von Nachrichten mithilfe eines regulären Ausdrucks:
OnMessage(new Regex(@"^order\s+\d+$", RegexOptions.IgnoreCase), async (context, state, ct) =>
{
await context.SendActivityAsync("Looking up your order...", cancellationToken: ct);
});
Unterhaltungsaktualisierungen handhaben
Registrieren Sie Handler für Unterhaltungslebenszyklus-Ereignisse wie das Ein- oder Austreten von Mitgliedern.
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
});
Jede Aktivitätsart behandeln
Aktivitäten anhand ihrer Typ-Zeichenfolge abgleichen, um vollständige Kontrolle über das Routing zu erhalten.
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Handles all message activities
});
OnActivity(ActivityTypes.Event, async (context, state, ct) =>
{
// Handles event activities
});
Verwenden Sie ActivityTypes-Konstanten statt fest kodierter Zeichenfolgen.
Bewertungsreihenfolge der Steuerrouten
Das System sortiert die Routen bei der Registrierung in eine feste Auswertungsreihenfolge, nicht zur Laufzeit. Die Sortierung verwendet zwei Ebenen:
Routentyp: Das System gruppiert Routen nach Typ und wertet immer höher priorisierte Typen vor niedriger priorisierten Typen aus, unabhängig vom Rang:
Priorität Routentyp 1 (höchste) Agentische Aufrufrouten 2 Aufrufrouten (adaptive Kartenaktionen, OAuth-Rückrufe und andere zeitabhängige Aufrufe) 3 Agentische Routen 4 (niedrigste) Alle anderen Routen Rang: Innerhalb jeder Routentypgruppe ordnet das System die Routen nach ihrem Rangwert. Niedrigere numerische Werte werden zuerst geprüft.
Verwenden Sie RouteRank-Konstanten, um den Rang beim Registrieren eines Handlers festzulegen:
| Konstante | Wert | Bedeutung |
|---|---|---|
RouteRank.First |
0 |
Ausgewertet vor allen anderen Routen in seiner Gruppe |
RouteRank.Unspecified |
32767 |
Standard, wenn kein Rang angegeben ist |
RouteRank.Last |
65535 |
Ausgewertet nach allen anderen Routen in der Gruppe |
Standardmäßig endet die Verarbeitung bei der ersten passenden Route. Verwenden Sie RouteRank.Last als Auffangroute, die alles übernimmt, was nicht von einer spezifischeren Route abgedeckt wird.
// 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);
Dialogschrittlebenszyklus-Hooks
Logik registrieren, die bei jedem Zug ausgeführt wird, vor oder nach dem Routenabgleich. Diese Hooks sind nützlich zur Protokollierung, Querschnittsthemen und Fehlerbehandlung.
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);
});
Wenn OnBeforeTurn das Ergebnis false zurückgibt, wird der Dialogschritt abgebrochen, und es werden keine Routen ausgeführt. Wenn OnAfterTurnfalse zurückgibt, wird der Zug-Zustand nicht gespeichert.
Turn-Zustand verwenden
Der Agent lädt den Dialogschrittstatus automatisch, bevor die Handler ausgeführt werden, und speichert ihn danach. Das Turn State-Objekt, das an Ihre Handler übergeben wird, ermöglicht Ihnen den Zugriff auf die verschiedenen Umfänge, sodass Sie Daten lesen und schreiben können, die entweder über mehrere Turns hinweg bestehen bleiben oder nur für den aktuellen Turn verfügbar sind.
- Unterhaltungsbereich: Für Daten, die über alle Dialogschritte einer Unterhaltung verfügbar sind
- Benutzerumfang: Für Daten pro Benutzer
- Temp. Bereich: Für Daten, die nur während des aktuellen Dialogschritts existieren müssen
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);
});
Anmerkung
Verwenden Sie MemoryStorage zur lokalen Entwicklung und Tests Für den Produktivbetrieb, insbesondere bei Bereitstellungen mit mehreren Instanzen, verwenden Sie einen persistenten Speicheranbieter wie Azure Cosmos DB oder Azure Blob Storage. Siehe Speicheranbieter in Ihrem Agent verwenden.