Skip to content

.Net: Update to AgentDefinition.Inputs to match latest spec changes #10817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
8 changes: 4 additions & 4 deletions dotnet/src/Agents/Abstractions/Definition/AgentDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ public sealed class AgentDefinition
public ModelDefinition? Model { get; set; }

/// <summary>
/// Gets or sets the collection of input variables used by the agent.
/// Gets or sets the collection of inputs used by the agent.
/// </summary>
public IList<InputVariable>? Inputs { get; set; }
public Dictionary<string, AgentInput>? Inputs { get; set; }

/// <summary>
/// Gets or sets the collection of output variables supported by the agent.
/// Gets or sets the collection of outputs supported by the agent.
/// </summary>
public IList<OutputVariable>? Outputs { get; set; }
public IList<AgentOutput>? Outputs { get; set; }

/// <summary>
/// Gets or sets the template options used by the agent.
Expand Down
55 changes: 55 additions & 0 deletions dotnet/src/Agents/Abstractions/Definition/AgentInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;

namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Represents an input for an agent.
/// </summary>
[ExcludeFromCodeCoverage]
[Experimental("SKEXP0110")]
public sealed class AgentInput
{
/// <summary>
/// Gets or sets the name of the input.
/// </summary>
public string? Name { get; set; }

/// <summary>
/// Gets or sets a description of the input.
/// </summary>
public string? Description { get; set; }

/// <summary>
/// Gets or sets a default value for the input.
/// </summary>
public object? Default { get; set; }

/// <summary>
/// Gets or sets whether the input is considered required (rather than optional).
/// </summary>
/// <remarks>
/// The default is true.
/// </remarks>
public bool Required { get; set; } = true;

/// <summary>
/// Gets or sets JSON Schema describing this input.
/// </summary>
public string? Schema { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to handle the input value as potential dangerous content.
/// </summary>
/// <remarks>
/// The default is true.
/// When set to false the value of the input is treated as safe content.
/// </remarks>
public bool Strict { get; set; } = true;

/// <summary>
/// Gets or sets a sample value for the input.
/// </summary>
public object? Sample { get; set; }
}
28 changes: 28 additions & 0 deletions dotnet/src/Agents/Abstractions/Definition/AgentOutput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;

namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Represents an output for an agent.
/// </summary>
[ExcludeFromCodeCoverage]
[Experimental("SKEXP0110")]
public sealed class AgentOutput
{
/// <summary>
/// Gets or sets the name of the output.
/// </summary>
public string? Name { get; set; }

/// <summary>
/// Gets or sets a description of the output.
/// </summary>
public string? Description { get; set; }

/// <summary>
/// Gets or sets JSON Schema describing this output.
/// </summary>
public string? Schema { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Provides extension methods for <see cref="AgentDefinition"/>.
/// </summary>
[Experimental("SKEXP0110")]
public static class AgentDefinitionExtensions
{
/// <summary>
Expand All @@ -21,11 +23,11 @@ public static KernelArguments GetDefaultKernelArguments(this AgentDefinition age
if (agentDefinition?.Inputs is not null)
{
// Add default arguments for the agent
foreach (var input in agentDefinition.Inputs)
foreach (var keyValuePair in agentDefinition.Inputs)
{
if (input.Default is not null)
if (keyValuePair.Value.Default is not null)
{
arguments.Add(input.Name, input.Default);
arguments.Add(keyValuePair.Key, keyValuePair.Value.Default);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections.Generic;
using Microsoft.SemanticKernel.Agents;
using Xunit;

Expand All @@ -19,11 +20,11 @@ public void VerifyGetDefaultKernelArguments()
// Arrange
AgentDefinition agentDefinition = new()
{
Inputs =
[
new() { Name = "Input1", IsRequired = false, Default = "Default1" },
new() { Name = "Input2", IsRequired = true, Default = "Default2" }
],
Inputs = new Dictionary<string, AgentInput>
{
["Input1"] = new() { Name = "Input1", Required = false, Default = "Default1" },
["Input2"] = new() { Name = "Input2", Required = true, Default = "Default2" }
},
};

// Act
Expand Down
14 changes: 10 additions & 4 deletions dotnet/src/Agents/UnitTests/Yaml/AgentDefinitionYamlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ public void VerifyAgentDefinitionFromYaml()
configuration:
type: azureai
inputs:
- name: input1
description: input1 description
- name: input2
description: input2 description
input1:
description: input1 description
required: true
default: input1 default
sample: input1 sample
input2:
description: input2 description
required: false
default: input2 default
sample: input2 sample
outputs:
- description: output1 description
template:
Expand Down
55 changes: 55 additions & 0 deletions dotnet/src/Agents/UnitTests/Yaml/KernelAgentYamlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,61 @@ public void Dispose()
this._httpClient.Dispose();
}

/// <summary>
/// Verify can create an instance of <see cref="AgentDefinition"/> from YAML text.
/// </summary>
[Fact]
public void VerifyAgentDefinitionFromYaml()
{
// Arrange
var text =
"""
version: 1.0.0
type: chat_completion_agent
name: ChatCompletionAgent
description: ChatCompletionAgent Description
instructions: ChatCompletionAgent Instructions
metadata:
author: Microsoft
created: 2025-02-21
model:
id: gpt-4o-mini
options:
temperature: 0.4
function_choice_behavior:
type: auto
configuration:
type: azureai
inputs:
input1:
description: input1 description
required: true
default: input1 default
sample: input1 sample
input2:
description: input2 description
required: false
default: input2 default
sample: input2 sample
outputs:
- description: output1 description
template:
format: liquid
parser: semantic-kernel
tools:
- name: tool1
type: code_interpreter
- name: tool2
type: file_search
""";

// Act
var agentDefinition = AgentDefinitionYaml.FromYaml(text);

// Assert
Assert.NotNull(agentDefinition);
}

/// <summary>
/// Verify can create an instance of <see cref="KernelAgent"/> using <see cref="ChatCompletionAgentFactory"/>
/// </summary>
Expand Down
24 changes: 23 additions & 1 deletion dotnet/src/Agents/Yaml/AgentDefinitionYaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ public static AgentDefinition FromYaml(string text)
.WithTypeConverter(new AgentMetadataTypeConverter())
.Build();

return deserializer.Deserialize<AgentDefinition>(text);
var agentDefinition = deserializer.Deserialize<AgentDefinition>(text);
return agentDefinition.UpdateInputNames();
}

#region private
/// <summary>
/// Update the input names to match dictionary keys in this <see cref="AgentDefinition"/> instance.
/// </summary>
/// <param name="agentDefinition">AgentDefinition instance to update.</param>
private static AgentDefinition UpdateInputNames(this AgentDefinition agentDefinition)
{
Verify.NotNull(agentDefinition);

if (agentDefinition?.Inputs is not null)
{
foreach (var keyValuePair in agentDefinition.Inputs)
{
keyValuePair.Value.Name = keyValuePair.Key;
}
}

return agentDefinition!;
}
#endregion
}
Loading