Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,17 @@ public TBuilder WithHandoff(AIAgent from, AIAgent to, string? handoffReason = nu

if (string.IsNullOrWhiteSpace(handoffReason))
{
handoffReason = to.Description ?? to.Name ?? (to as ChatClientAgent)?.Instructions;
handoffReason = (string.IsNullOrWhiteSpace(to.Description) ? null : to.Description)
?? (string.IsNullOrWhiteSpace(to.Name) ? null : $"handoff to {to.Name}")
?? to.GetService<ChatClientAgent>()?.Instructions;
Comment thread
lokitoth marked this conversation as resolved.

if (string.IsNullOrWhiteSpace(handoffReason))
{
Throw.ArgumentException(
nameof(to),
$"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.");
$"The provided target agent '{(string.IsNullOrWhiteSpace(to.Name) ? to.Id : to.Name)}' 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.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
Expand All @@ -11,7 +12,9 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Agents.AI.Workflows.InProc;
using Microsoft.Agents.AI.Workflows.Specialized;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;

#pragma warning disable SYSLIB1045 // Use GeneratedRegex
#pragma warning disable RCS1186 // Use Regex instance instead of static method
Expand Down Expand Up @@ -52,6 +55,51 @@ public void BuildHandoffs_InvalidArguments_Throws()

var noDescriptionAgent = new ChatClientAgent(new MockChatClient(delegate { return new(); }));
Assert.Throws<ArgumentException>("to", () => handoffs.WithHandoff(agent, noDescriptionAgent));

var emptyDescriptionAgent = new MockChatClient(delegate { return new(); }).AsAIAgent(description: "");
Assert.Throws<ArgumentException>("to", () => handoffs.WithHandoff(agent, emptyDescriptionAgent));

var emptyNameAgent = new MockChatClient(delegate { return new(); }).AsAIAgent(name: "");
Assert.Throws<ArgumentException>("to", () => handoffs.WithHandoff(agent, emptyNameAgent));
}

private sealed class NullLogger : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
return null;
}

public bool IsEnabled(LogLevel logLevel)
{
return false;
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
}
}

[Fact]
public void BuildHandoffs_DelegatingAIAgent_DoesNotThrow()
{
DoubleEchoAgent agent = new("agent");
HandoffWorkflowBuilder handoffs = AgentWorkflowBuilder.CreateHandoffBuilderWith(agent);
Assert.NotNull(handoffs);

ChatClientAgent instructionsOnlyAgent = new MockChatClient(delegate { return new(); }).AsAIAgent(instructions: "instructions");
LoggingAgent delegatingAgent = new(instructionsOnlyAgent, new NullLogger());

handoffs.WithHandoff(agent, delegatingAgent);

// get the _targets field from the HandoffWorkflowBuilder (need to use the base type)
FieldInfo field = typeof(HandoffWorkflowBuilder).BaseType!.GetField("_targets", BindingFlags.Instance | BindingFlags.NonPublic)!;
Dictionary<AIAgent, HashSet<HandoffTarget>>? targets = field.GetValue(handoffs) as Dictionary<AIAgent, HashSet<HandoffTarget>>;

targets.Should().NotBeNull();

HandoffTarget target = targets[agent].Single();
target.Reason.Should().Be("instructions");
}

[Fact]
Expand Down
Loading