AgentApplication dalam Agen SDK Microsoft 365

AgentApplication adalah penyusun baris pusat dari agen yang dibangun dengan SDK Agen. AgentApplication adalah titik masuk untuk semua aktivitas masuk, termasuk pesan dari pengguna, peristiwa siklus hidup percakapan, interaksi kartu adaptif, panggilan balik OAuth.

Agen, pada intinya, sebuah AgentApplication. Anda mengonfigurasinya dengan handler yang menjelaskan apa yang dilakukan agen Anda. SDK mengurus perutean, manajemen status, dan infrastruktur yang diperlukan untuk menjalankannya.

Cara kerja AgentApplication

Setiap agen memiliki siklus hidup yang dimulai ketika saluran (Microsoft Teams, layanan bot, atau klien kustom) memberikan aktivitas ke titik akhir agen Anda. AgentApplication berada di pusat siklus hidup tersebut:

Channel → Hosting layer → AgentApplication → Your handlers

Lapisan pemrosesan dalam agen yang dibangun dengan Agen SDK berfungsi sebagai berikut:

  1. Lapisan hosting menerima permintaan HTTP dan mengautentikasinya.
  2. AgentApplication memproses aktivitas masuk melalui alurnya.
  3. Handler Anda dipanggil berdasarkan rute yang cocok.

Agen Anda memuat status giliran sebelum handler Anda berjalan. Setelah itu, agen menyimpan status giliran.

Konsep inti

Activities

Semua yang ada dalam SDK Agen mengalir sebagai aktivitas. Aktivitas adalah pesan terstruktur yang mewakili sesuatu yang terjadi. Aktivitas memiliki jenis, seperti pesan, peristiwa, pemanggilan, conversationUpdate, dan sebagainya. Ini membawa muatan yang relevan dengan jenis tersebut. AgentApplication menerima aktivitas dan merutekannya ke handler yang tepat.

Routes

Rute memasangkan pemilih dengan handler. Pemilih menentukan apakah rute cocok dengan aktivitas saat ini. Handler menjalankan logika Anda saat rute cocok.

Daftarkan rute saat Anda mengonfigurasi agen Anda. Mereka bisa mencocokkan:

  • Pesan yang berisi teks tertentu atau cocok dengan ekspresi reguler
  • Aktivitas apa pun dari jenis tertentu
  • Peristiwa siklus hidup percakapan (anggota ditambahkan, anggota dihapus)
  • Tindakan kartu adaptif
  • Kondisi kustom

Ketika aktivitas tiba, sistem mengevaluasi rute secara berurutan hingga menemukan kecocokan. Secara default, hanya satu rute yang berjalan.

Ubah keadaan

AgentApplication mengelola _turn state—penyimpanan terstruktur yang dipartisi menjadi beberapa cakupan:

Jenis cakupan Description
Percakapan Dibagikan kepada semua pengguna dalam percakapan, disimpan di antara giliran
Pengguna Terbatas pada pengguna individu di semua percakapan
Temp Giliran saat ini saja - tidak pernah bertahan

Sistem secara otomatis memuat status sebelum handler Anda berjalan dan menyimpannya secara otomatis setelahnya.

Ubah konteks

Saat handler berjalan, handler akan menerima konteks giliran. Konteks giliran adalah snapshot aktivitas saat ini, koneksi adaptor, dan utilitas untuk mengirim respons. Konteks giliran adalah antarmuka Anda untuk interaksi yang sedang berlangsung.

Middleware

AgentApplication mendukung alur middleware. Middleware adalah serangkaian komponen yang memproses setiap langkah sebelum dan sesudah handler Anda menjalankan. Middleware dapat memeriksa, mengubah, atau mempersingkat alur aktivitas. Penggunaan umum termasuk pengelogan, pemeriksaan autentikasi, dan normalisasi permintaan.

Buat agen

Subkelas AgentApplication dan daftarkan handler Anda di konstruktor. Kerangka kerja hosting secara otomatis menyuntikkan 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);
    }
}

Daftarkan agen Anda di 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();

Mendaftarkan pengendali aktivitas

Menangani pesan

Cocokkan pesan dengan teks yang tepat (tidak peka huruf besar/kecil):

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

Cocokkan pesan menggunakan ekspresi reguler:

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

Menangani perubahan pembicaraan

Daftarkan handler untuk peristiwa siklus hidup percakapan seperti anggota yang bergabung atau pergi.

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

Menangani jenis aktivitas apa pun

Cocokkan aktivitas apa pun dengan string jenisnya untuk kontrol penuh atas perutean.

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

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

Gunakan ActivityTypes konstanta alih-alih string yang dikodekan secara permanen.

Urutan evaluasi rute kontrol

Sistem mengurutkan rute ke dalam urutan evaluasi tetap saat Anda mendaftarkannya, bukan pada waktu proses. Pengurutan menggunakan dua tingkat:

  1. Jenis rute: Sistem mengelompokkan rute berdasarkan jenis, dan selalu mengevaluasi jenis prioritas yang lebih tinggi sebelum jenis prioritas yang lebih rendah, terlepas dari peringkat:

    Prioritas Jenis rute
    1 (tertinggi) Rute pemanggilan agentik
    2 Memanggil rute (tindakan kartu adaptif, panggilan balik OAuth, dan pemanggilan sensitif waktu lainnya)
    3 Rute agentik
    4 (terendah) Semua rute lainnya
  2. Peringkat: Dalam setiap grup jenis rute, sistem memesan rute berdasarkan nilai peringkatnya. Nilai numerik yang lebih rendah dievaluasi terlebih dahulu.

Gunakan RouteRank konstanta untuk mengatur peringkat saat mendaftarkan handler:

Konstanta Value Meaning
RouteRank.First 0 Dievaluasi sebelum semua rute lain dalam grupnya
RouteRank.Unspecified 32767 Default ketika peringkat tidak ditentukan
RouteRank.Last 65535 Dievaluasi setelah semua rute lain dalam grupnya

Secara default, evaluasi berhenti pada rute pertama yang cocok. Gunakan RouteRank.Last untuk fallback catch-all yang menangani apa pun yang tidak cocok dengan rute yang lebih spesifik.

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

Kait siklus hidup giliran

Daftarkan logika yang dijalankan di setiap putaran, baik sebelum atau sesudah pencocokan rute. Kait ini berguna untuk pengelogan, lintas aspek, dan penanganan kesalahan.

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

Saat OnBeforeTurn mengembalikan false, gilirannya dibatalkan dan tidak ada rute yang dijalankan. Saat OnAfterTurn mengembalikan false, status giliran tidak disimpan.

Gunakan status giliran

Agen secara otomatis memuat status giliran sebelum handler Anda berjalan dan menyimpannya setelahnya. Objek status giliran yang diteruskan ke handler memberi Anda akses ke cakupan yang berbeda sehingga Anda dapat membaca dan menulis data yang bertahan dari satu giliran ke giliran berikutnya atau bersifat sementara untuk giliran tersebut.

  • Cakupan percakapan: Untuk data yang dibagikan di semua giliran dalam percakapan
  • Cakupan pengguna: Untuk data per pengguna
  • Cakupan sementara: Untuk data yang hanya perlu ada selama giliran saat ini
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

Gunakan MemoryStorage untuk pengembangan dan pengujian lokal. Untuk penyebaran produksi, terutama penyebaran yang berjalan pada beberapa instans, gunakan penyedia penyimpanan persisten seperti Azure Cosmos DB atau Azure Blob Storage. Lihat Gunakan penyedia penyimpanan di agen Anda.

Langkah berikutnya