mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Remove instructions from base agent type, and ensure description is only required where necessary. (#154)
* Remove instructions from base agent type, and ensure description is only required where necessary. * Fix code issue. * Remove unused import. * Remove typo * Make the description parameter optional * Also use name for handoffs if no description is provided.
This commit is contained in:
committed by
GitHub
Unverified
parent
fbf1f10a8a
commit
bc6573f475
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -30,7 +29,7 @@ public abstract class AgentActor : OrchestrationActor
|
||||
id,
|
||||
runtime,
|
||||
context,
|
||||
VerifyDescription(agent),
|
||||
agent.Description,
|
||||
logger)
|
||||
{
|
||||
this.Agent = agent;
|
||||
@@ -162,9 +161,4 @@ public abstract class AgentActor : OrchestrationActor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string VerifyDescription(Agent agent)
|
||||
{
|
||||
return agent.Description ?? throw new ArgumentException($"Missing agent description: {agent.Name ?? agent.Id}", nameof(agent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.AI.Agents.Runtime;
|
||||
@@ -84,7 +85,12 @@ public static class OrchestrationHandoffsExtensions
|
||||
|
||||
foreach (Agent target in targets)
|
||||
{
|
||||
agentHandoffs[target.Name ?? target.Id] = target.Description ?? string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(target.Description) && string.IsNullOrWhiteSpace(target.Name))
|
||||
{
|
||||
throw new InvalidOperationException($"The provided target agent with Id '{target.Id}' has no description or name, and no handoff description has been provided. At least one of these are required to register a handoff so that the appropriate target agent can be chosen.");
|
||||
}
|
||||
|
||||
agentHandoffs[target.Name ?? target.Id] = target.Description ?? target.Name!;
|
||||
}
|
||||
|
||||
return handoffs;
|
||||
|
||||
@@ -15,7 +15,7 @@ public abstract class OrchestrationActor : RuntimeActor
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrchestrationActor"/> class.
|
||||
/// </summary>
|
||||
protected OrchestrationActor(ActorId id, IAgentRuntime runtime, OrchestrationContext context, string description, ILogger? logger = null)
|
||||
protected OrchestrationActor(ActorId id, IAgentRuntime runtime, OrchestrationContext context, string? description = null, ILogger? logger = null)
|
||||
: base(id, runtime, description, logger)
|
||||
{
|
||||
this.Context = context;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Microsoft.Extensions.AI.Agents;
|
||||
public abstract class Agent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the identifier of the agent (optional).
|
||||
/// Gets the identifier of the agent.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The identifier of the agent. The default is a random GUID value, but for service agents, it will match the id of the agent in the service.
|
||||
@@ -32,11 +32,6 @@ public abstract class Agent
|
||||
/// </summary>
|
||||
public virtual string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instructions for the agent (optional).
|
||||
/// </summary>
|
||||
public virtual string? Instructions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a new <see cref="AgentThread"/> instance that is compatible with the agent.
|
||||
/// </summary>
|
||||
|
||||
@@ -15,7 +15,7 @@ public readonly struct ActorMetadata : IEquatable<ActorMetadata>
|
||||
/// <param name="type">The type of the actor.</param>
|
||||
/// <param name="key">The unique key associated with the actor.</param>
|
||||
/// <param name="description">A brief description of the actor.</param>
|
||||
public ActorMetadata(ActorType type, string key, string description)
|
||||
public ActorMetadata(ActorType type, string key, string? description = null)
|
||||
{
|
||||
if (!ActorId.IsValidKey(key))
|
||||
{
|
||||
@@ -46,7 +46,7 @@ public readonly struct ActorMetadata : IEquatable<ActorMetadata>
|
||||
/// <summary>
|
||||
/// A brief description of the actor's purpose or functionality.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
public string? Description { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly bool Equals(object? obj) =>
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class RuntimeActor : IRuntimeActor
|
||||
protected RuntimeActor(
|
||||
ActorId id,
|
||||
IAgentRuntime runtime,
|
||||
string description,
|
||||
string? description = null,
|
||||
ILogger? logger = null)
|
||||
{
|
||||
this.Id = id;
|
||||
|
||||
@@ -56,8 +56,10 @@ public sealed class ChatClientAgent : Agent
|
||||
/// <inheritdoc/>
|
||||
public override string? Description => this._agentOptions?.Description;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? Instructions => this._agentOptions?.Instructions;
|
||||
/// <summary>
|
||||
/// Gets the instructions for the agent (optional).
|
||||
/// </summary>
|
||||
public string? Instructions => this._agentOptions?.Instructions;
|
||||
|
||||
/// <summary>
|
||||
/// Gets of the default <see cref="Microsoft.Extensions.AI.ChatOptions"/> used by the agent.
|
||||
|
||||
@@ -201,23 +201,41 @@ public class HandoffsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddWithTargetWithNoDescriptionUsesEmptyString()
|
||||
public void AddWithAgentWithNoDescriptionUsesName()
|
||||
{
|
||||
// Arrange
|
||||
OrchestrationHandoffs handoffs = new("source");
|
||||
|
||||
Agent sourceAgent = CreateAgent("source", "Source Agent");
|
||||
Agent targetAgent = CreateAgent("target", null);
|
||||
Agent targetAgent1 = CreateAgent("target1", name: "target 1");
|
||||
|
||||
// Act
|
||||
handoffs.Add(sourceAgent, targetAgent);
|
||||
handoffs.Add(sourceAgent, targetAgent1);
|
||||
|
||||
// Assert
|
||||
Assert.Single(handoffs);
|
||||
Assert.Equal("source", handoffs.FirstAgentName);
|
||||
Assert.True(handoffs.ContainsKey("source"));
|
||||
|
||||
AgentHandoffs sourceHandoffs = handoffs["source"];
|
||||
Assert.Single(sourceHandoffs);
|
||||
Assert.Equal(string.Empty, sourceHandoffs["target"]);
|
||||
Assert.Equal("target 1", sourceHandoffs["target 1"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddWithAgentWithNoDescriptionOrNameThrows()
|
||||
{
|
||||
// Arrange
|
||||
OrchestrationHandoffs handoffs = new("source");
|
||||
|
||||
Agent sourceAgent = CreateAgent("source", "Source Agent");
|
||||
Agent targetAgent1 = CreateAgent("target1");
|
||||
|
||||
// Act
|
||||
InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => handoffs.Add(sourceAgent, targetAgent1));
|
||||
|
||||
// Assert
|
||||
Assert.Equal("The provided target agent with Id 'target1' has no description or name, and no handoff description has been provided. At least one of these are required to register a handoff so that the appropriate target agent can be chosen.", ex.Message);
|
||||
}
|
||||
|
||||
private static ChatClientAgent CreateAgent(string id, string? description = null, string? name = null)
|
||||
|
||||
Reference in New Issue
Block a user