diff --git a/Directory.Packages.props b/Directory.Packages.props
index 4b31b218..7bd645a5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -38,6 +38,7 @@
+
@@ -45,7 +46,7 @@
-
+
diff --git a/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs b/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
index 89f097ae..9dce26cd 100644
--- a/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
+++ b/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
@@ -47,7 +47,11 @@ protected override async ValueTask ExecuteAsync(ActivityExecutionContext context
var agentInvoker = context.GetRequiredService();
var result = await agentInvoker.InvokeAgentAsync(AgentName, functionInput, context.CancellationToken);
- var json = result.FunctionResult.GetValue();
+ var json = result.ChatMessageContent.Content?.Trim();
+
+ if (string.IsNullOrWhiteSpace(json))
+ throw new InvalidOperationException("The message content is empty or null.");
+
var outputType = context.ActivityDescriptor.Outputs.Single().Type;
// If the target type is object, we want the JSON to be deserialized into an ExpandoObject for dynamic field access.
diff --git a/src/modules/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj b/src/modules/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj
index 0879dc1d..77e8b563 100644
--- a/src/modules/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj
+++ b/src/modules/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj
@@ -3,7 +3,7 @@
Provides Agent activities
elsa extension module agents semantic kernel llm ai
-
+
diff --git a/src/modules/agents/Elsa.Agents.Core/Contracts/IkernelFactory.cs b/src/modules/agents/Elsa.Agents.Core/Contracts/IkernelFactory.cs
new file mode 100644
index 00000000..7b14d61d
--- /dev/null
+++ b/src/modules/agents/Elsa.Agents.Core/Contracts/IkernelFactory.cs
@@ -0,0 +1,8 @@
+using Microsoft.SemanticKernel;
+namespace Elsa.Agents;
+
+public interface IKernelFactory
+{
+ Kernel CreateKernel(KernelConfig kernelConfig, AgentConfig agentConfig);
+ Kernel CreateKernel(KernelConfig kernelConfig, string agentName);
+}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj b/src/modules/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj
index 28b86c8a..bdb4be65 100644
--- a/src/modules/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj
+++ b/src/modules/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/modules/agents/Elsa.Agents.Core/Extensions/AgentConfigExtensions.cs b/src/modules/agents/Elsa.Agents.Core/Extensions/AgentConfigExtensions.cs
index 2a4cdc6f..5afbbab3 100644
--- a/src/modules/agents/Elsa.Agents.Core/Extensions/AgentConfigExtensions.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Extensions/AgentConfigExtensions.cs
@@ -20,6 +20,7 @@ public static OpenAIPromptExecutionSettings ToOpenAIPromptExecutionSettings(this
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
ResponseFormat = agentConfig.ExecutionSettings.ResponseFormat,
ChatSystemPrompt = agentConfig.PromptTemplate,
+ ServiceId = "default"
};
}
diff --git a/src/modules/agents/Elsa.Agents.Core/Extensions/FunctionResultExtensions.cs b/src/modules/agents/Elsa.Agents.Core/Extensions/FunctionResultExtensions.cs
index ba02314f..90b66954 100644
--- a/src/modules/agents/Elsa.Agents.Core/Extensions/FunctionResultExtensions.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Extensions/FunctionResultExtensions.cs
@@ -8,18 +8,24 @@ public static class FunctionResultExtensions
public static async Task AsJsonElementAsync(this Task resultTask)
{
var result = await resultTask;
- return result.FunctionResult.AsJsonElement();
+ return result.ChatMessageContent.AsJsonElement();
}
-
- public static async Task AsJsonElementAsync(this Task resultTask)
- {
- var result = await resultTask;
- return result.AsJsonElement();
- }
-
- public static JsonElement AsJsonElement(this FunctionResult result)
+
+ public static JsonElement AsJsonElement(this ChatMessageContent result)
{
- var response = result.GetValue()!;
- return JsonSerializer.Deserialize(response);
+ var content = result.Content?.Trim();
+
+ if (string.IsNullOrWhiteSpace(content))
+ throw new InvalidOperationException("The message content is empty.");
+
+ try
+ {
+ return JsonSerializer.Deserialize(content!);
+ }
+ catch (JsonException ex)
+ {
+ throw new InvalidOperationException($"Error deserializing the message content as JSON:\n{content}", ex);
+ }
+
}
}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Models/InvokeAgentResult.cs b/src/modules/agents/Elsa.Agents.Core/Models/InvokeAgentResult.cs
index ee2732b9..d7b032ba 100644
--- a/src/modules/agents/Elsa.Agents.Core/Models/InvokeAgentResult.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Models/InvokeAgentResult.cs
@@ -3,12 +3,8 @@
namespace Elsa.Agents;
-public record InvokeAgentResult(AgentConfig Function, FunctionResult FunctionResult)
+public record InvokeAgentResult(AgentConfig Function, ChatMessageContent ChatMessageContent)
{
- public object? ParseResult()
- {
- var targetType = Type.GetType(Function.OutputVariable.Type) ?? typeof(JsonElement);
- var json = FunctionResult.GetValue();
- return JsonSerializer.Deserialize(json, targetType);
- }
+
+
}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Services/AgentInvoker.cs b/src/modules/agents/Elsa.Agents.Core/Services/AgentInvoker.cs
index a40458c5..907caae4 100644
--- a/src/modules/agents/Elsa.Agents.Core/Services/AgentInvoker.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Services/AgentInvoker.cs
@@ -1,12 +1,14 @@
using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.PromptTemplates.Handlebars;
#pragma warning disable SKEXP0010
#pragma warning disable SKEXP0001
namespace Elsa.Agents;
-public class AgentInvoker(KernelFactory kernelFactory, IKernelConfigProvider kernelConfigProvider)
+public class AgentInvoker(IKernelFactory kernelFactory, IKernelConfigProvider kernelConfigProvider)
{
public async Task InvokeAgentAsync(string agentName, IDictionary input, CancellationToken cancellationToken = default)
{
@@ -21,9 +23,9 @@ public async Task InvokeAgentAsync(string agentName, IDiction
MaxTokens = executionSettings.MaxTokens,
PresencePenalty = executionSettings.PresencePenalty,
FrequencyPenalty = executionSettings.FrequencyPenalty,
- ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
ResponseFormat = executionSettings.ResponseFormat,
ChatSystemPrompt = agentConfig.PromptTemplate,
+ FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var promptExecutionSettingsDictionary = new Dictionary
@@ -46,10 +48,36 @@ public async Task InvokeAgentAsync(string agentName, IDiction
AllowDangerouslySetContent = true
}).ToList()
};
-
- var kernelFunction = kernel.CreateFunctionFromPrompt(promptTemplateConfig);
+
+ var templateFactory = new HandlebarsPromptTemplateFactory();
+
+ var promptConfig = new PromptTemplateConfig
+ {
+ Template = agentConfig.PromptTemplate,
+ TemplateFormat = "handlebars",
+ Name = agentConfig.FunctionName
+ };
+
+ var promptTemplate = templateFactory.Create(promptConfig);
+
var kernelArguments = new KernelArguments(input);
- var result = await kernelFunction.InvokeAsync(kernel, kernelArguments, cancellationToken: cancellationToken);
- return new(agentConfig, result);
+ string renderedPrompt = await promptTemplate.RenderAsync(kernel, kernelArguments);
+
+ ChatHistory chatHistory = [];
+ chatHistory.AddUserMessage(renderedPrompt);
+
+ IChatCompletionService chatCompletion = kernel.GetRequiredService();
+
+ OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
+ {
+ FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
+ };
+
+ var response = await chatCompletion.GetChatMessageContentAsync(
+ chatHistory,
+ executionSettings: openAIPromptExecutionSettings,
+ kernel: kernel);
+
+ return new(agentConfig, response);
}
}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Services/KernelFactory.cs b/src/modules/agents/Elsa.Agents.Core/Services/KernelFactory.cs
index bdc738f4..9b8dfaf8 100644
--- a/src/modules/agents/Elsa.Agents.Core/Services/KernelFactory.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Services/KernelFactory.cs
@@ -7,7 +7,7 @@
namespace Elsa.Agents;
-public class KernelFactory(IPluginDiscoverer pluginDiscoverer, IServiceDiscoverer serviceDiscoverer, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, ILogger logger)
+public class KernelFactory(IPluginDiscoverer pluginDiscoverer, IServiceDiscoverer serviceDiscoverer, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, ILogger logger) : IKernelFactory
{
public Kernel CreateKernel(KernelConfig kernelConfig, string agentName)
{