A2A Tümleştirmesi

Aracıdan Aracıya (A2A) protokolü aracılar arasında standartlaştırılmış iletişime olanak tanıyarak farklı çerçeveler ve teknolojilerle oluşturulmuş aracıların sorunsuz bir şekilde iletişim kurmasına olanak tanır.

A2A nedir?

A2A, şu desteği sağlayan standartlaştırılmış bir protokoldür:

  • Aracı kartları aracılığıyla aracı bulma
  • Aracılar arasında ileti tabanlı iletişim
  • Görevler aracılığıyla uzun süreli etken süreçler
  • Farklı ajan çerçeveleri arasında platformlar arası birlikte çalışabilirlik

Daha fazla bilgi için bkz. A2A protokol belirtimi.

Kitaplık, Microsoft.Agents.AI.Hosting.A2A.AspNetCore A2A protokolü aracılığıyla aracılarınızı kullanıma sunmak için ASP.NET Core tümleştirmesi sağlar.

NuGet Paketleri:

Example

Bu basit örnek, A2A aracılığıyla bir aracıyı nasıl kullanıma sunacağınızı gösterir. Örnek, testi basitleştirmek için OpenAPI ve Swagger bağımlılıklarını içerir.

1. ASP.NET Core Web API projesi oluşturma

Yeni bir ASP.NET Core Web API projesi oluşturun veya var olan bir projeyi kullanın.

2. Gerekli bağımlılıkları yükleme

Aşağıdaki paketleri yükleyin:

Gerekli NuGet paketlerini yüklemek için proje dizininizde aşağıdaki komutları çalıştırın:

# 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 bağlantısını yapılandırma

Uygulama bir Microsoft Foundry proje bağlantısı gerektirir. veya ortam değişkenlerini kullanarak dotnet user-secrets uç nokta ve dağıtım adını yapılandırın. Ayrıca, yalnızca öğesini düzenleyebilirsiniz appsettings.json, ancak verilerin bir kısmı gizli olarak değerlendirilebileceği için üretimde dağıtılan uygulamalar için bu önerilmez.

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. Kodu Program.cs'ye ekleyin

öğesinin içeriğini Program.cs aşağıdaki kodla değiştirin ve uygulamayı çalıştırın:

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

Uyarı

DefaultAzureCredential geliştirme için uygundur ancak üretimde dikkatli bir şekilde dikkate alınması gerekir. Üretimde gecikme sorunları, istenmeyen kimlik bilgisi yoklama ve geri dönüş mekanizmalarından kaynaklanan olası güvenlik risklerini önlemek için belirli bir kimlik bilgisi (ör ManagedIdentityCredential. ) kullanmayı göz önünde bulundurun.

Aracıyı Test Etme

Uygulama çalıştırıldıktan sonra aşağıdaki .http dosyayı kullanarak veya Swagger kullanıcı arabirimi aracılığıyla A2A aracısını test edebilirsiniz.

Giriş biçimi A2A belirtimiyle uyumlu. Aşağıdakiler için değerler sağlayabilirsiniz:

  • messageId - Bu özel ileti için benzersiz bir tanımlayıcı. Kendi kimliğinizi (örneğin, GUID) oluşturabilir veya null ayarlayarak aracının otomatik olarak bir kimlik oluşturmasına izin verebilirsiniz.
  • contextId - Konuşma tanımlayıcısı. Yeni bir konuşma başlatmak için kendi kimliğinizi belirtin veya önceki contextIdbir öğesini yeniden kullanarak var olan bir konuşmaya devam edin. Aracı, aynı contextId için konuşma geçmişini korur. Ajan, sağlanmadıysa sizin için de bir tane oluşturur.
# 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"
  }
}

Not: {{baseAddress}} ile sunucu uç noktanızı değiştirin.

Bu istek aşağıdaki JSON yanıtını döndürür:

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

Yanıtta contextId (konuşma tanımlayıcısı), messageId (ileti tanımlayıcısı) ve korsan ajanının gerçek içeriği yer alır.

AgentCard Yapılandırması

aracınız AgentCard hakkında bulma ve tümleştirme için meta veriler sağlar:

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

Aracı kartına şu isteği göndererek erişebilirsiniz:

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

