Freigeben über


A2A-Integration

Das Agent-to-Agent-Protokoll (A2A) ermöglicht eine standardisierte Kommunikation zwischen Agents, sodass Agents, die mit verschiedenen Frameworks und Technologien erstellt wurden, nahtlos kommunizieren können.

Was ist A2A?

A2A ist ein standardisiertes Protokoll, das Folgendes unterstützt:

  • Agent-Ermittlung über Agentkarten
  • Nachrichtenbasierte Kommunikation zwischen Agents
  • Langfristige agentische Prozesse über Aufgaben
  • Plattformübergreifende Interoperabilität zwischen verschiedenen Agent-Frameworks

Weitere Informationen finden Sie in der A2A-Protokollspezifikation.

Die Microsoft.Agents.AI.Hosting.A2A.AspNetCore Bibliothek bietet ASP.NET Core-Integration zum Verfügbarmachen Ihrer Agents über das A2A-Protokoll.

NuGet-Pakete:

Example

Dieses minimale Beispiel zeigt, wie ein Agent über A2A verfügbar gemacht wird. Das Beispiel enthält OpenAPI- und Swagger-Abhängigkeiten, um tests zu vereinfachen.

1. Erstellen eines ASP.NET Core Web API-Projekts

Erstellen Sie ein neues ASP.NET Core Web API-Projekt, oder verwenden Sie ein vorhandenes.

2. Installieren erforderlicher Abhängigkeiten

Installieren Sie die folgenden Pakete:

Führen Sie die folgenden Befehle in Ihrem Projektverzeichnis aus, um die erforderlichen NuGet-Pakete zu installieren:

# Hosting.A2A.AspNetCore for A2A protocol integration
dotnet add package Microsoft.Agents.AI.Hosting.A2A.AspNetCore --prerelease

# Libraries to connect to Azure OpenAI
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease

# Swagger to test app
dotnet add package Microsoft.AspNetCore.OpenApi
dotnet add package Swashbuckle.AspNetCore

3. Konfigurieren der Azure OpenAI-Verbindung

Die Anwendung erfordert eine Azure OpenAI-Verbindung. Konfigurieren Sie den Endpunkt und den Bereitstellungsnamen mithilfe von dotnet user-secrets oder Umgebungsvariablen. Sie können auch einfach die appsettings.json bearbeiten, jedoch wird dies für Apps, die in der Produktion bereitgestellt werden, nicht empfohlen, da einige der Daten als geheim eingestuft werden können.

dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" "https://<your-openai-resource>.openai.azure.com/"
dotnet user-secrets set "AZURE_OPENAI_DEPLOYMENT_NAME" "gpt-4o-mini"

4. Hinzufügen des Codes zu Program.cs

Ersetzen Sie den Inhalt von Program.cs durch den folgenden Code, und führen Sie die Anwendung aus.

using A2A.AspNetCore;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();
builder.Services.AddSingleton(chatClient);

// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via A2A protocol. You can also customize the agentCard
app.MapA2A(pirateAgent, path: "/a2a/pirate", agentCard: new()
{
    Name = "Pirate Agent",
    Description = "An agent that speaks like a pirate.",
    Version = "1.0"
});

app.Run();

Testen des Agents

Sobald die Anwendung ausgeführt wird, können Sie den A2A-Agent mit der folgenden .http Datei oder über die Swagger-Benutzeroberfläche testen.

Das Eingabeformat entspricht der A2A-Spezifikation. Sie können Werte für Folgendes angeben:

  • messageId – Ein eindeutiger Bezeichner für diese bestimmte Nachricht. Sie können Ihre eigene ID (z. B. eine GUID) erstellen oder sie auf null setzen, damit der Agent automatisch eine ID generiert.
  • contextId - Die Gesprächs-ID. Geben Sie Ihre eigene ID an, um eine neue Unterhaltung zu beginnen, oder um eine vorhandene Unterhaltung fortzusetzen, indem Sie eine vorige ID wieder contextId. Der Agent wird den Gesprächsverlauf für denselben contextId verwalten. Der Agent generiert auch eine für Sie, wenn keine bereitgestellt wird.
# Send A2A request to the pirate agent
POST {{baseAddress}}/a2a/pirate/v1/message:stream
Content-Type: application/json
{
  "message": {
    "kind": "message",
    "role": "user",
    "parts": [
      {
        "kind": "text",
        "text": "Hey pirate! Tell me where have you been",
        "metadata": {}
      }
    ],
	"messageId": null,
    "contextId": "foo"
  }
}

