diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentBinding.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentBinding.cs
index 171f7d9eec..4897189d90 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentBinding.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentBinding.cs
@@ -11,7 +11,7 @@ namespace Microsoft.Agents.AI.Workflows;
/// The AI agent.
/// Specifies whether the agent should emit events. If null, the default behavior is applied.
public record AIAgentBinding(AIAgent Agent, bool EmitEvents = false)
- : ExecutorBinding(Throw.IfNull(Agent).Name ?? Throw.IfNull(Agent.Id),
+ : ExecutorBinding(Throw.IfNull(Agent).GetDescriptiveId(),
(_) => new(new AIAgentHostExecutor(Agent, EmitEvents)),
typeof(AIAgentHostExecutor),
Agent)
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
index cd8386a268..0a887013a3 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
@@ -14,7 +14,7 @@ internal sealed class AIAgentHostExecutor : ChatProtocolExecutor
private readonly AIAgent _agent;
private AgentThread? _thread;
- public AIAgentHostExecutor(AIAgent agent, bool emitEvents = false) : base(id: agent.Id)
+ public AIAgentHostExecutor(AIAgent agent, bool emitEvents = false) : base(id: agent.GetDescriptiveId())
{
this._agent = agent;
this._emitEvents = emitEvents;
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/SpecializedExecutorSmokeTests.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/SpecializedExecutorSmokeTests.cs
index 87a29690db..b93d7862d5 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/SpecializedExecutorSmokeTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/SpecializedExecutorSmokeTests.cs
@@ -8,6 +8,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
+using Microsoft.Agents.AI.Workflows.Checkpointing;
using Microsoft.Agents.AI.Workflows.Execution;
using Microsoft.Agents.AI.Workflows.Specialized;
using Microsoft.Extensions.AI;
@@ -196,4 +197,50 @@ public class SpecializedExecutorSmokeTests
collected.Text.Should().Be(expectedText);
}
}
+
+ [Fact]
+ public async Task Test_AIAgent_ExecutorId_Use_Agent_NameAsync()
+ {
+ const string AgentAName = "TestAgentAName";
+ const string AgentBName = "TestAgentBName";
+ TestAIAgent agentA = new(name: AgentAName);
+ TestAIAgent agentB = new(name: AgentBName);
+ var workflow = new WorkflowBuilder(agentA).AddEdge(agentA, agentB).Build();
+ var definition = workflow.ToWorkflowInfo();
+
+ // Verify that the agent host executor registration IDs in the workflow definition
+ // match the agent names when agent names are provided.
+ // The property DisplayName falls back to using the agent ID when Name is not set.
+ agentA.GetDescriptiveId().Should().Contain(AgentAName);
+ agentB.GetDescriptiveId().Should().Contain(AgentBName);
+ definition.Executors[agentA.GetDescriptiveId()].ExecutorId.Should().Be(agentA.GetDescriptiveId());
+ definition.Executors[agentB.GetDescriptiveId()].ExecutorId.Should().Be(agentB.GetDescriptiveId());
+
+ // This will create an instance of the start agent and verify that the ID
+ // of the executor instance matches the ID of the registration.
+ var protocolDescriptor = await workflow.DescribeProtocolAsync();
+ protocolDescriptor.Accepts.Should().Contain(typeof(ChatMessage));
+ }
+
+ [Fact]
+ public async Task Test_AIAgent_ExecutorId_Use_Agent_ID_When_Name_Not_ProvidedAsync()
+ {
+ TestAIAgent agentA = new();
+ TestAIAgent agentB = new();
+ var workflow = new WorkflowBuilder(agentA).AddEdge(agentA, agentB).Build();
+ var definition = workflow.ToWorkflowInfo();
+
+ // Verify that the agent host executor registration IDs in the workflow definition
+ // match the agent IDs when agent names are not provided.
+ // The property DisplayName falls back to using the agent ID when Name is not set.
+ agentA.GetDescriptiveId().Should().Contain(agentA.Id);
+ agentB.GetDescriptiveId().Should().Contain(agentB.Id);
+ definition.Executors[agentA.GetDescriptiveId()].ExecutorId.Should().Be(agentA.GetDescriptiveId());
+ definition.Executors[agentB.GetDescriptiveId()].ExecutorId.Should().Be(agentB.GetDescriptiveId());
+
+ // This will create an instance of the start agent and verify that the ID
+ // of the executor instance matches the ID of the registration.
+ var protocolDescriptor = await workflow.DescribeProtocolAsync();
+ protocolDescriptor.Accepts.Should().Contain(typeof(ChatMessage));
+ }
}