Layanan agen A2A

Memungkinkan A2AAgent aplikasi Anda terhubung ke agen jarak jauh yang diekspos melalui protokol Agent-to-Agent (A2A). Ini membungkus titik akhir yang mematuhi A2A sebagai standar AIAgent, sehingga Anda dapat menggunakan metode yang familier seperti RunAsync dan RunStreamingAsync untuk berinteraksi dengan agen jarak jauh terlepas dari kerangka kerja atau teknologi apa yang mereka bangun.

Untuk mengekspos agen Agent Framework sebagai server A2A, lihat Agen host dengan A2A.

Getting Started

Tambahkan paket NuGet yang diperlukan ke proyek Anda:

dotnet add package Microsoft.Agents.AI.A2A --prerelease

Penemuan Agen

Sebelum berkomunikasi dengan agen A2A jarak jauh, Anda perlu menemukannya dan membuat AIAgent instans. Protokol A2A mendefinisikan tiga strategi penemuan, masing-masing didukung oleh Agent Framework.

URI Well-Known

Agen A2A dapat membuat Kartu Agen mereka dapat ditemukan di jalur standar: https://{domain}/.well-known/agent-card.json. A2ACardResolver Gunakan untuk mengambil kartu dan membuat agen dalam satu panggilan:

using A2A;
using Microsoft.Agents.AI;

// Initialize a resolver pointing at the remote agent's host.
A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));

// Resolve the agent card and create an AIAgent in one step.
AIAgent agent = await resolver.GetAIAgentAsync();

// Use the agent.
Console.WriteLine(await agent.RunAsync("Hello!"));

Tip

GetAIAgentAsync juga menerima parameter opsional A2AClientOptions untuk pemilihan protokol.

penemuan Catalog-Based

Di lingkungan perusahaan atau pasar publik, Kartu Agen sering dikelola oleh registri pusat. Jika Anda sudah memiliki yang AgentCard diperoleh dari registri seperti itu, konversikan langsung ke AIAgent:

using A2A;
using Microsoft.Agents.AI;

// Assume agentCard was retrieved from a registry or catalog.
AgentCard agentCard = await GetAgentCardFromRegistryAsync("travel-planner");

AIAgent agent = agentCard.AsAIAgent();

Console.WriteLine(await agent.RunAsync("Plan a trip to Paris."));

Konfigurasi Langsung

Untuk sistem yang digabungkan dengan erat atau skenario pengembangan di mana titik akhir agen diketahui sebelumnya, buat A2AClient secara langsung dan konversi menjadi AIAgent:

using A2A;
using Microsoft.Agents.AI;

// Create a client pointing at the known agent endpoint.
A2AClient a2aClient = new(new Uri("https://a2a-agent.example.com"));

AIAgent agent = a2aClient.AsAIAgent(name: "my-agent", description: "A helpful assistant.");

Console.WriteLine(await agent.RunAsync("What can you help me with?"));

Pemilihan Protokol

Agen A2A dapat mengekspos beberapa pengikatan protokol seperti HTTP+JSON dan JSON-RPC. Secara default, HTTP+JSON lebih disukai daripada JSON-RPC. Gunakan A2AClientOptions.PreferredBindings untuk secara eksplisit mengontrol pengikatan protokol mana yang digunakan:

Nota

Agen A2A jarak jauh harus tersedia di titik akhir yang mendukung pengikatan protokol yang dipilih.

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver agentCardResolver = new(new Uri("https://a2a-agent.example.com"));

AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();

// Prefer HTTP+JSON protocol binding. For JSON-RPC, set PreferredBindings = [ProtocolBindingNames.JsonRpc]
A2AClientOptions options = new()
{
    PreferredBindings = [ProtocolBindingNames.HttpJson]
};

AIAgent agent = agentCard.AsAIAgent(options: options);

Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));

Streaming

A2A mendukung respons streaming melalui Server-Sent Events. Gunakan RunStreamingAsync untuk menerima pembaruan secara real time saat agen jarak jauh memproses permintaan:

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

await foreach (var update in agent.RunStreamingAsync("Write a short story about a robot."))
{
    if (!string.IsNullOrEmpty(update.Text))
    {
        Console.Write(update.Text);
    }
}

Respons Latar Belakang

Agen A2A mendukung respons latar belakang untuk menangani operasi yang berjalan lama. Saat agen A2A jarak jauh mengembalikan tugas alih-alih pesan langsung, Kerangka Kerja Agen menyediakan token kelanjutan yang dapat Anda gunakan untuk melakukan polling untuk hasil atau menyambungkan kembali ke aliran yang terganggu.

