mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Fix workflow lookup with AddAsAIAgent(name) when name differs from workflow name (#1925)
This commit is contained in:
committed by
GitHub
Unverified
parent
6ca907f23f
commit
77d882e2b4
@@ -26,8 +26,10 @@ public static class HostedWorkflowBuilderExtensions
|
||||
/// <returns>An <see cref="IHostedAgentBuilder"/> that can be used to further configure the agent.</returns>
|
||||
public static IHostedAgentBuilder AddAsAIAgent(this IHostedWorkflowBuilder builder, string? name)
|
||||
{
|
||||
var agentName = name ?? builder.Name;
|
||||
return builder.HostApplicationBuilder.AddAIAgent(agentName, (sp, key) => sp.GetRequiredKeyedService<Workflow>(key)
|
||||
.AsAgent(name: key));
|
||||
var workflowName = builder.Name;
|
||||
var agentName = name ?? workflowName;
|
||||
|
||||
return builder.HostApplicationBuilder.AddAIAgent(agentName, (sp, key) =>
|
||||
sp.GetRequiredKeyedService<Workflow>(workflowName).AsAgent(name: key));
|
||||
}
|
||||
}
|
||||
|
||||
+191
@@ -233,6 +233,197 @@ public class HostApplicationBuilderWorkflowExtensionsTests
|
||||
Assert.Equal("agentBuilders", exception.ParamName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent without a name parameter uses the workflow name as the agent name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithoutName_UsesWorkflowName()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent();
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
|
||||
// Verify workflow is registered with workflow name
|
||||
var workflowDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(Workflow));
|
||||
Assert.NotNull(workflowDescriptor);
|
||||
|
||||
// Verify agent is registered with workflow name
|
||||
var agentDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(AIAgent));
|
||||
Assert.NotNull(agentDescriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent with a name parameter uses that name instead of the workflow name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithName_UsesProvidedName()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
const string AgentName = "testAgent";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent(AgentName);
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
|
||||
// Verify workflow is registered with workflow name
|
||||
var workflowDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(Workflow));
|
||||
Assert.NotNull(workflowDescriptor);
|
||||
|
||||
// Verify agent is registered with agent name (not workflow name)
|
||||
var agentDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == AgentName && d.ServiceType == typeof(AIAgent));
|
||||
Assert.NotNull(agentDescriptor);
|
||||
|
||||
// Verify no agent registered with workflow name
|
||||
var wrongAgentDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(AIAgent));
|
||||
Assert.NotSame(workflowDescriptor, wrongAgentDescriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent correctly retrieves the workflow using the workflow name, not the agent name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithDifferentName_RetrievesWorkflowCorrectly()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "myWorkflow";
|
||||
const string AgentName = "myAgent";
|
||||
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
workflowBuilder.AddAsAIAgent(AgentName);
|
||||
|
||||
var serviceProvider = builder.Build().Services;
|
||||
|
||||
// Act - Get the agent using the agent name
|
||||
var agent = serviceProvider.GetRequiredKeyedService<AIAgent>(AgentName);
|
||||
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal(AgentName, agent.Name);
|
||||
|
||||
// Verify that we can still get the workflow using the workflow name
|
||||
var workflow = serviceProvider.GetRequiredKeyedService<Workflow>(WorkflowName);
|
||||
Assert.NotNull(workflow);
|
||||
Assert.Equal(WorkflowName, workflow.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent returns IHostedAgentBuilder with correct name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_ReturnsHostedAgentBuilder()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
const string AgentName = "testAgent";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent(AgentName);
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
Assert.IsAssignableFrom<IHostedAgentBuilder>(agentBuilder);
|
||||
Assert.Equal(AgentName, agentBuilder.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent without name returns IHostedAgentBuilder with workflow name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithoutName_ReturnsHostedAgentBuilderWithWorkflowName()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent();
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
Assert.IsAssignableFrom<IHostedAgentBuilder>(agentBuilder);
|
||||
Assert.Equal(WorkflowName, agentBuilder.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent can chain multiple agents from the same workflow.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_MultipleAgents_FromSameWorkflow()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder1 = workflowBuilder.AddAsAIAgent("agent1");
|
||||
var agentBuilder2 = workflowBuilder.AddAsAIAgent("agent2");
|
||||
|
||||
Assert.NotNull(agentBuilder1);
|
||||
Assert.NotNull(agentBuilder2);
|
||||
|
||||
// Verify both agents are registered
|
||||
var agentDescriptor1 = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == "agent1" && d.ServiceType == typeof(AIAgent));
|
||||
var agentDescriptor2 = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == "agent2" && d.ServiceType == typeof(AIAgent));
|
||||
|
||||
Assert.NotNull(agentDescriptor1);
|
||||
Assert.NotNull(agentDescriptor2);
|
||||
|
||||
// Verify workflow is registered only once
|
||||
var workflowDescriptors = builder.Services.Where(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(Workflow)).ToList();
|
||||
Assert.Single(workflowDescriptors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent with null name behaves the same as the parameterless overload.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithNullName_UsesWorkflowName()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent(name: null);
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
Assert.Equal(WorkflowName, agentBuilder.Name);
|
||||
|
||||
// Verify agent is registered with workflow name
|
||||
var agentDescriptor = builder.Services.FirstOrDefault(
|
||||
d => (d.ServiceKey as string) == WorkflowName && d.ServiceType == typeof(AIAgent));
|
||||
Assert.NotNull(agentDescriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddAsAIAgent with empty string name uses empty string as agent name.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddAsAIAgent_WithEmptyName_UsesEmptyStringAsAgentName()
|
||||
{
|
||||
var builder = new HostApplicationBuilder();
|
||||
const string WorkflowName = "testWorkflow";
|
||||
var workflowBuilder = builder.AddWorkflow(WorkflowName, (sp, key) => CreateTestWorkflow(key));
|
||||
|
||||
var agentBuilder = workflowBuilder.AddAsAIAgent(name: "");
|
||||
|
||||
Assert.NotNull(agentBuilder);
|
||||
Assert.Equal("", agentBuilder.Name);
|
||||
|
||||
// Verify agent is registered with empty string name
|
||||
var agentDescriptor = builder.Services.FirstOrDefault(
|
||||
d => d.ServiceKey is string s && s.Length == 0 && d.ServiceType == typeof(AIAgent));
|
||||
Assert.NotNull(agentDescriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a simple test workflow with a given name.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user