From 7c79bc72b34bcea3b7dcf1f18d951ce84e04a393 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 22 Dec 2024 16:36:18 -0600 Subject: [PATCH 1/3] refine code --- .../BotSharp.Abstraction/Agents/IAgentService.cs | 2 +- .../BotSharp.Abstraction/Agents/Models/Agent.cs | 6 ++++++ .../BotSharp.Core/Agents/Hooks/BasicAgentHook.cs | 16 +++++++++------- .../Agents/Services/AgentService.LoadAgent.cs | 8 ++++++-- .../Agents/Services/AgentService.Rendering.cs | 6 +++++- .../Functions/ReadImageFn.cs | 15 +++++++++------ .../Providers/Chat/ChatCompletionProvider.cs | 12 ++++++++---- .../Providers/ProviderHelper.cs | 10 ++++++---- 8 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index b8945f40..91beea8b 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -18,7 +18,7 @@ public interface IAgentService /// /// /// - Task LoadAgent(string id); + Task LoadAgent(string id, bool loadUtility = true); /// /// Inherit from an agent diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 41b3800c..80d6db07 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -118,6 +118,12 @@ public class Agent [JsonIgnore] public Dictionary TemplateDict { get; set; } = new(); + [JsonIgnore] + public List SecondaryFunctions { get; set; } = []; + + [JsonIgnore] + public List SecondaryInstructions { get; set; } = []; + public override string ToString() => $"{Name} {Id}"; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 65d454c8..1101f160 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -4,6 +4,8 @@ public class BasicAgentHook : AgentHookBase { public override string SelfId => string.Empty; + private const string UTIL_PREFIX = "util-"; + public BasicAgentHook(IServiceProvider services, AgentSettings settings) : base(services, settings) { @@ -17,22 +19,23 @@ public class BasicAgentHook : AgentHookBase var isConvMode = conv.IsConversationMode(); if (!isConvMode) return; - agent.Functions ??= []; + agent.SecondaryFunctions ??= []; + agent.SecondaryInstructions ??= []; agent.Utilities ??= []; var (functions, templates) = GetUtilityContent(agent); foreach (var fn in functions) { - if (!agent.Functions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase))) + if (!agent.SecondaryFunctions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase))) { - agent.Functions.Add(fn); + agent.SecondaryFunctions.Add(fn); } } foreach (var prompt in templates) { - agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; + agent.SecondaryInstructions.Add(prompt); } } @@ -67,14 +70,13 @@ public class BasicAgentHook : AgentHookBase return ([], []); } - var prefix = "util-"; utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? []; var functionNames = utilities.SelectMany(x => x.Functions) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix)) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) .Select(x => x.Name) .Distinct().ToList(); var templateNames = utilities.SelectMany(x => x.Templates) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix)) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) .Select(x => x.Name) .Distinct().ToList(); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index 0e9c2e3c..9e6ad8ee 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -8,7 +8,7 @@ public partial class AgentService public static ConcurrentDictionary> AgentParameterTypes = new(); [MemoryCache(10 * 60, perInstanceCache: true)] - public async Task LoadAgent(string id) + public async Task LoadAgent(string id, bool loadUtility = true) { if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString()) { @@ -67,7 +67,11 @@ public partial class AgentService hook.OnSamplesLoaded(agent.Samples); } - hook.OnAgentUtilityLoaded(agent); + if (loadUtility) + { + hook.OnAgentUtilityLoaded(agent); + } + hook.OnAgentLoaded(agent); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index ba76e310..b0038f35 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -11,13 +11,17 @@ public partial class AgentService var render = _services.GetRequiredService(); var conv = _services.GetRequiredService(); + // merge instructions + var texts = new List { agent.Instruction }; + texts.AddRange(agent.SecondaryInstructions ?? []); + // update states foreach (var t in conv.States.GetStates()) { agent.TemplateDict[t.Key] = t.Value; } - var res = render.Render(agent.Instruction, agent.TemplateDict); + var res = render.Render(string.Join("\r\n", texts), agent.TemplateDict); return res; } diff --git a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs index e2c4f8c2..64b5a7ae 100644 --- a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs +++ b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs @@ -24,17 +24,20 @@ public class ReadImageFn : IFunctionCallback var wholeDialogs = conv.GetDialogHistory(); var dialogs = AssembleFiles(conv.ConversationId, args?.ImageUrls, wholeDialogs); - var agentId = !string.IsNullOrWhiteSpace(message.CurrentAgentId) ? message.CurrentAgentId : BuiltInAgentId.UtilityAssistant; - var agent = await agentService.LoadAgent(agentId); - var fileAgent = new Agent + var agent = new Agent { - Id = agent?.Id ?? Guid.Empty.ToString(), - Name = agent?.Name ?? "Unkown", + Id = BuiltInAgentId.UtilityAssistant, + Name = "Utility Agent", Instruction = !string.IsNullOrWhiteSpace(args?.UserRequest) ? args.UserRequest : "Please describe the image(s).", TemplateDict = new Dictionary() }; - var response = await GetChatCompletion(fileAgent, dialogs); + if (!string.IsNullOrEmpty(message.CurrentAgentId)) + { + agent = await agentService.LoadAgent(message.CurrentAgentId, loadUtility: false); + } + + var response = await GetChatCompletion(agent, dialogs); message.Content = response; return true; } diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs index 50151513..244a3a73 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -1,5 +1,7 @@ using BotSharp.Abstraction.Files.Utilities; +using BotSharp.Abstraction.Templating; using OpenAI.Chat; +using static System.Net.Mime.MediaTypeNames; namespace BotSharp.Plugin.OpenAI.Providers.Chat; @@ -208,7 +210,9 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - foreach (var function in agent.Functions) + + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; @@ -220,10 +224,10 @@ public class ChatCompletionProvider : IChatCompletion functionParameters: BinaryData.FromObjectAsJson(property))); } - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { - var instruction = agentService.RenderedInstruction(agent); - messages.Add(new SystemChatMessage(instruction)); + var text = agentService.RenderedInstruction(agent); + messages.Add(new SystemChatMessage(text)); } if (!string.IsNullOrEmpty(agent.Knowledges)) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs index 7ab56b5d..1f73a71d 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs @@ -9,10 +9,12 @@ public class ProviderHelper { var settingsService = services.GetRequiredService(); var settings = settingsService.GetSetting(provider, model); - var options = string.IsNullOrEmpty(settings.Endpoint) - ? null - : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; - return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); + //var options = string.IsNullOrEmpty(settings.Endpoint) + // ? null + // : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; + //return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); + var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey)); + return client; } public static List GetChatSamples(List lines) From 1d964f59a63f3c98c5d70eec62d713f54e57dfba Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 22 Dec 2024 16:37:08 -0600 Subject: [PATCH 2/3] clean code --- .../BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs index 1f73a71d..b385b380 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs @@ -9,10 +9,6 @@ public class ProviderHelper { var settingsService = services.GetRequiredService(); var settings = settingsService.GetSetting(provider, model); - //var options = string.IsNullOrEmpty(settings.Endpoint) - // ? null - // : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; - //return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey)); return client; } From ac72106e11b3394fcb3cb238cd2ccbe7ac75c25e Mon Sep 17 00:00:00 2001 From: Jicheng Lu Date: Thu, 26 Dec 2024 00:18:02 -0600 Subject: [PATCH 3/3] clean code --- .../Agents/Services/AgentService.Rendering.cs | 7 ++++--- .../Providers/ChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/ChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/GeminiChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/PalmChatCompletionProvider.cs | 7 ++++--- .../Providers/ChatCompletionProvider.cs | 7 +++++-- .../MicrosoftExtensionsAIChatCompletionProvider.cs | 3 ++- .../Providers/Chat/ChatCompletionProvider.cs | 1 - .../Providers/ChatCompletionProvider.cs | 5 +++-- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index b0038f35..d217d2c1 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -12,8 +12,9 @@ public partial class AgentService var conv = _services.GetRequiredService(); // merge instructions - var texts = new List { agent.Instruction }; - texts.AddRange(agent.SecondaryInstructions ?? []); + var instructions = new List { agent.Instruction }; + var secondaryInstructions = agent.SecondaryInstructions?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList() ?? []; + instructions.AddRange(secondaryInstructions); // update states foreach (var t in conv.States.GetStates()) @@ -21,7 +22,7 @@ public partial class AgentService agent.TemplateDict[t.Key] = t.Value; } - var res = render.Render(string.Join("\r\n", texts), agent.TemplateDict); + var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict); return res; } diff --git a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs index 8b90d29f..45ef200e 100644 --- a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs @@ -101,7 +101,7 @@ public class ChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { instruction += agentService.RenderedInstruction(agent); } @@ -197,7 +197,8 @@ public class ChatCompletionProvider : IChatCompletion ReferenceHandler = ReferenceHandler.IgnoreCycles, }; - foreach (var fn in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var fn in functions) { /*var inputschema = new InputSchema() { diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs index a1684c9d..bfce9d98 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -230,7 +230,8 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; @@ -242,7 +243,7 @@ public class ChatCompletionProvider : IChatCompletion functionParameters: BinaryData.FromObjectAsJson(property))); } - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(new SystemChatMessage(instruction)); diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs index 4419048b..c37284b0 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs @@ -107,7 +107,7 @@ public class GeminiChatCompletionProvider : IChatCompletion var funcDeclarations = new List(); var systemPrompts = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); contents.Add(new Content(instruction) @@ -119,7 +119,8 @@ public class GeminiChatCompletionProvider : IChatCompletion } var funcPrompts = new List(); - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs index 851792a6..5c507ee9 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs @@ -99,7 +99,7 @@ public class PalmChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { prompt += agentService.RenderedInstruction(agent); } @@ -110,10 +110,11 @@ public class PalmChatCompletionProvider : IChatCompletion var messages = conversations.Select(c => new PalmChatMessage(c.Content, c.Role == AgentRole.User ? "user" : "AI")) .ToList(); - if (agent.Functions != null && agent.Functions.Count > 0) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + if (!functions.IsNullOrEmpty()) { prompt += "\r\n\r\n[Functions] defined in JSON Schema:\r\n"; - prompt += JsonSerializer.Serialize(agent.Functions, new JsonSerializerOptions + prompt += JsonSerializer.Serialize(functions, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true diff --git a/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs index c702a7ec..f99293f4 100644 --- a/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Utilities; + namespace BotSharp.Plugin.MetaGLM.Providers; public class ChatCompletionProvider : IChatCompletion @@ -86,7 +88,7 @@ public class ChatCompletionProvider : IChatCompletion List messages = new List(); List toolcalls = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(new MessageItem("system", instruction)); @@ -105,7 +107,8 @@ public class ChatCompletionProvider : IChatCompletion new MessageItem("assistant", message.Content)); } - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { var functionTool = ConvertToFunctionTool(function); toolcalls.Add(functionTool); diff --git a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs index 67f1e513..37869050 100644 --- a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs @@ -66,7 +66,8 @@ public sealed class MicrosoftExtensionsAIChatCompletionProvider : IChatCompletio if (_services.GetService() is { } agentService) { - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (agentService.RenderFunction(agent, function)) { diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs index 845cd978..6f424c33 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -210,7 +210,6 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); foreach (var function in functions) { diff --git a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs index d15345e6..5edf4708 100644 --- a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs @@ -176,7 +176,7 @@ public class ChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); var messages = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(ChatMessage.FromSystem(instruction)); @@ -193,7 +193,8 @@ public class ChatCompletionProvider : IChatCompletion ChatMessage.FromAssistant(message.Content)); } - foreach (var function in agent.Functions) + var agentFuncs = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in agentFuncs) { functions.Add(ConvertToFunctionDef(function)); }