AgentApplication σε SDK παραγόντων Microsoft 365

AgentApplication Είναι το κεντρικό μπλοκ δόμησης ενός παράγοντα που δημιουργήθηκε με το Agents SDK. AgentApplication Το είναι το σημείο εισόδου για όλες τις εισερχόμενες δραστηριότητες, συμπεριλαμβανομένων των μηνυμάτων από χρήστες, συμβάντα κύκλου ζωής συνομιλίας, προσαρμόσιμες αλληλεπιδράσεις καρτών, επιστροφές κλήσης OAuth.

Ένας παράγοντας είναι, στον πυρήνα του, ένας AgentApplication. Μπορείτε να ρυθμίσετε τις παραμέτρους του με χειρισμούς που περιγράφουν τι κάνει ο πράκτοράς σας. Το SDK αναλαμβάνει τη δρομολόγηση, τη διαχείριση των πολιτειών και την υποδομή που απαιτείται για την εκτέλεση.

Πώς λειτουργεί το AgentApplication

Κάθε παράγοντας έχει έναν κύκλο ζωής που ξεκινά όταν ένα κανάλι (Microsoft Teams, μια υπηρεσία bot ή ένα προσαρμοσμένο πρόγραμμα-πελάτη) παρέχει μια δραστηριότητα στο τελικό σημείο του παράγοντα σας. AgentApplication βρίσκεται στο κέντρο του κύκλου ζωής:

Channel → Hosting layer → AgentApplication → Your handlers

Τα επίπεδα επεξεργασίας σε έναν παράγοντα που δημιουργείται με το Agents SDK λειτουργούν ως εξής:

  1. Το επίπεδο φιλοξενίας λαμβάνει την αίτηση HTTP και την πραγματοποιεί έλεγχο ταυτότητας.
  2. Η AgentApplication επεξεργάζεται την εισερχόμενη δραστηριότητα μέσω του σωλήνα.
  3. Οι διαχειριστές καλούνται με βάση τις αντιστοιχισμένες διαδρομές.

Ο πράκτοράς σας φορτώνει την κατάσταση αλλαγής πριν την εκτέλεση των χειριστών. Αφού, ο πράκτορας αποθηκεύει την κατάσταση λειτουργίας.

Βασικές έννοιες

Δραστηριότητες

Όλα τα στοιχεία στο Ατζέντες SDK ρέουν ως δραστηριότητα. Μια δραστηριότητα είναι ένα δομημένο μήνυμα που αντιπροσωπεύει κάτι που συνέβη. Μια δραστηριότητα έχει έναν τύπο, όπως μήνυμα, συμβάν, κλήση, συνομιλίαΗμερομηνία και ούτω καθεξής. Μεταφέρει ένα ωφέλιμο φορτίο σχετικό με αυτόν τον τύπο. AgentApplication λαμβάνει δραστηριότητες και τις δρομολογεί στον σωστό διαχειριστή.

Διαδρομές

Μια διαδρομή αντιστοιχίζει έναν επιλογέα με έναν χειρισμό. Ο επιλογέας προσδιορίζει εάν μια διαδρομή συμφωνεί με την τρέχουσα δραστηριότητα. Ο χειριστής εκτελεί τη λογική σας όταν η διαδρομή αντιστοιχεί.

Καταχωρήστε τις δρομολογίσεις όταν ρυθμίζετε τον πράκτορά σας. Μπορούν να ταιριάζουν:

  • Ένα μήνυμα που περιέχει συγκεκριμένο κείμενο ή που αντιστοιχεί σε μια κανονική παράσταση
  • Οποιαδήποτε δραστηριότητα συγκεκριμένου τύπου
  • Συμβάντα κύκλου ζωής συνομιλίας (το μέλος προστέθηκε, το μέλος καταργήθηκε)
  • Ενέργειες προσαρμόσιμης κάρτας
  • Προσαρμοσμένες συνθήκες

Κατά την άφιξη μιας δραστηριότητας, το σύστημα αξιολογεί τις δρομολογήσεις με τη σειρά μέχρι να εντοπίσει μια αντιστοιχία. Από προεπιλογή, εκτελείται μόνο μία διαδρομή.

Μετατροπή κατάστασης

AgentApplication Το διαχειρίζεται _turn κατάσταση , δομημένος χώρος αποθήκευσης διαμεισμένος σε εμβέλειες:

Τύπος εμβέλειας Περιγραφή
Συνομιλία Κοινή χρήση για όλους τους χρήστες σε μια συνομιλία, με παραμονή μεταξύ των εναλλαγών
Χρήστης Περικλείεται σε έναν μεμονωμένο χρήστη σε όλες τις συνομιλίες
Temp Μόνο η τρέχουσα στροφή - ποτέ δεν διατηρήθηκε