Polling untuk Penyelesaian Tugas

Untuk skenario non-streaming, gunakan AllowBackgroundResponses untuk menerima token dan polling kelanjutan hingga tugas selesai:

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

AgentSession session = await agent.CreateSessionAsync();

// AllowBackgroundResponses must be true so the server returns immediately with a continuation token
// instead of blocking until the task is complete.
AgentRunOptions options = new() { AllowBackgroundResponses = true };

// Start the initial run with a long-running task.
AgentResponse response = await agent.RunAsync(
    "Conduct a comprehensive analysis of quantum computing applications in cryptography.",
    session,
    options: options);

// Poll until the response is complete.
while (response.ContinuationToken is { } token)
{
    // Wait before polling again.
    await Task.Delay(TimeSpan.FromSeconds(2));

    // Continue with the token.
    response = await agent.RunAsync(session, options: new AgentRunOptions { ContinuationToken = token });
}

Console.WriteLine(response);

Koneksi Ulang Aliran

Dalam skenario streaming, setiap pembaruan dapat mencakup token kelanjutan. Jika aliran terganggu, gunakan token untuk menyambungkan kembali dan mendapatkan aliran respons dari awal:

using A2A;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

AgentSession session = await agent.CreateSessionAsync();

ResponseContinuationToken? continuationToken = null;

await foreach (var update in agent.RunStreamingAsync(
    "Conduct a comprehensive analysis of quantum computing applications in cryptography.",
    session))
{
    // Save the continuation token to reconnect later if the stream is interrupted.
    // Continuation tokens are only returned for long-running tasks. If the A2A agent
    // returns a message instead of a task, the continuation token will not be initialized.
    if (update.ContinuationToken is { } token)
    {
        continuationToken = token;
    }
}

// If the stream was interrupted and a continuation token was captured,
// reconnect to the response stream using the saved continuation token.
if (continuationToken is not null)
{
    await foreach (var update in agent.RunStreamingAsync(
        session,
        options: new() { ContinuationToken = continuationToken }))
    {
        if (!string.IsNullOrEmpty(update.Text))
        {
            Console.WriteLine(update.Text);
        }
    }
}

Nota

Agen A2A mendukung koneksi ulang aliran (mendapatkan aliran respons yang sama dari awal), bukan memulai kembali streaming dari titik tertentu di aliran.

Tools

A2AAgent adalah pembungkus tingkat transportasi di sekitar agen A2A jarak jauh. Alat apa pun yang digunakan agen jarak jauh secara langsung di sisi jarak jauh dan tidak terlihat oleh kode Anda. Jenis alat Agent Framework (alat fungsi, penerjemah kode, pencarian file, MCP yang dihosting/lokal, dll.) tidak dikonfigurasi pada A2AAgent dirinya sendiri — untuk memperluas kemampuan agen jarak jauh, mengubah konfigurasi agen jarak jauh.

Getting Started

Instal paket A2A:

pip install agent-framework-a2a --pre

Inisialisasi

A2AAgent dapat diinisialisasi dengan tiga cara tergantung pada seberapa banyak Anda tahu tentang agen jarak jauh sebelumnya.

URL Langsung

Untuk pengembangan atau sistem yang digabungkan dengan erat di mana titik akhir diketahui:

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    response = await agent.run("Hello!")
    print(response.messages[0].text)

Ketika hanya URL yang disediakan, A2AAgent buat kartu agen minimal secara internal dan terhubung menggunakan JSON-RPC.

Kartu Agen

Jika Anda memiliki AgentCard dari registri atau katalog, teruskan secara langsung:

from agent_framework.a2a import A2AAgent

async with A2AAgent(agent_card=agent_card) as agent:
    response = await agent.run("Plan a trip to Paris.")
    print(response.messages[0].text)

AgentCard Ketika disediakan, A2AAgent default name dan description dari kartu. Ini menegosiasikan transportasi menggunakan kartu supported_interfaces.

URI Well-Known (A2ACardResolver)

Gunakan A2ACardResolver dari a2a-sdk untuk menemukan agen jarak jauh di jalur standar terkenal (/.well-known/agent.json):

import httpx
from a2a.client import A2ACardResolver
from agent_framework.a2a import A2AAgent

async with httpx.AsyncClient(timeout=60.0) as http_client:
    resolver = A2ACardResolver(httpx_client=http_client, base_url="https://a2a-agent.example.com")
    agent_card = await resolver.get_agent_card()

