A2A-ügynökszolgáltatás

Ez A2AAgent lehetővé teszi, hogy az alkalmazás az Ügynökről ügynökre (A2A) protokollon keresztül közzétett távoli ügynökökhöz csatlakozzon. Minden A2A-kompatibilis végpontot szabványosként AIAgentburkol, így az ismerős módszereket, például RunAsync a RunStreamingAsync távoli ügynökökkel való interakciót használhatja, függetlenül attól, hogy milyen keretrendszerrel vagy technológiával készültek.

Az Agent Framework-ügynök A2A-kiszolgálóként való megjelenítéséhez lásd: Gazdagépügynökök A2A-vel.

Első lépések

Adja hozzá a szükséges NuGet-csomagot a projekthez:

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

Ügynökfelderítés

A távoli A2A-ügynökkel való kommunikáció előtt fel kell fedeznie, és létre kell hoznia egy példányt AIAgent . Az A2A protokoll három felderítési stratégiát határoz meg, amelyeket az Ügynök keretrendszer támogat.

Well-Known URI

Az A2A-ügynökök az ügynökkártyájukat egy szabványosított útvonalon fedezhetik fel: https://{domain}/.well-known/agent-card.json. A2ACardResolver A kártya lekérése és ügynök létrehozása egyetlen hívásban:

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

GetAIAgentAsynca A2AClientOptions opcionális paramétert is elfogad.

Catalog-Based felderítés

Vállalati környezetekben vagy nyilvános piactereken az ügynökkártyákat gyakran egy központi beállításjegyzék kezeli. Ha már rendelkezik ilyen AgentCard beállításjegyzékből beszerzett adatokval, konvertálja közvetlenül a AIAgentkövetkező beállításjegyzékbe:

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."));

Közvetlen konfiguráció

Olyan szorosan összekapcsolt rendszerekhez vagy fejlesztési forgatókönyvekhez, amelyekben az ügynökvégpont előre ismert, hozzon létre egy A2AClient közvetlent, és alakítsa át a következővé 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?"));

Protokoll kiválasztása

Az A2A-ügynökök több protokollkötést is elérhetővé tehetnek, például HTTP+JSON és JSON-RPC. Alapértelmezés szerint a HTTP+JSON előnyben részesíti a JSON-RPC-t. A protokollkötések explicit szabályozására szolgál A2AClientOptions.PreferredBindings :

Megjegyzés:

A távoli A2A-ügynöknek elérhetőnek kell lennie a kiválasztott protokollkötést támogató végponton.

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

Az A2A támogatja a streamelési válaszokat Server-Sent eseményeken keresztül. A frissítések valós idejű fogadására használható RunStreamingAsync , amikor a távoli ügynök feldolgozza a kérést:

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

Háttérválaszok

Az A2A-ügynökök támogatják a háttérválaszokat a hosszú ideig futó műveletek kezeléséhez. Ha egy távoli A2A-ügynök azonnali üzenet helyett egy feladatot ad vissza, az Ügynök-keretrendszer egy folytatási jogkivonatot biztosít, amellyel lekérdezheti az eredményeket, vagy újracsatlakozhat a megszakított streamekhez.

Lekérdezés a tevékenység befejezéséhez

Nem streamelési forgatókönyvek esetén a folytatási jogkivonat fogadásához és a lekérdezéshez használja AllowBackgroundResponses a feladat befejezéséig:

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

Stream újracsatlakoztatása

Streamelési forgatókönyvekben minden frissítés tartalmazhat egy folytatási jogkivonatot. Ha a stream megszakad, használja a jogkivonatot a válaszfolyam újracsatlakoztatásához és beszerzéséhez az elejétől kezdve:

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

Megjegyzés:

Az A2A-ügynökök támogatják a stream újracsatlakozását (az elejétől ugyanazt a válaszfolyamot szerzik be), nem pedig a stream egy adott pontjáról való újrakezdést.

Eszközök

A2AAgent egy átviteli szintű burkoló egy távoli A2A-ügynök körül. Bármilyen eszközt használ a távoli ügynök élőben a távoli oldalon, és láthatatlan a kód számára. Az Ügynök-keretrendszer eszköztípusai (függvényeszközök, kódértelmező, fájlkeresés, üzemeltetett/helyi MCP stb.) nincsenek önmagában A2AAgent konfigurálva – a távoli ügynök képességeinek kibővítéséhez módosítsa a távoli ügynök konfigurációját.

Első lépések

Telepítse az A2A-csomagot:

pip install agent-framework-a2a --pre

Inicializálás

A2AAgent háromféleképpen inicializálható attól függően, hogy mennyit tud a távoli ügynökről.

Közvetlen URL-cím

Olyan fejlesztéshez vagy szorosan összekapcsolt rendszerekhez, ahol a végpont ismert:

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)

Ha csak egy URL-címet ad meg, belsőleg létrehoz egy minimális ügynökkártyát, A2AAgent és JSON-RPC használatával csatlakozik.

Ügynökkártya

Ha egy beállításjegyzékből vagy katalógusból származó adatbázissal AgentCard rendelkezik, adja át közvetlenül:

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)

Ha meg AgentCard van adva, A2AAgent alapértelmezés szerint name és description a kártyáról. A kártya supported_interfaceshasználatával tárgyalja a szállítást.