Not: {{baseAddress}} ile sunucu uç noktanızı değiştirin.

AgentCard Özellikleri

  • Ad: Aracının görünen adı
  • Açıklama: Temsilcinin kısa açıklaması
  • Sürüm: Ajan için sürüm dizesi
  • Url: Uç nokta URL'si (belirtilmezse otomatik olarak atanır)
  • Özellikler: Akış, anında iletme bildirimleri ve diğer özellikler hakkında isteğe bağlı meta veriler

Birden Çok Aracıyı Açığa Çıkarma

Birbirleriyle çakışmadıkları sürece, tek bir uygulamada birden fazla aracı kullanıma sunabilirsiniz. Bir örnek aşağıda verilmiştir:

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

Paket, agent-framework-a2a hem dış A2A uyumlu aracılara bağlanmanızı hem de A2A protokolü üzerinden bir Agent Framework aracısını kullanıma sunmanızı sağlar.

pip install agent-framework-a2a --pre

A2A Aracısı'na bağlanma

Uzak A2A uç noktalarını sarmak için A2AAgent'yi kullanın. Aracı, uzak aracının özelliklerini AgentCard aracılığıyla çözer ve tüm protokol ayrıntılarını işler.

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

Akış Yanıtları

A2A doğal olarak Sunucu-Gönderimli Olaylar aracılığıyla akış desteği sunar. Uzak aracı çalıştığında güncellemeler gerçek zamanlı olarak gelir.

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

Uzun Süreli Görevler

Varsayılan olarak A2AAgent, geri dönmeden önce uzak aracı bitene kadar bekler. Uzun süreli görevler için, daha sonra yoklama yapabilmek veya yeniden abone olabilmek amacıyla kullanabileceğiniz bir devam belirtecini almak için background=True ile ayarlayın:

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)

Konuşma Kimliği (context_id)

A2AAgent.run() ajansını bir AgentSession ile çağırdığınızda, eğer giden ileti zaten bir tane taşımıyorsa, ajan otomatik olarak session.service_session_id'dan A2A context_id türetir. Bu özellik, her iletiyi manuel olarak ayarlamadan birden fazla A2A çağrısında konuşmanın sürekliliğini korumanıza olanak tanır:

from agent_framework import AgentSession
from agent_framework.a2a import A2AAgent

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

    # context_id is automatically set to "my-conversation-1"
    response = await agent.run("Hello!", session=session)

    # Subsequent calls with the same session continue the conversation
    response = await agent.run("Follow-up question", session=session)

bir iletinin içinde context_idaçık additional_properties bir değer varsa, bu değer oturumdan türetilen geri dönüşten önceliklidir.

Authentication

Güvenli A2A uç noktaları için bir AuthInterceptor kullanın:

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

A2A üzerinden Bir Agent Framework Aracısını Ortaya Çıkarma

, A2AExecutor herhangi bir Aracı Çerçevesini Agent A2A sunucu tarafı protokolüne uyarlar. Diğer A2A istemcilerinin temsilcinizi bulabilmesi ve çağırabilmesi için resmi a2a-sdk Starlette/ASGI sunucusuyla barındırabilirsiniz.

import uvicorn
from a2a.server.apps import A2AStarletteApplication
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
from agent_framework import Agent
from agent_framework.a2a import A2AExecutor
from agent_framework.openai import OpenAIChatClient

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.",
    url="http://localhost:9999/",
    version="1.0.0",
    defaultInputModes=["text"],
    defaultOutputModes=["text"],
    capabilities=AgentCapabilities(streaming=True),
    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),
    task_store=InMemoryTaskStore(),
)

server = A2AStarletteApplication(
    agent_card=public_agent_card,
    http_handler=request_handler,
).build()

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

A2AExecutor Akış aracısı, altında yatan aracının akışı desteklemesi durumunda A2A yapıtları olarak güncelleştirilir, A2A'yı aracının context_id'si olarak yayar ve kalıcı iş parçacığı depolaması için geçersiz kılabileceğiniz kancaları thread_idsave_thread/ kullanıma sunar.

Tip

Tam bir çalıştırılabilir örnek için örneğe bakın.agent_framework_to_a2a.py

Ayrıca Bkz.

Sonraki Adımlar