async with A2AAgent(agent_card=agent_card) as agent:
    response = await agent.run("What can you help me with?")
    print(response.messages[0].text)

Streaming

Gunakan stream=True untuk menerima pembaruan secara real time saat agen jarak jauh memproses permintaan:

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    stream = agent.run("Write a short story about a robot.", stream=True)
    async for update in stream:
        for content in update.contents:
            if content.text:
                print(content.text, end="", flush=True)

    final = await stream.get_final_response()
    print(f"\n({len(final.messages)} message(s))")

Tugas Berjalan Lama

Secara default, A2AAgent menunggu agen jarak jauh selesai sebelum kembali. Untuk tugas yang berjalan lama, atur background=True ke permukaan token kelanjutan yang dapat Anda gunakan untuk melakukan polling atau berlangganan nanti:

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="worker", url="https://a2a-agent.example.com") as agent:
    # Start a long-running task
    response = await agent.run("Process this large dataset", background=True)

    if response.continuation_token:
        # Poll for completion later
        result = await agent.poll_task(response.continuation_token)
        print(result)

Anda juga dapat berlangganan ulang ke aliran SSE alih-alih polling:

# Resubscribe to the task's event stream
response = await agent.run(continuation_token=response.continuation_token)

Identitas Pembicaraan (context_id)

A2AAgent menyimpan status protokol tahan lama sebagai AgentSession.service_session_idA2AServiceSessionId pemetaan:

Ladang Type Kegunaan
context_id str Mengidentifikasi percakapan A2A.
task_id str \| None Melacak tugas jarak jauh terbaru, saat respons dibuat.
task_state TaskState \| None Merekam status tugas terbaru sehingga permintaan berikutnya dapat melanjutkan tugas yang diperlukan input atau mereferensikan tugas yang telah selesai.

Buat sesi dengan status terstruktur saat aplikasi Anda sudah mengetahui konteks A2A:

from agent_framework import AgentSession
from agent_framework.a2a import A2AAgent, A2AServiceSessionId

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    session = AgentSession(
        service_session_id=A2AServiceSessionId(
            context_id="my-conversation-1",
            task_id=None,
            task_state=None,
        )
    )

    # The A2A message uses context_id="my-conversation-1".
    response = await agent.run("Hello!", session=session)

    # A2AAgent updates task_id and task_state from the response.
    response = await agent.run("Follow-up question", session=session)

Anda juga dapat memulai dengan AgentSession() dan membiarkan A2AAgent mengisi pemetaan terstruktur dari respons pertama. Pertahankan sesi reguler dengan session.to_dict() dan pulihkan dengan AgentSession.from_dict(...); konteks A2A, ID tugas, dan status tugas tetap bersama.

Untuk tugas di TASK_STATE_INPUT_REQUIRED, pesan berikutnya mengatur bahwa task_id untuk melanjutkan tugas yang sama. Untuk status tugas lainnya, ID tugas sebelumnya dikirim reference_task_ids sehingga agen jarak jauh dapat memperbaiki atau melanjutkan dari hasil sebelumnya.

Authentication

Gunakan sebuah AuthInterceptor untuk titik akhir A2A yang aman.

from a2a.client.auth.interceptor import AuthInterceptor
from agent_framework.a2a import A2AAgent

class BearerAuth(AuthInterceptor):
    def __init__(self, token: str):
        self.token = token

    async def intercept(self, request):
        request.headers["Authorization"] = f"Bearer {self.token}"
        return request

async with A2AAgent(
    name="secure-agent",
    url="https://secure-a2a-agent.example.com",
    auth_interceptor=BearerAuth("your-token"),
) as agent:
    response = await agent.run("Hello!")

Konfigurasi Batas Waktu

A2AAgent timeout menerima parameter untuk mengontrol batas waktu permintaan:

import httpx
from agent_framework.a2a import A2AAgent

# Simple timeout (applies to all components)
async with A2AAgent(name="remote", url="https://example.com", timeout=120.0) as agent:
    ...

# Fine-grained timeout
async with A2AAgent(
    name="remote",
    url="https://example.com",
    timeout=httpx.Timeout(connect=10.0, read=120.0, write=10.0, pool=5.0),
) as agent:
    ...

Ketika tidak ada batas waktu yang ditentukan, defaultnya adalah: 10s connect, 60s read, 10s write, 5s pool.

Tools