Well-Known URI (A2ACardResolver)

Használja A2ACardResolver a a2a-sdk távoli ügynök felderítéséhez a szabványos jól ismert elérési úton (/.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

A frissítések valós idejű fogadására használható stream=True , amikor a távoli ügynök feldolgozza a kérést:

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))")

Hosszan tartó tevékenységek

Alapértelmezés szerint a A2AAgent megvárja, amíg a távoli ügynök befejezi a műveletet, még mielőtt visszatér. Hosszú ideig futó feladatok esetén állítsa be background=True , hogy egy folytatási jogkivonatot jelenítsen meg, amelyet később lekérdezhet vagy előfizethet:

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)

A lekérdezés helyett az SSE-streamre is újra lehet iratkozni:

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

Beszélgetési azonosító (context_id)

A2AAgent a tartós protokoll állapotát AgentSession.service_session_id leképezésként A2AServiceSessionId tárolja:

Field Típus Alkalmazás célja
context_id str Azonosítja az A2A-beszélgetést.
task_id str \| None Nyomon követi a legutóbbi távoli feladatot, amikor a válasz létrehozott egyet.
task_state TaskState \| None Rögzíti a legújabb tevékenységállapotot, hogy a következő kérés folytathassa a bemenethez szükséges tevékenységet, vagy hivatkozzon egy befejezett tevékenységre.

Hozzon létre strukturált állapotú munkamenetet, ha az alkalmazás már ismeri az A2A-környezetet:

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)

Az első válaszból AgentSession()A2AAgent kiindulva feltöltheti a strukturált leképezést is. A normál munkamenet session.to_dict() megőrzése és visszaállítása a következővel AgentSession.from_dict(...): az A2A-környezet, a tevékenységazonosító és a tevékenységállapot együtt marad.

Egy feladatnál a következő üzenet azt állítja TASK_STATE_INPUT_REQUIREDbe, hogy task_id ugyanazt a feladatot folytassa. Más tevékenységállapotok esetén a rendszer elküldi reference_task_ids az előző tevékenységazonosítót, hogy a távoli ügynök pontosíthassa vagy folytassa a korábbi eredményt.

Authentication

Használjon biztonságos AuthInterceptor A2A-végpontokat:

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!")

Időtúllépés konfigurálása

A2AAgent Egy paramétert timeout fogad el a kérések időtúllépéseinek szabályozásához:

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:
    ...

Ha nincs megadva időtúllépés, az alapértelmezett értékek a következők: 10s connect, 60s read, 10s write, 5s pool.

Eszközök

A2AAgent egy átviteli szintű burkoló egy távoli A2A-ügynök körül. Bármilyen eszközt használ a távoli ügynök élőben a távoli oldalon, és láthatatlan a kód számára. Az Ügynök-keretrendszer eszköztípusai (függvényeszközök, kódértelmező, fájlkeresés, üzemeltetett/helyi MCP stb.) nincsenek önmagában A2AAgent konfigurálva – a távoli ügynök képességeinek kibővítéséhez módosítsa a távoli ügynök konfigurációját.

Ha azt szeretné, hogy egy Foundry-ügynök eszközként meghívjon egy A2A-ügynököt, tekintse meg a get_a2a_tool gyári beállításokat FoundryChatClient.

A Go a csomagon keresztül támogatja a provider/a2aprovider távoli A2A-ügynököket.

Telepítse az Agent Framework és az A2A csomagokat:

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

Csatlakozás távoli A2A-ügynökhöz

Oldja fel a távoli ügynökkártyát, hozzon létre belőle egy A2A-ügyfelet, és csomagolja be az ügyfelet standard Ügynök-keretrendszer-ügynökként:

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()

A szolgáltató az A2A context_id - és feladatazonosítókat az Ügynök-keretrendszer munkamenetében tárolja, hogy a követő üzenetek megőrizzék a beszélgetés folytonosságát.

Protokoll kiválasztása

Ha egy távoli ügynök több átviteli kötést is meghirdet, az A2A-ügyfél létrehozásakor konfigurálja az előnyben részesített átvitelt:

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

Akkor használja a2a.TransportProtocolJSONRPC , ha a JSON-RPC-t szeretné előnyben részesíteni.

Hosszan futó feladatok

Az A2A-feladatok az Agent Framework folytatási tokenjein keresztül jelennek meg. Indítsa el a futtatást egy explicit munkamenettel és a(z) agent.AllowBackgroundResponses(true) használatával, majd lekérdezéssel kérdezze le az állapotot a(z) Run meghívásával új üzenetek nélkül és a folytatási tokennel:

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

Megszakított streaming futások esetén rögzítse az utoljára kapott frissítésből a(z) update.ContinuationToken értéket, majd adja át egy későbbi streaming futásnak a(z) agent.WithContinuationToken(token) és agent.Stream(true) használatával.

Távoli A2A-ügynökök használata eszközként

Oldja fel az egyes távoli ügynököket, csomagolja be a2aprovider.NewAgent, és alakítsa át egy eszközzé 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

A teljes futtatható példákhoz tekintse meg az A2A-szolgáltató mintáját és az A2A-ügynököket mintaként .

Következő lépések

Mélyedjen el: