Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions dotnet/samples/A2AClientServer/A2AServer/A2AServer.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -9,14 +9,16 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="A2A.AspNetCore" />
<PackageReference Include="Azure.AI.Agents.Persistent" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Hosting.A2A.AspNetCore\Microsoft.Agents.AI.Hosting.A2A.AspNetCore.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Hosting.A2A\Microsoft.Agents.AI.Hosting.A2A.csproj" />

<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.A2A\Microsoft.Agents.AI.A2A.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
Expand Down
9 changes: 4 additions & 5 deletions dotnet/samples/A2AClientServer/A2AServer/HostAgentFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
using Azure.AI.Agents.Persistent;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.A2A;
using Microsoft.Extensions.AI;
using OpenAI;

namespace A2AServer;

internal static class HostAgentFactory
{
internal static async Task<A2AHostAgent> CreateFoundryHostAgentAsync(string agentType, string model, string endpoint, string assistantId, IList<AITool>? tools = null)
internal static async Task<(AIAgent, AgentCard)> CreateFoundryHostAgentAsync(string agentType, string model, string endpoint, string assistantId, IList<AITool>? tools = null)
{
var persistentAgentsClient = new PersistentAgentsClient(endpoint, new AzureCliCredential());
PersistentAgent persistentAgent = await persistentAgentsClient.Administration.GetAgentAsync(assistantId);
Expand All @@ -28,10 +27,10 @@ internal static async Task<A2AHostAgent> CreateFoundryHostAgentAsync(string agen
_ => throw new ArgumentException($"Unsupported agent type: {agentType}"),
};

return new A2AHostAgent(agent, agentCard);
return new(agent, agentCard);
}

internal static async Task<A2AHostAgent> CreateChatCompletionHostAgentAsync(string agentType, string model, string apiKey, string name, string instructions, IList<AITool>? tools = null)
internal static async Task<(AIAgent, AgentCard)> CreateChatCompletionHostAgentAsync(string agentType, string model, string apiKey, string name, string instructions, IList<AITool>? tools = null)
{
AIAgent agent = new OpenAIClient(apiKey)
.GetChatClient(model)
Expand All @@ -45,7 +44,7 @@ internal static async Task<A2AHostAgent> CreateChatCompletionHostAgentAsync(stri
_ => throw new ArgumentException($"Unsupported agent type: {agentType}"),
};

return new A2AHostAgent(agent, agentCard);
return new(agent, agentCard);
}

#region private
Expand Down
14 changes: 8 additions & 6 deletions dotnet/samples/A2AClientServer/A2AServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using A2A;
using A2A.AspNetCore;
using A2AServer;
using Microsoft.Agents.AI.A2A;
using Microsoft.Agents.AI;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
Expand Down Expand Up @@ -47,10 +47,12 @@
AIFunctionFactory.Create(invoiceQueryPlugin.QueryByInvoiceId)
];

A2AHostAgent? hostAgent = null;
AIAgent hostA2AAgent;
AgentCard hostA2AAgentCard;

if (!string.IsNullOrEmpty(endpoint) && !string.IsNullOrEmpty(agentId))
{
hostAgent = agentType.ToUpperInvariant() switch
(hostA2AAgent, hostA2AAgentCard) = agentType.ToUpperInvariant() switch
{
"INVOICE" => await HostAgentFactory.CreateFoundryHostAgentAsync(agentType, model, endpoint, agentId, tools),
"POLICY" => await HostAgentFactory.CreateFoundryHostAgentAsync(agentType, model, endpoint, agentId),
Expand All @@ -60,7 +62,7 @@
}
else if (!string.IsNullOrEmpty(apiKey))
{
hostAgent = agentType.ToUpperInvariant() switch
(hostA2AAgent, hostA2AAgentCard) = agentType.ToUpperInvariant() switch
{
"INVOICE" => await HostAgentFactory.CreateChatCompletionHostAgentAsync(
agentType, model, apiKey, "InvoiceAgent",
Expand Down Expand Up @@ -102,7 +104,7 @@ You specialize in handling queries related to logistics.
throw new ArgumentException("Either A2AServer:ApiKey or A2AServer:ConnectionString & agentId must be provided");
}

app.MapA2A(hostAgent!.TaskManager!, "/");
app.MapWellKnownAgentCard(hostAgent!.TaskManager!, "/");
var a2aTaskManager = app.MapA2A(hostA2AAgent, path: "/", agentCard: hostA2AAgentCard);
app.MapWellKnownAgentCard(a2aTaskManager, "/");

await app.RunAsync();
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using AgentWebChat.AgentHost.Utilities;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI.Hosting.A2A.AspNetCore;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;

Expand Down
113 changes: 0 additions & 113 deletions dotnet/src/Microsoft.Agents.AI.A2A/A2AHostAgent.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) Microsoft. All rights reserved.

using A2A;
using A2A.AspNetCore;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.A2A;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Microsoft.AspNetCore.Builder;

/// <summary>
/// Provides extension methods for configuring A2A (Agent2Agent) communication in a host application builder.
/// </summary>
public static class MicrosoftAgentAIHostingA2AEndpointRouteBuilderExtensions
{
/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentName">The name of the agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static ITaskManager MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path)
{
var agent = endpoints.ServiceProvider.GetRequiredKeyedService<AIAgent>(agentName);
return endpoints.MapA2A(agent, path);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentName">The name of the agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
/// <remarks>
/// This method can be used to access A2A agents that support the
/// <see href="https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#2-curated-registries-catalog-based-discovery">Curated Registries (Catalog-Based Discovery)</see>
/// discovery mechanism.
/// </remarks>
public static ITaskManager MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentCard agentCard)
{
var agent = endpoints.ServiceProvider.GetRequiredKeyedService<AIAgent>(agentName);
return endpoints.MapA2A(agent, path, agentCard);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static ITaskManager MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path)
{
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
var taskManager = agent.MapA2A(loggerFactory: loggerFactory);
return endpoints.MapA2A(taskManager, path);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
/// <remarks>
/// This method can be used to access A2A agents that support the
/// <see href="https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#2-curated-registries-catalog-based-discovery">Curated Registries (Catalog-Based Discovery)</see>
/// discovery mechanism.
/// </remarks>
public static ITaskManager MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentCard agentCard)
{
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
var taskManager = agent.MapA2A(agentCard: agentCard, loggerFactory: loggerFactory);
return endpoints.MapA2A(taskManager, path);
}

/// <summary>
/// Maps HTTP A2A communication endpoints to the specified path using the provided TaskManager.
/// TaskManager should be preconfigured before calling this method.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="taskManager">Pre-configured A2A TaskManager to use for A2A endpoints handling.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static ITaskManager MapA2A(this IEndpointRouteBuilder endpoints, TaskManager taskManager, string path)
{
// note: current SDK version registers multiple `.well-known/agent.json` handlers here.
// it makes app return HTTP 500, but will be fixed once new A2A SDK is released.
// see https://github.com/microsoft/agent-framework/issues/476 for details
A2ARouteBuilderExtensions.MapA2A(endpoints, taskManager, path);
endpoints.MapHttpA2A(taskManager, path);

return taskManager;
}
}

This file was deleted.

Loading
Loading