A2AAgent adalah pembungkus tingkat transportasi di sekitar agen A2A jarak jauh. Alat apa pun yang digunakan agen jarak jauh secara langsung di sisi jarak jauh dan tidak terlihat oleh kode Anda. Jenis alat Agent Framework (alat fungsi, penerjemah kode, pencarian file, MCP yang dihosting/lokal, dll.) tidak dikonfigurasi pada A2AAgent dirinya sendiri — untuk memperluas kemampuan agen jarak jauh, mengubah konfigurasi agen jarak jauh.

Jika Anda ingin agen Foundry memanggil agen A2A sebagai alat, lihat get_a2a_tool pabrik di FoundryChatClient.

Go mendukung agen A2A jarak jauh melalui provider/a2aprovider paket.

Instal paket Agent Framework dan A2A:

go get github.com/microsoft/agent-framework-go
go get github.com/a2aproject/a2a-go/v2

Menyambungkan ke agen A2A jarak jauh

Atasi kartu agen jarak jauh, buat klien A2A darinya, dan bungkus klien sebagai agen Agent Framework standar:

import (
    "context"

    "github.com/a2aproject/a2a-go/v2/a2aclient"
    "github.com/a2aproject/a2a-go/v2/a2aclient/agentcard"
    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/provider/a2aprovider"
)

ctx := context.Background()

card, err := agentcard.DefaultResolver.Resolve(ctx, "http://localhost:5000")
if err != nil {
    panic(err)
}

client, err := a2aclient.NewFromCard(ctx, card)
if err != nil {
    panic(err)
}

a := a2aprovider.NewAgent(
    client,
    a2aprovider.AgentConfig{
        Config: agent.Config{
            Name:        card.Name,
            Description: card.Description,
        },
    },
)

resp, err := a.RunText(ctx, "Hello!").Collect()

Penyedia menyimpan A2A context_id dan ID tugas dalam sesi Kerangka Kerja Agen sehingga pesan tindak lanjut dapat mempertahankan kelangsungan percakapan.

Pemilihan protokol

Jika agen jarak jauh mengiklankan beberapa pengikatan transportasi, konfigurasikan transportasi pilihan saat membuat klien A2A:

client, err := a2aclient.NewFromCard(
    ctx,
    card,
    a2aclient.WithConfig(a2aclient.Config{
        PreferredTransports: []a2a.TransportProtocol{a2a.TransportProtocolHTTPJSON},
    }),
)

Gunakan a2a.TransportProtocolJSONRPC saat Anda ingin lebih memilih JSON-RPC.

Tugas jangka panjang

Tugas A2A muncul melalui token lanjutan Agent Framework. Mulai proses dengan sesi yang ditentukan secara eksplisit dan agent.AllowBackgroundResponses(true), kemudian lakukan polling dengan memanggil Run tanpa pesan baru dan dengan token kelanjutan:

session, err := a.CreateSession(ctx)
if err != nil {
    panic(err)
}

resp, err := a.RunText(
    ctx,
    "Process this large dataset.",
    agent.WithSession(session),
    agent.AllowBackgroundResponses(true),
).Collect()
if err != nil {
    panic(err)
}

for resp.ContinuationToken != "" {
    resp, err = a.Run(
        ctx,
        nil,
        agent.WithSession(session),
        agent.WithContinuationToken(resp.ContinuationToken),
    ).Collect()
    if err != nil {
        panic(err)
    }
}

Untuk eksekusi streaming yang terganggu, ambil update.ContinuationToken dari pembaruan terakhir yang diterima dan teruskan ke eksekusi streaming selanjutnya dengan agent.WithContinuationToken(token) dan agent.Stream(true).

Gunakan agen A2A jarak jauh sebagai alat

Atasi setiap agen jarak jauh, bungkus dengan a2aprovider.NewAgent, dan konversikan ke alat dengan agenttool.New.

tools := make([]tool.Tool, 0, len(agentURLs))

for _, agentURL := range agentURLs {
    card, err := agentcard.DefaultResolver.Resolve(ctx, agentURL)
    if err != nil {
        panic(err)
    }

    client, err := a2aclient.NewFromCard(ctx, card)
    if err != nil {
        panic(err)
    }

    remoteAgent := a2aprovider.NewAgent(client, a2aprovider.AgentConfig{
        Config: agent.Config{
            Name:        card.Name,
            Description: card.Description,
        },
    })

    tools = append(tools, agenttool.New(remoteAgent, agenttool.Config{}))
}

Tip

Lihat sampel penyedia A2A dan agen A2A sebagai sampel alat untuk contoh lengkap yang dapat dijalankan.

Langkah berikutnya

Masuk lebih dalam: