diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/ExecuteTemplateArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/ExecuteTemplateArgs.cs
new file mode 100644
index 00000000..e3d2405e
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/ExecuteTemplateArgs.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.Instructs.Models;
+
+public class ExecuteTemplateArgs
+{
+ [JsonPropertyName("template_name")]
+ public string? TemplateName { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
index 00e1f30a..ad6b4e19 100644
--- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
+++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
@@ -90,6 +90,7 @@
+
@@ -187,6 +188,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/Infrastructure/BotSharp.Core/Instructs/Functions/ExecuteTemplateFn.cs b/src/Infrastructure/BotSharp.Core/Instructs/Functions/ExecuteTemplateFn.cs
new file mode 100644
index 00000000..b09019e3
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/Instructs/Functions/ExecuteTemplateFn.cs
@@ -0,0 +1,69 @@
+using BotSharp.Abstraction.Functions;
+using BotSharp.Abstraction.Instructs.Models;
+
+namespace BotSharp.Core.Instructs.Functions;
+
+public class ExecuteTemplateFn : IFunctionCallback
+{
+ public string Name => "util-instruct-execute_template";
+
+ private readonly IServiceProvider _services;
+ private readonly ILogger _logger;
+
+ public ExecuteTemplateFn(
+ IServiceProvider services,
+ ILogger logger)
+ {
+ _services = services;
+ _logger = logger;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs);
+ if (string.IsNullOrEmpty(args.TemplateName))
+ {
+ message.Content = $"Empty template name.";
+ return false;
+ }
+
+ var agentService = _services.GetRequiredService();
+ var agent = await agentService.GetAgent(message.CurrentAgentId);
+ var template = agent.Templates.FirstOrDefault(x => x.Name.IsEqualTo(args.TemplateName));
+
+ if (template == null)
+ {
+ message.Content = $"Cannot find template ({args.TemplateName}) in agent {agent.Name}";
+ return false;
+ }
+
+ var prompt = agentService.RenderedTemplate(agent, args.TemplateName);
+ var response = await GetAiResponse(agent, prompt);
+ message.Content = response;
+ return true;
+ }
+
+ private async Task GetAiResponse(Agent agent, string text)
+ {
+ try
+ {
+ var completion = CompletionProvider.GetChatCompletion(_services, provider: agent.LlmConfig?.Provider, model: agent.LlmConfig?.Model);
+ var response = await completion.GetChatCompletions(new Agent()
+ {
+ Id = agent.Id
+ },
+ new List
+ {
+ new(AgentRole.User, text)
+ });
+ return response.Content;
+ }
+ catch (Exception ex)
+ {
+ var error = $"Error when getting agent {agent.Name} instruction response.";
+ _logger.LogWarning($"{error} {ex.Message}\r\n{ex.InnerException}");
+ return error;
+ }
+
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs b/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs
new file mode 100644
index 00000000..e0c6d686
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs
@@ -0,0 +1,17 @@
+namespace BotSharp.Core.Instructs.Hooks;
+
+public class InstructUtilityHook : IAgentUtilityHook
+{
+ private static string PREFIX = "util-instruct-";
+ private static string EXECUTE_TEMPLATE = $"{PREFIX}execute_template";
+
+ public void AddUtilities(List utilities)
+ {
+ utilities.Add(new AgentUtility
+ {
+ Name = "instruct.template",
+ Functions = [new($"{EXECUTE_TEMPLATE}")],
+ Templates = [new($"{EXECUTE_TEMPLATE}.fn")]
+ });
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core/Instructs/InsturctionPlugin.cs b/src/Infrastructure/BotSharp.Core/Instructs/InsturctionPlugin.cs
index c44cb874..7bde20e8 100644
--- a/src/Infrastructure/BotSharp.Core/Instructs/InsturctionPlugin.cs
+++ b/src/Infrastructure/BotSharp.Core/Instructs/InsturctionPlugin.cs
@@ -1,6 +1,7 @@
using BotSharp.Abstraction.Instructs.Settings;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Settings;
+using BotSharp.Core.Instructs.Hooks;
using Microsoft.Extensions.Configuration;
namespace BotSharp.Core.Instructs;
@@ -18,6 +19,8 @@ public class InsturctionPlugin : IBotSharpPlugin
var settingService = provider.GetRequiredService();
return settingService.Bind("Instruction");
});
+
+ services.AddScoped();
}
public bool AttachMenu(List menu)
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs
index e6fedc05..de7a556b 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs
@@ -8,13 +8,11 @@ public class RoutingUtilityHook : IAgentUtilityHook
public void AddUtilities(List utilities)
{
- var utility = new AgentUtility
+ utilities.Add(new AgentUtility
{
Name = "routing.tools",
Functions = [new($"{REDIRECT_TO_AGENT}"), new($"{FALLBACK_TO_ROUTER}")],
Templates = [new($"{REDIRECT_TO_AGENT}.fn"), new($"{FALLBACK_TO_ROUTER}.fn")]
- };
-
- utilities.Add(utility);
+ });
}
}
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-instruct-execute_template.json b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-instruct-execute_template.json
new file mode 100644
index 00000000..52780e61
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-instruct-execute_template.json
@@ -0,0 +1,14 @@
+{
+ "name": "util-instruct-execute_template",
+ "description": "Select a specific template that can handle the user's request.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "template_name": {
+ "type": "string",
+ "description": "The template name that is selected for handling the request."
+ }
+ },
+ "required": [ "template_name" ]
+ }
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-instruct-execute_template.fn.liquid b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-instruct-execute_template.fn.liquid
new file mode 100644
index 00000000..78291d3b
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-instruct-execute_template.fn.liquid
@@ -0,0 +1,3 @@
+please call function util-routing-execute_template if user wants to use a template to fulfill a specific task.
+Please ensure the template is executed only once.
+Please output the template response directly without changing anthything.
\ No newline at end of file