mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: [Breaking] Delete display name property (#2758)
* delete the AIAgent.DisplayName property * use agent name as a first value for activity display name * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
0298e0a401
commit
a71f768331
+4
-4
@@ -45,7 +45,7 @@ namespace SampleApp
|
||||
}
|
||||
|
||||
// Clone the input messages and turn them into response messages with upper case text.
|
||||
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
|
||||
List<ChatMessage> 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 @@ namespace SampleApp
|
||||
}
|
||||
|
||||
// Clone the input messages and turn them into response messages with upper case text.
|
||||
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
|
||||
List<ChatMessage> 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 @@ namespace SampleApp
|
||||
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 @@ namespace SampleApp
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<ChatMessage> CloneAndToUpperCase(IEnumerable<ChatMessage> messages, string agentName) => messages.Select(x =>
|
||||
private static IEnumerable<ChatMessage> CloneAndToUpperCase(IEnumerable<ChatMessage> messages, string? agentName) => messages.Select(x =>
|
||||
{
|
||||
// Clone the message and update its author to be the agent.
|
||||
var messageClone = x.Clone();
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
@@ -40,9 +39,8 @@ internal sealed class A2AAgent : AIAgent
|
||||
/// <param name="id">The unique identifier for the agent.</param>
|
||||
/// <param name="name">The the name of the agent.</param>
|
||||
/// <param name="description">The description of the agent.</param>
|
||||
/// <param name="displayName">The display name of the agent.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory to use for logging.</param>
|
||||
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 @@ internal sealed class A2AAgent : AIAgent
|
||||
this._id = id;
|
||||
this._name = name;
|
||||
this._description = description;
|
||||
this._displayName = displayName;
|
||||
this._logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<A2AAgent>();
|
||||
}
|
||||
|
||||
@@ -203,9 +200,6 @@ internal sealed class A2AAgent : AIAgent
|
||||
/// <inheritdoc/>
|
||||
public override string? Name => this._name ?? base.Name;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string DisplayName => this._displayName ?? base.DisplayName;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? Description => this._description ?? base.Description;
|
||||
|
||||
|
||||
@@ -33,9 +33,8 @@ public static class A2AClientExtensions
|
||||
/// <param name="id">The unique identifier for the agent.</param>
|
||||
/// <param name="name">The the name of the agent.</param>
|
||||
/// <param name="description">The description of the agent.</param>
|
||||
/// <param name="displayName">The display name of the agent.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory for enabling logging within the agent.</param>
|
||||
/// <returns>An <see cref="AIAgent"/> instance backed by the A2A agent.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -60,18 +60,6 @@ public abstract class AIAgent
|
||||
/// </remarks>
|
||||
public virtual string? Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a display-friendly name for the agent.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The agent's <see cref="Name"/> if available, otherwise the <see cref="Id"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This property provides a guaranteed non-null string suitable for display in user interfaces,
|
||||
/// logs, or other contexts where a readable identifier is needed.
|
||||
/// </remarks>
|
||||
public virtual string DisplayName => this.Name ?? this.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a description of the agent's purpose, capabilities, or behavior.
|
||||
/// </summary>
|
||||
|
||||
@@ -231,7 +231,7 @@ internal static class EntitiesApiExtensions
|
||||
return new EntityInfo(
|
||||
Id: entityId,
|
||||
Type: "agent",
|
||||
Name: agent.DisplayName,
|
||||
Name: agent.Name ?? agent.Id,
|
||||
Description: agent.Description,
|
||||
Framework: "agent_framework",
|
||||
Tools: tools,
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public static partial class MicrosoftAgentAIHostingOpenAIEndpointRouteBuilderExt
|
||||
|
||||
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))
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public static partial class MicrosoftAgentAIHostingOpenAIEndpointRouteBuilderExt
|
||||
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)
|
||||
|
||||
@@ -125,14 +125,14 @@ public sealed class HandoffsWorkflowBuilder
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed class AgentRunStreamingExecutor(AIAgent agent, bool includeInput
|
||||
|
||||
protected override async ValueTask TakeTurnAsync(List<ChatMessage> messages, IWorkflowContext context, bool? emitEvents, CancellationToken cancellationToken = default)
|
||||
{
|
||||
List<ChatMessage>? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.DisplayName);
|
||||
List<ChatMessage>? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.Name ?? agent.Id);
|
||||
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
await foreach (var update in agent.RunStreamingAsync(messages, cancellationToken: cancellationToken).ConfigureAwait(false))
|
||||
|
||||
@@ -67,7 +67,7 @@ internal sealed class HandoffAgentExecutor(
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
List<ChatMessage> allMessages = handoffState.Messages;
|
||||
|
||||
List<ChatMessage>? roleChanges = allMessages.ChangeAssistantToUserForOtherParticipants(this._agent.DisplayName);
|
||||
List<ChatMessage>? 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 @@ internal sealed class HandoffAgentExecutor(
|
||||
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"),
|
||||
|
||||
@@ -114,7 +114,9 @@ public sealed class OpenTelemetryAgent : DelegatingAIAgent, IDisposable
|
||||
|
||||
// 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))
|
||||
|
||||
@@ -42,16 +42,14 @@ public sealed class A2AAgentTests : IDisposable
|
||||
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 sealed class A2AAgentTests : IDisposable
|
||||
Assert.NotEmpty(agent.Id);
|
||||
Assert.Null(agent.Name);
|
||||
Assert.Null(agent.Description);
|
||||
Assert.Equal(agent.Id, agent.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
+1
-3
@@ -19,10 +19,9 @@ public sealed class A2AClientExtensionsTests
|
||||
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 sealed class A2AClientExtensionsTests
|
||||
Assert.Equal(TestId, agent.Id);
|
||||
Assert.Equal(TestName, agent.Name);
|
||||
Assert.Equal(TestDescription, agent.Description);
|
||||
Assert.Equal(TestDisplayName, agent.DisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ public class LoggingAgentTests
|
||||
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]
|
||||
|
||||
@@ -45,7 +45,6 @@ public class OpenTelemetryAgentTests
|
||||
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 @@ public class OpenTelemetryAgentTests
|
||||
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 @@ public class OpenTelemetryAgentTests
|
||||
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"));
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ internal sealed class HandoffTestEchoAgent(string id, string name, string prefix
|
||||
{
|
||||
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
|
||||
}];
|
||||
|
||||
@@ -47,7 +47,7 @@ internal class TestEchoAgent(string? id = null, string? name = null, string? pre
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user