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
16 changes: 16 additions & 0 deletions dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRunOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using Microsoft.Extensions.AI;
using Microsoft.Shared.Diagnostics;

namespace Microsoft.Agents.AI;
Expand Down Expand Up @@ -32,6 +33,7 @@ public AgentRunOptions(AgentRunOptions options)
_ = Throw.IfNull(options);
this.ContinuationToken = options.ContinuationToken;
this.AllowBackgroundResponses = options.AllowBackgroundResponses;
this.AdditionalProperties = options.AdditionalProperties?.Clone();
}

/// <summary>
Expand Down Expand Up @@ -74,4 +76,18 @@ public AgentRunOptions(AgentRunOptions options)
/// </para>
/// </remarks>
public bool? AllowBackgroundResponses { get; set; }

/// <summary>
/// Gets or sets additional properties associated with these options.
/// </summary>
/// <value>
/// An <see cref="AdditionalPropertiesDictionary"/> containing custom properties,
/// or <see langword="null"/> if no additional properties are present.
/// </value>
/// <remarks>
/// Additional properties provide a way to include custom metadata or provider-specific
/// information that doesn't fit into the standard options schema. This is useful for
/// preserving implementation-specific details or extending the options with custom data.
/// </remarks>
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ public void CloningConstructorCopiesProperties()
var options = new AgentRunOptions
{
ContinuationToken = new object(),
AllowBackgroundResponses = true
AllowBackgroundResponses = true,
AdditionalProperties = new AdditionalPropertiesDictionary
{
["key1"] = "value1",
["key2"] = 42
}
};

// Act
Expand All @@ -28,6 +33,10 @@ public void CloningConstructorCopiesProperties()
Assert.NotNull(clone);
Assert.Same(options.ContinuationToken, clone.ContinuationToken);
Assert.Equal(options.AllowBackgroundResponses, clone.AllowBackgroundResponses);
Assert.NotNull(clone.AdditionalProperties);
Assert.NotSame(options.AdditionalProperties, clone.AdditionalProperties);
Assert.Equal("value1", clone.AdditionalProperties["key1"]);
Assert.Equal(42, clone.AdditionalProperties["key2"]);
}

[Fact]
Expand All @@ -42,7 +51,12 @@ public void JsonSerializationRoundtrips()
var options = new AgentRunOptions
{
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
AllowBackgroundResponses = true
AllowBackgroundResponses = true,
AdditionalProperties = new AdditionalPropertiesDictionary
{
["key1"] = "value1",
["key2"] = 42
}
};

// Act
Expand All @@ -54,5 +68,13 @@ public void JsonSerializationRoundtrips()
Assert.NotNull(deserialized);
Assert.Equivalent(ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }), deserialized!.ContinuationToken);
Assert.Equal(options.AllowBackgroundResponses, deserialized.AllowBackgroundResponses);
Assert.NotNull(deserialized.AdditionalProperties);
Assert.Equal(2, deserialized.AdditionalProperties.Count);
Assert.True(deserialized.AdditionalProperties.TryGetValue("key1", out object? value1));
Assert.IsType<JsonElement>(value1);
Assert.Equal("value1", ((JsonElement)value1!).GetString());
Assert.True(deserialized.AdditionalProperties.TryGetValue("key2", out object? value2));
Assert.IsType<JsonElement>(value2);
Assert.Equal(42, ((JsonElement)value2!).GetInt32());
}
}
Loading