Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Протокол "агент — агент" (A2A) позволяет стандартизированной связи между агентами, позволяя агентам, созданным с различными платформами и технологиями, легко взаимодействовать.
Что такое A2A?
A2A — это стандартизованный протокол, поддерживающий:
- Обнаружение агента с помощью карточек агента
- Обмен данными между агентами на основе сообщений
- Длительные агентические процессы с помощью задач
- Кроссплатформенная взаимодействие между разными платформами агентов
Дополнительные сведения см. в спецификации протокола A2A.
Библиотека Microsoft.Agents.AI.Hosting.A2A.AspNetCore предоставляет интеграцию ASP.NET Core для представления агентов через протокол A2A.
Пакеты NuGet:
Пример
В этом минимальном примере показано, как сделать агента доступным через 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 позволяет подключаться и взаимодействовать с внешними агентами, совместимыми с A2A.
pip install agent-framework-a2a --pre
Подключение к агенту A2A
Упакуйте любую удаленную конечную точку A2A с помощью A2AAgent. Агент определяет возможности удаленного агента через AgentCard и обрабатывает все детали протокола.
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())
Ответы потоковые
A2A естественно поддерживает потоковую трансляцию через события, отправляемые сервером (Server-Sent Events) — обновления поступают в режиме реального времени по мере выполнения удалённым агентом задач.
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))")
длительные задачи
По умолчанию A2AAgent ожидает завершения удаленного агента перед возвратом. Для длительных задач используйте background=True для получения маркера продолжения, который можно использовать для опроса или повторной подписки в будущем.
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
Используйте 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!")