Агенты узлов с A2A

Протокол a Agent to-Agent (A2A) обеспечивает стандартизованную связь между агентами, созданными с различными платформами и технологиями. На этой странице описывается предоставление агентов Agent Framework в качестве серверов A2A.

Сведения об обнаружении и вызове удаленного агента A2A см. в службе агента A2A.

Что такое A2A?

A2A — это стандартизованный протокол, поддерживающий:

  • Обнаружение агента с помощью карточек агента
  • Обмен данными между агентами на основе сообщений
  • Длительные агентические процессы с помощью задач
  • Кроссплатформенная взаимодействие между разными платформами агентов

Дополнительные сведения см. в спецификации протокола A2A.

Библиотека Microsoft.Agents.AI.Hosting.A2A.AspNetCore предоставляет интеграцию ASP.NET Core для представления агентов через протокол A2A.

Пакеты NuGet:

Example

В этом минимальном примере показано, как сделать агента доступным через A2A. Пример включает зависимости OpenAPI и Swagger для упрощения тестирования.

1. Создание проекта веб-API ASP.NET Core

Создайте проект веб-API ASP.NET Core или используйте существующий.

2. Установка необходимых зависимостей

Установите следующие пакеты:

Выполните следующие команды в каталоге проекта, чтобы установить необходимые пакеты NuGet:

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

# Libraries to connect to Microsoft Foundry
dotnet add package Azure.AI.Projects --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Agents.AI.Foundry --prerelease

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

3. Настройка подключения Microsoft Foundry

Приложению требуется подключение проекта Microsoft Foundry. Настройте конечную точку и имя развертывания, используя dotnet user-secrets или переменные окружения. Вы также можете просто изменить appsettings.jsonфайл, но это не рекомендуется для приложений, развернутых в рабочей среде, так как некоторые данные могут считаться секретами.

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. Добавление кода в Program.cs

Замените содержимое Program.cs следующим кодом и запустите приложение:

using A2A.AspNetCore;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
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 AIProjectClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
        .GetProjectOpenAIClient()
        .GetProjectResponsesClient()
        .AsIChatClient(deploymentName);

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

Предупреждение

DefaultAzureCredential удобно для разработки, но требует тщательного рассмотрения в рабочей среде. В рабочей среде рекомендуется использовать определенные учетные данные (например, ManagedIdentityCredential), чтобы избежать проблем с задержкой, непреднамеренной проверки данных аутентификации и потенциальных рисков безопасности из-за резервных механизмов.

Тестирование агента

После запуска приложения можно протестировать агент A2A с помощью следующего .http файла или пользовательского интерфейса Swagger.

Входной формат соответствует спецификации A2A. Можно указать значения для:

  • messageId — уникальный идентификатор для этого конкретного сообщения. Вы можете создать собственный идентификатор (например, GUID) или установить null, чтобы агент сгенерировал его автоматически.
  • contextId — идентификатор беседы. Укажите собственный идентификатор, чтобы начать новую беседу или продолжить существующую, повторно выполнив предыдущий contextId. Агент будет поддерживать журнал бесед для одного и того же contextId. Агент также создаст один для вас, если он не указан.
# 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"
  }
}

Примечание. Замените {{baseAddress}} конечной точкой сервера.

Этот запрос возвращает следующий ответ 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"
}

Ответ включает contextId (идентификатор беседы), messageId (идентификатор сообщения) и реальное содержимое пиратского агента.

Конфигурация AgentCard

Этот элемент AgentCard предоставляет метаданные агента для его обнаружения и интеграции.

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

Вы можете получить доступ к карточке агента, отправив этот запрос:

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

Примечание. Замените {{baseAddress}} конечной точкой сервера.

Свойства AgentCard

  • Имя: отображаемое имя агента
  • Описание: краткое описание агента
  • Версия: строка версии агента
  • URL-адрес: URL-адрес конечной точки (автоматически назначается, если он не указан)
  • Возможности: необязательные метаданные о потоковой передаче, push-уведомлениях и других функциях

Выявление нескольких агентов

Вы можете размещать несколько агентов в одном приложении, пока их конечные точки не конфликтуют. Приведем пример:

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

Пакет agent-framework-a2a предоставляет агент Agent Framework через протокол A2A.

pip install agent-framework-a2a --pre

Тестирование защищенной конечной точки

Используйте тестовый AuthInterceptor клиент для проверки защищенной конечной точки A2A:

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

Публикация агента Agent Framework через A2A

