diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/AGUIEndpointRouteBuilderExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/AGUIEndpointRouteBuilderExtensions.cs
index 348d4a866..04437c418 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/AGUIEndpointRouteBuilderExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/AGUIEndpointRouteBuilderExtensions.cs
@@ -32,6 +32,21 @@ namespace Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
///
public static class AGUIEndpointRouteBuilderExtensions
{
+ ///
+ /// Maps an AG-UI agent endpoint using an agent registered in dependency injection via .
+ ///
+ /// The endpoint route builder.
+ /// The hosted agent builder that identifies the agent registration.
+ /// An for the mapped endpoint.
+ public static IEndpointConventionBuilder MapAGUIServer(
+ this IEndpointRouteBuilder endpoints,
+ IHostedAgentBuilder agentBuilder)
+ {
+ ArgumentNullException.ThrowIfNull(endpoints);
+ ArgumentNullException.ThrowIfNull(agentBuilder);
+ return endpoints.MapAGUIServer(agentBuilder.Name);
+ }
+
///
/// Maps an AG-UI agent endpoint using an agent registered in dependency injection via .
///
@@ -49,6 +64,23 @@ public static class AGUIEndpointRouteBuilderExtensions
return endpoints.MapAGUIServer(agentBuilder.Name, pattern);
}
+ ///
+ /// Maps an AG-UI agent endpoint using a named agent registered in dependency injection.
+ ///
+ /// The endpoint route builder.
+ /// The name of the keyed agent registration to resolve from dependency injection.
+ /// An for the mapped endpoint.
+ public static IEndpointConventionBuilder MapAGUIServer(
+ this IEndpointRouteBuilder endpoints,
+ string agentName)
+ {
+ ArgumentNullException.ThrowIfNull(endpoints);
+ ArgumentException.ThrowIfNullOrWhiteSpace(agentName);
+
+ var agent = endpoints.ServiceProvider.GetRequiredKeyedService(agentName);
+ return endpoints.MapAGUIServer(agent);
+ }
+
///
/// Maps an AG-UI agent endpoint using a named agent registered in dependency injection.
///
@@ -68,6 +100,24 @@ public static class AGUIEndpointRouteBuilderExtensions
return endpoints.MapAGUIServer(pattern, agent);
}
+ ///
+ /// Maps an AG-UI agent endpoint using a route derived from the agent name.
+ ///
+ /// The endpoint route builder.
+ /// The agent instance.
+ /// An for the mapped endpoint.
+ public static IEndpointConventionBuilder MapAGUIServer(
+ this IEndpointRouteBuilder endpoints,
+ AIAgent aiAgent)
+ {
+ ArgumentNullException.ThrowIfNull(endpoints);
+ ArgumentNullException.ThrowIfNull(aiAgent);
+ ArgumentException.ThrowIfNullOrWhiteSpace(aiAgent.Name, nameof(aiAgent.Name));
+ ValidateAgentName(aiAgent.Name);
+
+ return endpoints.MapAGUIServer($"/{aiAgent.Name}/agui", aiAgent);
+ }
+
///
/// Maps an AG-UI agent endpoint.
///
@@ -186,4 +236,13 @@ public static class AGUIEndpointRouteBuilderExtensions
await hostAgent.SaveSessionAsync(threadId, session, cancellationToken).ConfigureAwait(false);
}
+
+ private static void ValidateAgentName([NotNull] string agentName)
+ {
+ var escaped = Uri.EscapeDataString(agentName);
+ if (!string.Equals(escaped, agentName, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new ArgumentException($"Agent name '{agentName}' contains characters invalid for URL routes.", nameof(agentName));
+ }
+ }
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/MapAGUIEndpointRouteBuilderExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/MapAGUIEndpointRouteBuilderExtensionsTests.cs
new file mode 100644
index 000000000..11ca8d6f1
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/MapAGUIEndpointRouteBuilderExtensionsTests.cs
@@ -0,0 +1,210 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.DependencyInjection;
+using Moq;
+
+namespace Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests;
+
+///
+/// Unit tests for the agent-name-derived MapAGUIServer overloads.
+///
+public sealed class MapAGUIEndpointRouteBuilderExtensionsTests
+{
+ [Fact]
+ public void MapAGUIServer_WithAgentBuilder_MapsNameDerivedRoute()
+ {
+ // Arrange
+ using WebApplication app = CreateApp("test-agent");
+ Mock agentBuilder = new();
+ agentBuilder.SetupGet(builder => builder.Name).Returns("test-agent");
+
+ // Act
+ app.MapAGUIServer(agentBuilder.Object);
+
+ // Assert
+ Assert.Contains(GetRoutePatterns(app), pattern => pattern == "/test-agent/agui");
+ }
+
+ [Fact]
+ public void MapAGUIServer_WithAgentName_MapsNameDerivedRoute()
+ {
+ // Arrange
+ using WebApplication app = CreateApp("test-agent");
+
+ // Act
+ app.MapAGUIServer("test-agent");
+
+ // Assert
+ Assert.Contains(GetRoutePatterns(app), pattern => pattern == "/test-agent/agui");
+ }
+
+ [Fact]
+ public void MapAGUIServer_WithAgent_MapsNameDerivedRoute()
+ {
+ // Arrange
+ using WebApplication app = CreateApp();
+ AIAgent agent = new TestAgent("test-agent");
+
+ // Act
+ app.MapAGUIServer(agent);
+
+ // Assert
+ Assert.Contains(GetRoutePatterns(app), pattern => pattern == "/test-agent/agui");
+ }
+
+ [Fact]
+ public void MapAGUIServer_WithNullEndpoints_ThrowsArgumentNullException()
+ {
+ // Arrange
+ IEndpointRouteBuilder endpoints = null!;
+ AIAgent agent = new TestAgent("test-agent");
+
+ // Act
+ ArgumentNullException exception = Assert.Throws(() => endpoints.MapAGUIServer(agent));
+
+ // Assert
+ Assert.Equal("endpoints", exception.ParamName);
+ }
+
+ [Fact]
+ public void MapAGUIServer_WithNullAgentBuilder_ThrowsArgumentNullException()
+ {
+ // Arrange
+ using WebApplication app = CreateApp();
+
+ // Act
+ ArgumentNullException exception = Assert.Throws(() => app.MapAGUIServer((IHostedAgentBuilder)null!));
+
+ // Assert
+ Assert.Equal("agentBuilder", exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ [InlineData(" ")]
+ public void MapAGUIServer_WithNullOrWhitespaceAgentName_ThrowsArgumentException(string? agentName)
+ {
+ // Arrange
+ using WebApplication app = CreateApp();
+
+ // Act
+ ArgumentException exception = Assert.ThrowsAny(() => app.MapAGUIServer(agentName!));
+
+ // Assert
+ Assert.Equal("agentName", exception.ParamName);
+ }
+
+ [Fact]
+ public void MapAGUIServer_WithNullAgent_ThrowsArgumentNullException()
+ {
+ // Arrange
+ using WebApplication app = CreateApp();
+
+ // Act
+ ArgumentNullException exception = Assert.Throws(() => app.MapAGUIServer((AIAgent)null!));
+
+ // Assert
+ Assert.Equal("aiAgent", exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData("agent with spaces")]
+ [InlineData("agent