Hinweis: Ersetzen Sie den Serverendpunkt {{baseAddress}} durch Ihren Serverendpunkt.

Diese Anforderung gibt die folgende JSON-Antwort zurück:

{
	"kind": "message",
	"role": "agent",
	"parts": [
		{
			"kind": "text",
			"text": "Arrr, ye scallywag! Ye’ll have to tell me what yer after, or be I walkin’ the plank? 🏴‍☠️"
		}
	],
	"messageId": "chatcmpl-CXtJbisgIJCg36Z44U16etngjAKRk",
	"contextId": "foo"
}

Die Antwort enthält den contextId (Unterhaltungsbezeichner), messageId (Nachrichtenbezeichner) und den tatsächlichen Inhalt des Piraten-Agents.

AgentCard-Konfiguration

Dies AgentCard stellt Metadaten zu Ihrem Agent für die Ermittlung und Integration bereit:

app.MapA2A(agent, "/a2a/my-agent", agentCard: new()
{
    Name = "My Agent",
    Description = "A helpful agent that assists with tasks.",
    Version = "1.0",
});

Sie können auf die Agent-Karte zugreifen, indem Sie diese Anforderung senden:

# Send A2A request to the pirate agent
GET {{baseAddress}}/a2a/pirate/v1/card

Hinweis: Ersetzen Sie den Serverendpunkt {{baseAddress}} durch Ihren Serverendpunkt.

AgentCard-Eigenschaften

  • Name: Anzeigename des Agents
  • Beschreibung: Kurze Beschreibung des Agenten
  • Version: Versionszeichenfolge für den Agent
  • URL: Endpunkt-URL (automatisch zugewiesen, wenn nicht angegeben)
  • Funktionen: Optionale Metadaten zu Streaming, Pushbenachrichtigungen und anderen Features

Offenlegung mehrerer Agenten

Sie können mehrere Agents in einer einzigen Anwendung verfügbar machen, solange ihre Endpunkte nicht kollidieren. Ein Beispiel:

var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");

app.MapA2A(mathAgent, "/a2a/math");
app.MapA2A(scienceAgent, "/a2a/science");

Mit dem agent-framework-a2a Paket können Sie eine Verbindung mit externen A2A-kompatiblen Agents herstellen und mit diesen kommunizieren.

pip install agent-framework-a2a --pre

Herstellen einer Verbindung mit einem A2A-Agent

Verwenden Sie A2AAgent, um einen beliebigen A2A-Remoteendpunkt zu umschließen. Der Agent löst die Funktionen des Remote-Agents über seine AgentCard auf und verarbeitet alle Protokolldetails.

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

async def main():
    a2a_host = "https://your-a2a-agent.example.com"

    # 1. Discover the remote agent's capabilities
    async with httpx.AsyncClient(timeout=60.0) as http_client:
        resolver = A2ACardResolver(httpx_client=http_client, base_url=a2a_host)
        agent_card = await resolver.get_agent_card()
        print(f"Found agent: {agent_card.name}")

    # 2. Create an A2AAgent and send a message
    async with A2AAgent(
        name=agent_card.name,
        agent_card=agent_card,
        url=a2a_host,
    ) as agent:
        response = await agent.run("What are your capabilities?")
        for message in response.messages:
            print(message.text)

asyncio.run(main())

Streaming-Antworten

A2A unterstützt natürlich streaming über Server-Sent Events – Updates kommen in Echtzeit an, während der Remote-Agent funktioniert:

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    async with agent.run("Tell me about yourself", stream=True) as stream:
        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))")

Lang laufende Aufgaben

Standardmäßig wartet A2AAgent darauf, dass der Remote-Agent beendet ist, bevor er zurückkehrt. Für langfristige Aufgaben setzen Sie background=True ein, um ein Fortsetzungstoken zu erhalten, das Sie verwenden können, um später eine Abfrage durchzuführen oder das Abonnement zu erneuern.

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)

Authentifizierung

Verwenden Sie eine AuthInterceptor für gesicherte A2A-Endpunkte:

from a2a.client.auth.interceptor import AuthInterceptor

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

Siehe auch

Nächste Schritte