diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs index 8f1039251d..a7dafbfc50 100644 --- a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs +++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs @@ -45,7 +45,7 @@ public override async Task RunAsync(IEnumerable m } // Clone the input messages and turn them into response messages with upper case text. - List responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList(); + List responseMessages = CloneAndToUpperCase(messages, this.Name).ToList(); // Notify the thread of the input and output messages. await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken); @@ -69,7 +69,7 @@ public override async IAsyncEnumerable RunStreamingAsync } // Clone the input messages and turn them into response messages with upper case text. - List responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList(); + List responseMessages = CloneAndToUpperCase(messages, this.Name).ToList(); // Notify the thread of the input and output messages. await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken); @@ -79,7 +79,7 @@ public override async IAsyncEnumerable RunStreamingAsync yield return new AgentRunResponseUpdate { AgentId = this.Id, - AuthorName = this.DisplayName, + AuthorName = message.AuthorName, Role = ChatRole.Assistant, Contents = message.Contents, ResponseId = Guid.NewGuid().ToString("N"), @@ -88,7 +88,7 @@ public override async IAsyncEnumerable RunStreamingAsync } } - private static IEnumerable CloneAndToUpperCase(IEnumerable messages, string agentName) => messages.Select(x => + private static IEnumerable CloneAndToUpperCase(IEnumerable messages, string? agentName) => messages.Select(x => { // Clone the message and update its author to be the agent. var messageClone = x.Clone(); diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs b/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs index e804fbb389..e326151b13 100644 --- a/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs +++ b/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs @@ -30,7 +30,6 @@ internal sealed class A2AAgent : AIAgent private readonly string? _id; private readonly string? _name; private readonly string? _description; - private readonly string? _displayName; private readonly ILogger _logger; /// @@ -40,9 +39,8 @@ internal sealed class A2AAgent : AIAgent /// The unique identifier for the agent. /// The the name of the agent. /// The description of the agent. - /// The display name of the agent. /// Optional logger factory to use for logging. - public A2AAgent(A2AClient a2aClient, string? id = null, string? name = null, string? description = null, string? displayName = null, ILoggerFactory? loggerFactory = null) + public A2AAgent(A2AClient a2aClient, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null) { _ = Throw.IfNull(a2aClient); @@ -50,7 +48,6 @@ public A2AAgent(A2AClient a2aClient, string? id = null, string? name = null, str this._id = id; this._name = name; this._description = description; - this._displayName = displayName; this._logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger(); } @@ -203,9 +200,6 @@ public override async IAsyncEnumerable RunStreamingAsync /// public override string? Name => this._name ?? base.Name; - /// - public override string DisplayName => this._displayName ?? base.DisplayName; - /// public override string? Description => this._description ?? base.Description; diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs index 095481c0d4..d57ed4cb42 100644 --- a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs +++ b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs @@ -33,9 +33,8 @@ public static class A2AClientExtensions /// The unique identifier for the agent. /// The the name of the agent. /// The description of the agent. - /// The display name of the agent. /// Optional logger factory for enabling logging within the agent. /// An instance backed by the A2A agent. - public static AIAgent GetAIAgent(this A2AClient client, string? id = null, string? name = null, string? description = null, string? displayName = null, ILoggerFactory? loggerFactory = null) => - new A2AAgent(client, id, name, description, displayName, loggerFactory); + public static AIAgent GetAIAgent(this A2AClient client, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null) => + new A2AAgent(client, id, name, description, loggerFactory); } diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgent.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgent.cs index 4cff385dcc..1f39a2758f 100644 --- a/dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgent.cs +++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgent.cs @@ -60,18 +60,6 @@ public abstract class AIAgent /// public virtual string? Name { get; } - /// - /// Gets a display-friendly name for the agent. - /// - /// - /// The agent's if available, otherwise the . - /// - /// - /// This property provides a guaranteed non-null string suitable for display in user interfaces, - /// logs, or other contexts where a readable identifier is needed. - /// - public virtual string DisplayName => this.Name ?? this.Id; - /// /// Gets a description of the agent's purpose, capabilities, or behavior. /// diff --git a/dotnet/src/Microsoft.Agents.AI.DevUI/EntitiesApiExtensions.cs b/dotnet/src/Microsoft.Agents.AI.DevUI/EntitiesApiExtensions.cs index 3271b40853..8dcc46b53c 100644 --- a/dotnet/src/Microsoft.Agents.AI.DevUI/EntitiesApiExtensions.cs +++ b/dotnet/src/Microsoft.Agents.AI.DevUI/EntitiesApiExtensions.cs @@ -231,7 +231,7 @@ private static EntityInfo CreateAgentEntityInfo(AIAgent agent) return new EntityInfo( Id: entityId, Type: "agent", - Name: agent.DisplayName, + Name: agent.Name ?? agent.Id, Description: agent.Description, Framework: "agent_framework", Tools: tools, diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.ChatCompletions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.ChatCompletions.cs index 3fcc9cad27..92c817b124 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.ChatCompletions.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.ChatCompletions.cs @@ -61,7 +61,7 @@ public static IEndpointConventionBuilder MapOpenAIChatCompletions( path ??= $"/{agent.Name}/v1/chat/completions"; var group = endpoints.MapGroup(path); - var endpointAgentName = agent.DisplayName; + var endpointAgentName = agent.Name ?? agent.Id; group.MapPost("/", async ([FromBody] CreateChatCompletion request, CancellationToken cancellationToken) => await AIAgentChatCompletionsProcessor.CreateChatCompletionAsync(agent, request, cancellationToken).ConfigureAwait(false)) diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.Responses.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.Responses.cs index 9a395b9b12..ae96636f16 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.Responses.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/EndpointRouteBuilderExtensions.Responses.cs @@ -76,7 +76,7 @@ public static IEndpointConventionBuilder MapOpenAIResponses( var handlers = new ResponsesHttpHandler(responsesService); var group = endpoints.MapGroup(responsesPath); - var endpointAgentName = agent.DisplayName; + var endpointAgentName = agent.Name ?? agent.Id; // Create response endpoint group.MapPost("/", handlers.CreateResponseAsync) diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/HandoffsWorkflowBuilder.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/HandoffsWorkflowBuilder.cs index 9e5b61ac42..9a3abfe960 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/HandoffsWorkflowBuilder.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/HandoffsWorkflowBuilder.cs @@ -125,14 +125,14 @@ public HandoffsWorkflowBuilder WithHandoff(AIAgent from, AIAgent to, string? han { Throw.ArgumentException( nameof(to), - $"The provided target agent '{to.DisplayName}' has no description, name, or instructions, and no handoff description has been provided. " + + $"The provided target agent '{to.Name ?? to.Id}' has no description, name, or instructions, and no handoff description has been provided. " + "At least one of these is required to register a handoff so that the appropriate target agent can be chosen."); } } if (!handoffs.Add(new(to, handoffReason))) { - Throw.InvalidOperationException($"A handoff from agent '{from.DisplayName}' to agent '{to.DisplayName}' has already been registered."); + Throw.InvalidOperationException($"A handoff from agent '{from.Name ?? from.Id}' to agent '{to.Name ?? to.Id}' has already been registered."); } return this; diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AgentRunStreamingExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AgentRunStreamingExecutor.cs index ea80f646f0..ae3a932feb 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AgentRunStreamingExecutor.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AgentRunStreamingExecutor.cs @@ -20,7 +20,7 @@ internal sealed class AgentRunStreamingExecutor(AIAgent agent, bool includeInput protected override async ValueTask TakeTurnAsync(List messages, IWorkflowContext context, bool? emitEvents, CancellationToken cancellationToken = default) { - List? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.DisplayName); + List? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.Name ?? agent.Id); List updates = []; await foreach (var update in agent.RunStreamingAsync(messages, cancellationToken: cancellationToken).ConfigureAwait(false)) diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs index 59dc49f143..24e0eea3cb 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs @@ -67,7 +67,7 @@ protected override RouteBuilder ConfigureRoutes(RouteBuilder routeBuilder) => List updates = []; List allMessages = handoffState.Messages; - List? roleChanges = allMessages.ChangeAssistantToUserForOtherParticipants(this._agent.DisplayName); + List? roleChanges = allMessages.ChangeAssistantToUserForOtherParticipants(this._agent.Name ?? this._agent.Id); await foreach (var update in this._agent.RunStreamingAsync(allMessages, options: this._agentOptions, @@ -85,7 +85,7 @@ await AddUpdateAsync( new AgentRunResponseUpdate { AgentId = this._agent.Id, - AuthorName = this._agent.DisplayName, + AuthorName = this._agent.Name ?? this._agent.Id, Contents = [new FunctionResultContent(fcc.CallId, "Transferred.")], CreatedAt = DateTimeOffset.UtcNow, MessageId = Guid.NewGuid().ToString("N"), diff --git a/dotnet/src/Microsoft.Agents.AI/OpenTelemetryAgent.cs b/dotnet/src/Microsoft.Agents.AI/OpenTelemetryAgent.cs index 7cd3c27b70..22da0c99da 100644 --- a/dotnet/src/Microsoft.Agents.AI/OpenTelemetryAgent.cs +++ b/dotnet/src/Microsoft.Agents.AI/OpenTelemetryAgent.cs @@ -114,7 +114,9 @@ private void UpdateCurrentActivity(Activity? previousActivity) // Override information set by OpenTelemetryChatClient to make it specific to invoke_agent. - activity.DisplayName = $"{OpenTelemetryConsts.GenAI.InvokeAgent} {this.DisplayName}"; + activity.DisplayName = string.IsNullOrWhiteSpace(this.Name) + ? $"{OpenTelemetryConsts.GenAI.InvokeAgent} {this.Id}" + : $"{OpenTelemetryConsts.GenAI.InvokeAgent} {this.Name}({this.Id})"; activity.SetTag(OpenTelemetryConsts.GenAI.Operation.Name, OpenTelemetryConsts.GenAI.InvokeAgent); if (!string.IsNullOrWhiteSpace(this._providerName)) diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs index 9869d47f6b..0b491fb303 100644 --- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs @@ -42,16 +42,14 @@ public void Constructor_WithAllParameters_InitializesPropertiesCorrectly() const string TestId = "test-id"; const string TestName = "test-name"; const string TestDescription = "test-description"; - const string TestDisplayName = "test-display-name"; // Act - var agent = new A2AAgent(this._a2aClient, TestId, TestName, TestDescription, TestDisplayName); + var agent = new A2AAgent(this._a2aClient, TestId, TestName, TestDescription); // Assert Assert.Equal(TestId, agent.Id); Assert.Equal(TestName, agent.Name); Assert.Equal(TestDescription, agent.Description); - Assert.Equal(TestDisplayName, agent.DisplayName); } [Fact] @@ -70,7 +68,6 @@ public void Constructor_WithDefaultParameters_UsesBaseProperties() Assert.NotEmpty(agent.Id); Assert.Null(agent.Name); Assert.Null(agent.Description); - Assert.Equal(agent.Id, agent.DisplayName); } [Fact] diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs index e21035003e..5b84324e8b 100644 --- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs @@ -19,10 +19,9 @@ public void GetAIAgent_WithAllParameters_ReturnsA2AAgentWithSpecifiedProperties( const string TestId = "test-agent-id"; const string TestName = "Test Agent"; const string TestDescription = "This is a test agent description"; - const string TestDisplayName = "Test Display Name"; // Act - var agent = a2aClient.GetAIAgent(TestId, TestName, TestDescription, TestDisplayName); + var agent = a2aClient.GetAIAgent(TestId, TestName, TestDescription); // Assert Assert.NotNull(agent); @@ -30,6 +29,5 @@ public void GetAIAgent_WithAllParameters_ReturnsA2AAgentWithSpecifiedProperties( Assert.Equal(TestId, agent.Id); Assert.Equal(TestName, agent.Name); Assert.Equal(TestDescription, agent.Description); - Assert.Equal(TestDisplayName, agent.DisplayName); } } diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/LoggingAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/LoggingAgentTests.cs index 57b3051197..58e9536491 100644 --- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/LoggingAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/LoggingAgentTests.cs @@ -42,7 +42,6 @@ public void Properties_DelegateToInnerAgent() Assert.Equal("TestAgent", agent.Name); Assert.Equal("This is a test agent.", agent.Description); Assert.Equal(innerAgent.Id, agent.Id); - Assert.Equal(innerAgent.DisplayName, agent.DisplayName); } [Fact] diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs index b9b04b7228..405832763c 100644 --- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs @@ -45,7 +45,6 @@ public void Properties_DelegateToInnerAgent() Assert.Equal("TestAgent", agent.Name); Assert.Equal("This is a test agent.", agent.Description); Assert.Equal(innerAgent.Id, agent.Id); - Assert.Equal(innerAgent.DisplayName, agent.DisplayName); } [Fact] @@ -170,7 +169,7 @@ async static IAsyncEnumerable CallbackAsync( Assert.Equal("localhost", activity.GetTagItem("server.address")); Assert.Equal(12345, (int)activity.GetTagItem("server.port")!); - Assert.Equal("invoke_agent TestAgent", activity.DisplayName); + Assert.Equal($"invoke_agent {agent.Name}({agent.Id})", activity.DisplayName); Assert.Equal("invoke_agent", activity.GetTagItem("gen_ai.operation.name")); Assert.Equal("TestAgentProviderFromAIAgentMetadata", activity.GetTagItem("gen_ai.provider.name")); Assert.Equal(innerAgent.Name, activity.GetTagItem("gen_ai.agent.name")); @@ -431,7 +430,15 @@ async static IAsyncEnumerable CallbackAsync( Assert.Equal("localhost", activity.GetTagItem("server.address")); Assert.Equal(12345, (int)activity.GetTagItem("server.port")!); - Assert.Equal($"invoke_agent {innerAgent.DisplayName}", activity.DisplayName); + if (string.IsNullOrWhiteSpace(innerAgent.Name)) + { + Assert.Equal($"invoke_agent {innerAgent.Id}", activity.DisplayName); + } + else + { + Assert.Equal($"invoke_agent {innerAgent.Name}({innerAgent.Id})", activity.DisplayName); + } + Assert.Equal("invoke_agent", activity.GetTagItem("gen_ai.operation.name")); Assert.Equal("TestAgentProviderFromAIAgentMetadata", activity.GetTagItem("gen_ai.provider.name")); Assert.Equal(innerAgent.Name, activity.GetTagItem("gen_ai.agent.name")); diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/Sample/12_HandOff_HostAsAgent.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/Sample/12_HandOff_HostAsAgent.cs index 824a75d5d0..c319a0ac32 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/Sample/12_HandOff_HostAsAgent.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/Sample/12_HandOff_HostAsAgent.cs @@ -30,7 +30,7 @@ protected override IEnumerable GetEpilogueMessages(AgentRunOptions? { return [new(ChatRole.Assistant, [new FunctionCallContent(Guid.NewGuid().ToString("N"), handoff.Name)]) { - AuthorName = this.DisplayName, + AuthorName = this.Name ?? this.Id, MessageId = Guid.NewGuid().ToString("N"), CreatedAt = DateTime.UtcNow }]; diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestEchoAgent.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestEchoAgent.cs index 9ddc94cf71..caec2a0631 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestEchoAgent.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestEchoAgent.cs @@ -47,7 +47,7 @@ IEnumerable echoMessages select UpdateThread(new ChatMessage(ChatRole.Assistant, $"{prefix}{message.Text}") { - AuthorName = this.DisplayName, + AuthorName = this.Name ?? this.Id, CreatedAt = DateTimeOffset.Now, MessageId = Guid.NewGuid().ToString("N") }, thread as InMemoryAgentThread);