Пакет agent-framework-a2a предоставляет готовый A2AExecutor, который адаптирует любого агента платформы Agent Framework к серверному протоколу A2A. Он запускает агент, сопоставляет поддерживаемое выходное содержимое с событиями и артефактами A2A, а также управляет обновлениями состояния задачи с помощью официального a2a-sdk.

Ваше приложение объединяет компоненты вокруг сервера A2A SDK: карточку агента, DefaultRequestHandlerхранилище задач, маршруты или конструктор приложений, аутентификацию и развертывание. Сравнение с адаптерами, принадлежащими приложению, и вспомогательными помощниками по автономному преобразованию см. в agent-framework-hosting-a2aразделе " Агенты A2A для самообслуживания".

import uvicorn
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill
from agent_framework import Agent
from agent_framework.a2a import A2AExecutor
from agent_framework.openai import OpenAIChatClient
from starlette.applications import Starlette

flight_skill = AgentSkill(
    id="Flight_Booking",
    name="Flight Booking",
    description="Search and book flights across Europe.",
    tags=["flights", "travel", "europe"],
    examples=[],
)

public_agent_card = AgentCard(
    name="Europe Travel Agent",
    description="Helps users search and book flights and hotels across Europe.",
    version="1.0.0",
    default_input_modes=["text"],
    default_output_modes=["text"],
    capabilities=AgentCapabilities(streaming=True),
    supported_interfaces=[
        AgentInterface(url="http://localhost:9999/", protocol_binding="JSONRPC"),
    ],
    skills=[flight_skill],
)

agent = Agent(
    client=OpenAIChatClient(),
    name="Europe Travel Agent",
    instructions="You are a helpful Europe Travel Agent.",
)

request_handler = DefaultRequestHandler(
    agent_executor=A2AExecutor(agent, stream=True),
    task_store=InMemoryTaskStore(),
    agent_card=public_agent_card,
)

server = Starlette(
    routes=[
        *create_agent_card_routes(public_agent_card),
        *create_jsonrpc_routes(request_handler, "/"),
    ]
)

uvicorn.run(server, host="0.0.0.0", port=9999)

A2AExecutor передаёт обновления агента в потоковом режиме в виде артефактов A2A, когда базовый агент поддерживает потоковую передачу и передаёт A2A context_id в качестве session_id сеанса агента. Можно создать подкласс на основе A2AExecutor и переопределить метод handle_events, чтобы реализовать пользовательские преобразования из формата выходных данных агента в события протокола A2A.

Протокол A2A

Платформа агента Go поддерживает размещение агентов agent Framework через протокол "агент — агент" (A2A) с provider/a2aprovider пакетом и официальными обработчиками сервера A2A Go.

Установите пакеты Agent Framework и A2A в модуле Go:

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

Размещение агента через A2A

Создайте или используйте повторно агент в Agent Framework, опишите его с помощью карточки агента A2A и опубликуйте его через одну из транспортных привязок A2A. В этом примере hostAgent используется любая платформа *agent.Agentагента; сервер размещает конечную точку JSON-RPC и / обслуживает карточку агента по известному пути A2A.

import (
    "fmt"
    "net/http"

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

url := "http://localhost:5000"

card := &a2a.AgentCard{
    Name:               "InvoiceAgent",
    Description:        "Handles requests relating to invoices.",
    Version:            "1.0.0",
    DefaultInputModes:  []string{"text"},
    DefaultOutputModes: []string{"text"},
    Capabilities: a2a.AgentCapabilities{
        Streaming: false,
    },
    SupportedInterfaces: []*a2a.AgentInterface{
        a2a.NewAgentInterface(url, a2a.TransportProtocolJSONRPC),
    },
}

mux := http.NewServeMux()
requestHandler := a2asrv.NewHandler(
    a2aprovider.NewExecutor(hostAgent, a2aprovider.ExecutorConfig{}),
    a2asrv.WithExtendedAgentCard(card),
)
mux.Handle("/", a2asrv.NewJSONRPCHandler(requestHandler))
mux.Handle(a2asrv.WellKnownAgentCardPath, a2asrv.NewStaticAgentCardHandler(card))

if err := http.ListenAndServe(":5000", mux); err != nil {
    panic(fmt.Errorf("A2A server failed: %w", err))
}

Оберните тот же обработчик запросов с помощью a2asrv.NewRESTHandler, если хотите предоставить привязку транспорта HTTP+JSON. Установите для ExecutorConfig.AllowBackgroundResponses значение true, если размещаемому агенту должно быть разрешено возвращать задачи A2A для длительно выполняемой работы.

См. также

Дальнейшие действия