Skip to content

Commit dfd266c

Browse files
committed
Allow extending agent with additional properties
Any configuration key that's not a property of AIAgent is available via the IHasAdditionalProperties.AdditionalProperties implemented by the configurable agent.
1 parent 2d5ee94 commit dfd266c

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

src/Agents/AgentExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ public static ChatResponse AsChatResponse(this AgentRunResponse response)
2323

2424
return chatResponse;
2525
}
26+
27+
extension(AIAgent agent)
28+
{
29+
/// <summary>Gets the emoji associated with the agent, if any.</summary>
30+
public string? Emoji => agent is not IHasAdditionalProperties additional
31+
? null
32+
: additional.AdditionalProperties is null
33+
? null
34+
: additional.AdditionalProperties.TryGetValue("Emoji", out var value) ? value as string : null;
35+
}
2636
}

src/Agents/ConfigurableAIAgent.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Devlooped.Agents.AI;
1515
/// A configuration-driven <see cref="AIAgent"/> which monitors configuration changes and
1616
/// re-applies them to the inner agent automatically.
1717
/// </summary>
18-
public sealed partial class ConfigurableAIAgent : AIAgent, IDisposable
18+
public sealed partial class ConfigurableAIAgent : AIAgent, IHasAdditionalProperties, IDisposable
1919
{
2020
readonly IServiceProvider services;
2121
readonly IConfiguration configuration;
@@ -57,6 +57,9 @@ Type t when typeof(AIAgentMetadata).IsAssignableFrom(t) => metadata,
5757
_ => agent.GetService(serviceType, serviceKey)
5858
};
5959

60+
/// <inheritdoc/>
61+
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
62+
6063
/// <inheritdoc/>
6164
public override string Id => agent.Id;
6265
/// <inheritdoc/>
@@ -89,6 +92,20 @@ public override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(IEnum
8992
options?.Description = options?.Description?.Dedent();
9093
options?.Instructions = options?.Instructions?.Dedent();
9194

95+
var properties = configSection.Get<AdditionalPropertiesDictionary>();
96+
if (properties is not null)
97+
{
98+
properties?.Remove(nameof(AgentClientOptions.Name));
99+
properties?.Remove(nameof(AgentClientOptions.Description));
100+
properties?.Remove(nameof(AgentClientOptions.Instructions));
101+
properties?.Remove(nameof(AgentClientOptions.Client));
102+
properties?.Remove(nameof(AgentClientOptions.Model));
103+
properties?.Remove(nameof(AgentClientOptions.Use));
104+
properties?.Remove(nameof(AgentClientOptions.Tools));
105+
106+
AdditionalProperties = properties;
107+
}
108+
92109
// If there was a custom id, we must validate it didn't change since that's not supported.
93110
if (configuration[$"{section}:name"] is { } newname && newname != name)
94111
throw new InvalidOperationException($"The name of a configured agent cannot be changed at runtime. Expected '{name}' but was '{newname}'.");
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Microsoft.Extensions.AI;
2+
3+
namespace Devlooped.Agents.AI;
4+
5+
/// <summary>Indicates that the instance can have additional properties associated with it.</summary>
6+
public interface IHasAdditionalProperties
7+
{
8+
/// <summary>Gets or sets any additional properties associated with the instance.</summary>
9+
AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
10+
}

src/Tests/ConfigurableAgentTests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public void CanConfigureAgent()
2525
["ai:agents:bot:description"] = "Helpful chat agent",
2626
["ai:agents:bot:instructions"] = "You are a helpful chat agent.",
2727
["ai:agents:bot:options:temperature"] = "0.5",
28+
["ai:agents:bot:emoji"] = "🤖",
2829
});
2930

3031
builder.AddAIAgents();
@@ -36,6 +37,10 @@ public void CanConfigureAgent()
3637
Assert.Equal("chat", agent.Name);
3738
Assert.Equal("chat", agent.DisplayName);
3839
Assert.Equal("Helpful chat agent", agent.Description);
40+
41+
var additional = Assert.IsType<IHasAdditionalProperties>(agent, exactMatch: false);
42+
Assert.Equal("🤖", additional.AdditionalProperties?["emoji"]?.ToString());
43+
Assert.Equal("🤖", agent.Emoji);
3944
}
4045

4146
[Fact]

0 commit comments

Comments
 (0)