Partilhar via


Integração A2A

O protocolo Agente-para-Agente (A2A) permite a comunicação padronizada entre agentes, permitindo que agentes construídos com diferentes estruturas e tecnologias comuniquem de forma fluida.

O que é A2A?

O A2A é um protocolo padronizado que suporta:

  • Descoberta de agentes através de cartões de agente
  • Comunicação baseada em mensagens entre agentes
  • Processos agentivos de longa duração através de tarefas
  • Interoperabilidade entre plataformas entre diferentes frameworks de agentes

Para mais informações, consulte a especificação do protocolo A2A.

A Microsoft.Agents.AI.Hosting.A2A.AspNetCore biblioteca fornece integração com o ASP.NET Core para expor agentes através do protocolo A2A.

Pacotes NuGet:

Example

Este exemplo mínimo mostra como expor um agente através de A2A. O exemplo inclui dependências do OpenAPI e do Swagger para simplificar os testes.

1. Criar um projeto ASP.NET Core Web API

Crie um novo projeto ASP.NET Core Web API ou use um já existente.

2. Instalar as dependências necessárias

Instale os seguintes pacotes:

Execute os seguintes comandos no diretório do seu projeto para instalar os pacotes NuGet necessários:

# 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. Configurar a ligação Azure OpenAI

A aplicação requer uma ligação Azure OpenAI. Configura o endpoint e o nome da implementação usando dotnet user-secrets ou variáveis de ambiente. Também podes simplesmente editar o appsettings.json, mas isso não é recomendado para as aplicações implementadas em produção, pois alguns dados podem ser considerados secretos.

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. Adicionar o código à Program.cs

Substitua o conteúdo de Program.cs pelo seguinte código e execute a aplicação:

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

Testar o Agente

Depois de a aplicação estar a correr, pode testar o agente A2A usando o ficheiro seguinte .http ou através da interface Swagger.

O formato de entrada cumpre a especificação A2A. Pode fornecer valores para:

  • messageId - Um identificador único para esta mensagem específica. Podes criar o teu próprio ID (por exemplo, um GUID) ou defini-lo para null que o agente gere um automaticamente.
  • contextId - O identificador da conversa. Forneça o seu próprio ID para iniciar uma nova conversa ou continue uma existente reutilizando uma anterior contextId. O agente irá manter o histórico de conversas para o mesmo contextId. O agente também gerará um para si, se não for fornecido nenhum.
# 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"
  }
}

Nota: Substitua {{baseAddress}} pelo endpoint do seu servidor.

Este pedido devolve a seguinte resposta JSON:

{
	"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"
}

A resposta inclui o contextId (identificador da conversa), messageId (identificador da mensagem) e o conteúdo real do agente pirata.

Configuração do AgentCard

O AgentCard fornece metadados sobre o seu agente para descoberta e integração.

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

Pode aceder ao cartão de agente enviando este pedido:

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

Nota: Substitua {{baseAddress}} pelo endpoint do seu servidor.

Propriedades AgentCard

  • Nome: Nome de exibição do agente
  • Descrição: Breve descrição do agente
  • Versão: String de versão para o agente
  • URL: URL do endpoint (atribuído automaticamente se não especificado)
  • Capacidades: Metadados opcionais sobre streaming, notificações push e outras funcionalidades

Exposição de Múltiplos Agentes

Podes expor vários agentes numa única aplicação, desde que os seus endpoints não colidam. Eis um exemplo:

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

O agent-framework-a2a pacote permite-lhe ligar-se e comunicar com agentes externos compatíveis com a A2A.

pip install agent-framework-a2a --pre

Ligação a um Agente A2A

Utilize A2AAgent para envolver qualquer endpoint A2A remoto. O agente resolve as capacidades do agente remoto através do seu AgentCard e trata de todos os detalhes do protocolo.

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

Respostas de streaming

O A2A suporta naturalmente streaming através de Eventos Enviados pelo Servidor — as atualizações chegam em tempo real enquanto o agente remoto trabalha.

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

Tarefas de Longa Duração

Por defeito, A2AAgent espera que o agente remoto termine antes de regressar. Para tarefas de longa duração, defina background=True para obter um token de continuação que pode usar para consultar ou subscrever novamente mais tarde:

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)

Authentication

Use um AuthInterceptor para endpoints A2A seguros:

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

Ver também

Próximos passos