Το σύστημα φορτώνει αυτόματα την κατάσταση πριν από την εκτέλεση των χειριστών σας και την αποθηκεύει αυτόματα στη συνέχεια.

Εναλλαγή πλαισίου

Όταν εκτελείται ένας χειρισμός, λαμβάνει ένα περιβάλλον στροφής. Η ρύθμιση περιβάλλοντος είναι ένα στιγμιότυπο της τρέχουσας δραστηριότητας, της σύνδεσης προσαρμογέα και βοηθητικών προγραμμάτων για την αποστολή αποκρίσεων. Το περιβάλλον στροφής είναι η διασύνδεση στην τρέχουσα αλληλεπίδραση.

Middleware

AgentApplication υποστηρίζει μια διοχέτευση ενδιάμεσου λογισμικού. Το Middleware είναι μια αλυσίδα στοιχείων που επεξεργάζονται κάθε σειρά πριν και μετά την εκτέλεση των χειριστών σας. Το μεσαίο λογισμικό μπορεί να ελέγξει, να μετασχηματίσει ή να βραχυκυκλώσει τη ροή δραστηριότητας. Στις συνήθεις χρήσεις περιλαμβάνονται η καταγραφή, οι έλεγχοι ελέγχου ταυτότητας και η κανονικοποίηση αιτήσεων.

Δημιουργήστε πράκτορα

Υποκλάση 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. Τύπος διαδρομής: Οι ομάδες συστήματος δρομολογούν κατά τύπο και αξιολογεί πάντα τους τύπους υψηλότερης προτεραιότητας πριν από τους τύπους χαμηλότερης προτεραιότητας, ανεξάρτητα από την κατάταξη:

    Προτεραιότητα Τύπος δρομολόγησης
    1 (υψηλότερο) Η Agentic εφαρμόζει τις δρομολογίες
    2 Κλήση δρομολογήσεων (ενέργειες προσαρμόσιμης κάρτας, επιστροφές κλήσης OAuth και άλλες χρονικά ευαίσθητες ενεργοποιήσεις)
    3 Αντιπροσωπευτικές διαδρομές
    4 (χαμηλότερο) Όλες οι άλλες διαδρομές
  2. Κατάταξη: Σε κάθε ομάδα τύπου δρομολόγησης, το σύστημα ταξινομεί δρομολογεί σύμφωνα με την τιμή κατάταξης. Οι χαμηλότερες αριθμητικές τιμές αξιολογούνται πρώτες.

Χρήση RouteRank σταθερών για τον ορισμό κατάταξης κατά την καταχώρηση ενός δείκτη χειρισμού:

Σταθερά Τιμή Έννοια
RouteRank.First 0 Αξιολογήθηκε πριν από όλες τις άλλες διαδρομές στον όμιλο της
RouteRank.Unspecified 32767 Προεπιλογή όταν δεν καθορίζεται κατάταξη
RouteRank.Last 65535 Αξιολογήθηκε μετά από όλες τις άλλες διαδρομές στον όμιλο της

Από προεπιλογή, η αξιολόγηση σταματά στην πρώτη αντίστοιχη διαδρομή. Χρησιμοποιήστε RouteRank.Last το για μια εναλλακτική λύση catch-all που χειρίζεται οτιδήποτε δεν συμφωνεί με μια πιο συγκεκριμένη διαδρομή.

// 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, η κατάσταση στροφής δεν αποθηκεύεται.

Χρήση κατάστασης στροφής

Ο παράγοντας φορτώνει αυτόματα την κατάσταση στροφής πριν από την εκτέλεση των χειριστών σας και την αποθηκεύει στη συνέχεια. Το αντικείμενο κατάστασης στροφής που μεταβιβάζεται στους χειρισμούς σας σάς παρέχει πρόσβαση στις διαφορετικές εμβέλειες, ώστε να μπορείτε να διαβάζετε και να γράφετε δεδομένα που διατηρούνται μεταξύ των στροφών ή είναι εφήμερα για την τρέχουσα στροφή:

  • Εμβέλεια συνομιλίας: Για τα δεδομένα που κοινοποιούνται σε όλες τις στροφές σε μια συνομιλία
  • Εμβέλεια χρήστη: Για δεδομένα ανά χρήστη
  • Temp scope: Για δεδομένα που χρειάζεται να υπάρχουν μόνο κατά τη διάρκεια της τρέχουσας στροφής
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 ή Azure Blob Storage. Ανατρέξτε στο θέμα Χρήση υπηρεσιών παροχής χώρου αποθήκευσης στον πράκτορά σας.

Επόμενα βήματα