diff --git a/Directory.Build.props b/Directory.Build.props
index 720ea1eb..e56b8c0a 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -37,8 +37,8 @@
- 3.6.0-rc1
- 3.6.0-rc1
+ 3.6.0-preview.4162
+ 3.6.0-preview.1345
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8efbcf46..5f351d6e 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -140,6 +140,9 @@
+
+
+
diff --git a/src/modules/agents/Elsa.Agents.Activities/Activities/ConfiguredAgentActivity.cs b/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
similarity index 95%
rename from src/modules/agents/Elsa.Agents.Activities/Activities/ConfiguredAgentActivity.cs
rename to src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
index 49b66dbe..92797d09 100644
--- a/src/modules/agents/Elsa.Agents.Activities/Activities/ConfiguredAgentActivity.cs
+++ b/src/modules/agents/Elsa.Agents.Activities/Activities/AgentActivity.cs
@@ -15,10 +15,10 @@
namespace Elsa.Agents.Activities;
///
-/// An activity that executes a function of a skilled agent. This is an internal activity that is used by .
+/// An activity that executes a function of a skilled agent. This is an internal activity that is used by .
///
[Browsable(false)]
-public class ConfiguredAgentActivity : CodeActivity
+public class AgentActivity : CodeActivity
{
private static JsonSerializerOptions? _serializerOptions;
diff --git a/src/modules/agents/Elsa.Agents.Activities/Activities/CodeFirstAgentActivity.cs b/src/modules/agents/Elsa.Agents.Activities/Activities/CodeFirstAgentActivity.cs
deleted file mode 100644
index 8d988402..00000000
--- a/src/modules/agents/Elsa.Agents.Activities/Activities/CodeFirstAgentActivity.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System.ComponentModel;
-using System.Dynamic;
-using System.Reflection;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using Elsa.Expressions.Helpers;
-using Elsa.Agents.Activities.ActivityProviders;
-using Elsa.Workflows;
-using Elsa.Workflows.Models;
-using static Elsa.Agents.Activities.Extensions.ResponseHelpers;
-
-namespace Elsa.Agents.Activities;
-
-///
-/// An activity that executes a function of a skilled agent. This is an internal activity that is used by .
-///
-[Browsable(false)]
-public class CodeFirstAgentActivity : CodeActivity
-{
- private static JsonSerializerOptions? _serializerOptions;
-
- [JsonIgnore] internal string AgentName { get; set; } = null!;
- [JsonIgnore] internal string MethodName { get; set; } = null!;
-
- ///
- protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
- {
- var cancellationToken = context.CancellationToken;
- var activityDescriptor = context.ActivityDescriptor;
- var inputDescriptors = activityDescriptor.Inputs;
- var functionInput = new Dictionary();
-
- foreach (var inputDescriptor in inputDescriptors)
- {
- var input = (Input?)inputDescriptor.ValueGetter(this);
- var inputValue = input != null ? context.Get(input.MemoryBlockReference()) : null;
-
- if (inputValue is ExpandoObject expandoObject)
- inputValue = expandoObject.ConvertTo();
-
- functionInput[inputDescriptor.Name] = inputValue;
- }
-
- // Resolve the agent via the unified abstraction.
- var agentResolver = context.GetRequiredService();
- var agent = await agentResolver.ResolveAsync(AgentName, cancellationToken);
- var agentType = agent.GetType();
- var agentPropertyLookup = agentType.GetProperties().ToDictionary(x => x.Name, x => x);
-
- // Copy activity input descriptor values into the agent public properties:
- foreach (var inputDescriptor in inputDescriptors)
- {
- var input = (Input?)inputDescriptor.ValueGetter(this);
- var inputValue = input != null ? context.Get(input.MemoryBlockReference()) : null;
- agentPropertyLookup[inputDescriptor.Name].SetValue(agent, inputValue);
- }
-
- // Invoke the specified method on the agent using reflection
- var method = agentType.GetMethod(MethodName, BindingFlags.Instance | BindingFlags.Public);
- if (method == null)
- throw new InvalidOperationException($"Method '{MethodName}' not found on agent type '{agentType.Name}'.");
-
- var agentExecutionContext = new AgentExecutionContext { CancellationToken = context.CancellationToken };
- var task = method.Invoke(agent, new object[] { agentExecutionContext }) as Task;
- if (task == null)
- throw new InvalidOperationException($"Method '{MethodName}' did not return a Task.");
-
- var agentExecutionResponse = await task;
- var responseText = StripCodeFences(agentExecutionResponse.Text);
- var isJsonResponse = IsJsonResponse(responseText);
- var outputType = context.ActivityDescriptor.Outputs.Single().Type;
-
- // If the target type is object and the response is in JSON format, we want it to be deserialized into an ExpandoObject for dynamic field access.
- if (outputType == typeof(object) && isJsonResponse)
- outputType = typeof(ExpandoObject);
-
- var outputValue = isJsonResponse ? responseText.ConvertTo(outputType) : responseText;
- var outputDescriptor = activityDescriptor.Outputs.Single();
- var output = (Output?)outputDescriptor.ValueGetter(this);
- context.Set(output, outputValue, "Output");
- }
-}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/ConfiguredAgentActivityProvider.cs b/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs
similarity index 94%
rename from src/modules/agents/Elsa.Agents.Activities/ActivityProviders/ConfiguredAgentActivityProvider.cs
rename to src/modules/agents/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs
index 70ea85a7..4d4d8972 100644
--- a/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/ConfiguredAgentActivityProvider.cs
+++ b/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs
@@ -12,7 +12,7 @@ namespace Elsa.Agents.Activities.ActivityProviders;
/// Provides activities for each registered agent.
///
[UsedImplicitly]
-public class ConfigurationAgentActivityProvider(
+public class AgentActivityProvider(
IKernelConfigProvider kernelConfigProvider,
IActivityDescriber activityDescriber,
IWellKnownTypeRegistry wellKnownTypeRegistry
@@ -37,7 +37,7 @@ public async ValueTask> GetDescriptorsAsync(Canc
private async Task CreateAgentActivityDescriptor(AgentConfig agentConfig, CancellationToken cancellationToken)
{
- var activityDescriptor = await activityDescriber.DescribeActivityAsync(typeof(ConfiguredAgentActivity), cancellationToken);
+ var activityDescriptor = await activityDescriber.DescribeActivityAsync(typeof(AgentActivity), cancellationToken);
var functionName = string.IsNullOrWhiteSpace(agentConfig.FunctionName) ? agentConfig.Name : agentConfig.FunctionName;
var activityTypeName = $"Elsa.Agents.{activityDescriptor.Name.Pascalize()}.{functionName.Pascalize()}";
activityDescriptor.Name = functionName.Pascalize();
@@ -48,11 +48,11 @@ private async Task CreateAgentActivityDescriptor(AgentConfig
activityDescriptor.Category = "Agents";
activityDescriptor.Kind = ActivityKind.Task;
activityDescriptor.RunAsynchronously = true;
- activityDescriptor.ClrType = typeof(ConfiguredAgentActivity);
+ activityDescriptor.ClrType = typeof(AgentActivity);
activityDescriptor.Constructor = context =>
{
- var activity = context.CreateActivity();
+ var activity = context.CreateActivity();
activity.Type = activityTypeName;
activity.AgentName = agentConfig.Name;
activity.RunAsynchronously = true;
diff --git a/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/CodeFirstAgentActivityProvider.cs b/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/CodeFirstAgentActivityProvider.cs
deleted file mode 100644
index 8a5aeb79..00000000
--- a/src/modules/agents/Elsa.Agents.Activities/ActivityProviders/CodeFirstAgentActivityProvider.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-using System.ComponentModel;
-using System.ComponentModel.DataAnnotations;
-using System.Reflection;
-using Elsa.Expressions.Contracts;
-using Elsa.Expressions.Extensions;
-using Elsa.Extensions;
-using Elsa.Workflows;
-using Elsa.Workflows.Models;
-using Humanizer;
-using JetBrains.Annotations;
-using Microsoft.Extensions.Options;
-
-namespace Elsa.Agents.Activities.ActivityProviders;
-
-///
-/// Provides activities for each code-first agent registered via .
-/// Inputs are derived from public properties on the agent type using simple
-/// reflection rules. Execution is delegated to
-/// via the common abstraction.
-///
-[UsedImplicitly]
-public class CodeFirstAgentActivityProvider(
- IOptions agentOptions,
- IActivityDescriber activityDescriber,
- IWellKnownTypeRegistry wellKnownTypeRegistry) : IActivityProvider
-{
- public async ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default)
- {
- var descriptors = new List();
-
- foreach (var kvp in agentOptions.Value.AgentTypes)
- {
- var key = kvp.Key;
- var type = kvp.Value;
- var agentDescriptors = await CreateDescriptorsForAgentAsync(key, type, cancellationToken);
- descriptors.AddRange(agentDescriptors);
- }
-
- return descriptors;
- }
-
- private async Task> CreateDescriptorsForAgentAsync(string key, Type agentType, CancellationToken cancellationToken)
- {
- var descriptors = new List();
-
- // Discover all public methods that match the signature: async Task MethodName(AgentExecutionContext)
- var methods = agentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
- .Where(IsAgentActionMethod)
- .ToList();
-
- foreach (var method in methods)
- {
- var descriptor = await CreateDescriptorForAgentMethodAsync(key, agentType, method, cancellationToken);
- descriptors.Add(descriptor);
- }
-
- return descriptors;
- }
-
- private async Task CreateDescriptorForAgentMethodAsync(string agentKey, Type agentType, MethodInfo method, CancellationToken cancellationToken)
- {
- var descriptor = await activityDescriber.DescribeActivityAsync(typeof(CodeFirstAgentActivity), cancellationToken);
- var methodName = method.Name;
- var activityTypeName = $"Elsa.Agents.CodeFirst.{agentKey.Pascalize()}.{methodName}";
-
- // Strip "Async" suffix for display purposes
- var displayMethodName = methodName.EndsWith("Async", StringComparison.Ordinal)
- ? methodName[..^5]
- : methodName;
-
- // Check for DisplayAttribute
- var displayAttribute = method.GetCustomAttribute();
- var displayName = displayAttribute?.Name ?? displayMethodName.Humanize().Transform(To.TitleCase);
-
- descriptor.Name = methodName;
- descriptor.TypeName = activityTypeName;
- descriptor.DisplayName = displayName;
- descriptor.Description = method.GetCustomAttribute()?.Description;
- descriptor.Category = "Agents";
- descriptor.Kind = ActivityKind.Task;
- descriptor.RunAsynchronously = true;
- descriptor.IsBrowsable = true;
- descriptor.ClrType = typeof(CodeFirstAgentActivity);
-
- descriptor.Constructor = context =>
- {
- var activity = context.CreateActivity();
- activity.Type = activityTypeName;
- activity.AgentName = agentKey;
- activity.MethodName = methodName;
- activity.RunAsynchronously = true;
- return activity;
- };
-
- // Build inputs from public instance properties.
- descriptor.Inputs.Clear();
- foreach (var prop in agentType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
- {
- if (!IsInputProperty(prop))
- continue;
-
- var inputName = prop.Name;
- var inputType = prop.PropertyType.FullName ?? "object";
- var nakedInputType = wellKnownTypeRegistry.GetTypeOrDefault(inputType);
- var description = prop.GetCustomAttribute()?.Description;
-
- var inputDescriptor = new InputDescriptor
- {
- Name = inputName,
- DisplayName = inputName.Humanize(),
- Description = description,
- Type = nakedInputType,
- ValueGetter = activity => activity.SyntheticProperties.GetValueOrDefault(inputName),
- ValueSetter = (activity, value) => activity.SyntheticProperties[inputName] = value!,
- IsSynthetic = true,
- IsWrapped = true,
- UIHint = ActivityDescriber.GetUIHint(nakedInputType)
- };
-
- descriptor.Inputs.Add(inputDescriptor);
- }
-
- // For now, expose a single synthetic Output of type object, mirroring
- // the existing AgentActivity behavior.
- descriptor.Outputs.Clear();
- var outputName = "Output";
- var outputDescriptor = new OutputDescriptor
- {
- Name = outputName,
- Description = "The agent's output.",
- Type = typeof(object),
- IsSynthetic = true,
- ValueGetter = activity => activity.SyntheticProperties.GetValueOrDefault(outputName),
- ValueSetter = (activity, value) => activity.SyntheticProperties[outputName] = value!,
- };
- descriptor.Outputs.Add(outputDescriptor);
-
- return descriptor;
- }
-
- private static bool IsAgentActionMethod(MethodInfo method)
- {
- // Must return Task
- if (method.ReturnType != typeof(Task))
- return false;
-
- // Must have exactly one parameter of type AgentExecutionContext
- var parameters = method.GetParameters();
- if (parameters.Length != 1)
- return false;
-
- if (parameters[0].ParameterType != typeof(AgentExecutionContext))
- return false;
-
- return true;
- }
-
- private static bool IsInputProperty(PropertyInfo prop)
- {
- // Simple heuristic for now:
- // - Must be readable and writable
- // - Exclude indexers
- if (!prop.CanRead || !prop.CanWrite)
- return false;
-
- if (prop.GetIndexParameters().Length > 0)
- return false;
-
- // In the future, you can add a dedicated [AgentInput] attribute and
- // check for it here. For now, treat all simple public properties as
- // potential inputs.
- return true;
- }
-}
-
diff --git a/src/modules/agents/Elsa.Agents.Activities/Features/AgentActivitiesFeature.cs b/src/modules/agents/Elsa.Agents.Activities/Features/AgentActivitiesFeature.cs
index 046e72c4..7202e1b6 100644
--- a/src/modules/agents/Elsa.Agents.Activities/Features/AgentActivitiesFeature.cs
+++ b/src/modules/agents/Elsa.Agents.Activities/Features/AgentActivitiesFeature.cs
@@ -22,8 +22,7 @@ public class AgentActivitiesFeature(IModule module) : FeatureBase(module)
public override void Apply()
{
Services
- .AddActivityProvider()
- .AddActivityProvider()
+ .AddActivityProvider()
.AddNotificationHandler()
;
}
diff --git a/src/modules/agents/Elsa.Agents.Activities/Handlers/RefreshActivityRegistry.cs b/src/modules/agents/Elsa.Agents.Activities/Handlers/RefreshActivityRegistry.cs
index 8db3830f..6cc0bcf2 100644
--- a/src/modules/agents/Elsa.Agents.Activities/Handlers/RefreshActivityRegistry.cs
+++ b/src/modules/agents/Elsa.Agents.Activities/Handlers/RefreshActivityRegistry.cs
@@ -7,7 +7,7 @@
namespace Elsa.Agents.Activities.Handlers;
[UsedImplicitly]
-public class RefreshActivityRegistry(IActivityRegistry activityRegistry, ConfigurationAgentActivityProvider configurationAgentActivityProvider) :
+public class RefreshActivityRegistry(IActivityRegistry activityRegistry, AgentActivityProvider agentActivityProvider) :
INotificationHandler,
INotificationHandler,
INotificationHandler,
@@ -17,5 +17,5 @@ public class RefreshActivityRegistry(IActivityRegistry activityRegistry, Configu
public Task HandleAsync(AgentDefinitionUpdated notification, CancellationToken cancellationToken) => RefreshRegistryAsync(cancellationToken);
public Task HandleAsync(AgentDefinitionDeleted notification, CancellationToken cancellationToken) => RefreshRegistryAsync(cancellationToken);
public Task HandleAsync(AgentDefinitionsDeletedInBulk notification, CancellationToken cancellationToken) => RefreshRegistryAsync(cancellationToken);
- private Task RefreshRegistryAsync(CancellationToken cancellationToken) => activityRegistry.RefreshDescriptorsAsync(configurationAgentActivityProvider, cancellationToken);
+ private Task RefreshRegistryAsync(CancellationToken cancellationToken) => activityRegistry.RefreshDescriptorsAsync(agentActivityProvider, cancellationToken);
}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Contracts/IAgent.cs b/src/modules/agents/Elsa.Agents.Core/Contracts/IAgent.cs
deleted file mode 100644
index 36b11f7f..00000000
--- a/src/modules/agents/Elsa.Agents.Core/Contracts/IAgent.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Elsa.Agents;
-
-///
-/// Minimal abstraction to represent a code-first agent that can be automatically discovered as an activity.
-/// Implementing classes should define public async Task methods accepting as a parameter.
-/// Each such method will be automatically discovered and exposed as an activity.
-///
-public interface IAgent;
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Contracts/IAgentResolver.cs b/src/modules/agents/Elsa.Agents.Core/Contracts/IAgentResolver.cs
deleted file mode 100644
index bd27d0fc..00000000
--- a/src/modules/agents/Elsa.Agents.Core/Contracts/IAgentResolver.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Elsa.Agents;
-
-///
-/// Defines the contract for resolving agents by their names.
-///
-public interface IAgentResolver
-{
- ///
- /// Resolves an agent instance by its name asynchronously.
- ///
- /// The name of the agent to resolve.
- /// A token to monitor for cancellation requests.
- /// The resolved agent instance.
- Task ResolveAsync(string agentName, CancellationToken cancellationToken = default);
-}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Features/AgentsCoreFeature.cs b/src/modules/agents/Elsa.Agents.Core/Features/AgentsCoreFeature.cs
index 6a70e6ba..840f106d 100644
--- a/src/modules/agents/Elsa.Agents.Core/Features/AgentsCoreFeature.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Features/AgentsCoreFeature.cs
@@ -12,7 +12,7 @@ namespace Elsa.Agents.Features;
[UsedImplicitly]
public class AgentsCoreFeature(IModule module) : FeatureBase(module)
{
- private Func _kernelConfigProviderFactory = sp => sp.GetRequiredService();
+ private Func _kernelConfigProviderFactory = sp => sp.GetRequiredService();
public AgentsCoreFeature UseKernelConfigProvider(Func factory)
{
@@ -30,8 +30,7 @@ public override void Apply()
.AddScoped()
.AddScoped()
.AddScoped(_kernelConfigProviderFactory)
- .AddScoped()
- .AddScoped()
+ .AddScoped()
.AddSkillsProvider()
.AddSkillsProvider()
;
diff --git a/src/modules/agents/Elsa.Agents.Core/Models/AgentExecutionContext.cs b/src/modules/agents/Elsa.Agents.Core/Models/AgentExecutionContext.cs
deleted file mode 100644
index 861604e9..00000000
--- a/src/modules/agents/Elsa.Agents.Core/Models/AgentExecutionContext.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Elsa.Agents;
-
-public class AgentExecutionContext
-{
- public string Message { get; set; } = null!;
- public CancellationToken CancellationToken { get; set; }
-}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Options/AgentsOptions.cs b/src/modules/agents/Elsa.Agents.Core/Options/AgentsOptions.cs
index 809dd36b..e5e1b3a5 100644
--- a/src/modules/agents/Elsa.Agents.Core/Options/AgentsOptions.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Options/AgentsOptions.cs
@@ -4,20 +4,4 @@ public class AgentsOptions
{
public ICollection Agents { get; set; } = new List();
public ICollection ServiceDescriptors { get; set; } = new List();
-
- ///
- /// Map from agent key to the implementing type. Keys are case-insensitive.
- ///
- public IDictionary AgentTypes { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
- ///
- /// Registers a code-first agent type. If no key is provided, the type name
- /// is used as the key.
- ///
- public AgentsOptions AddAgentType(string? key = null) where TAgent : class, IAgent
- {
- key ??= typeof(TAgent).Name;
- AgentTypes[key] = typeof(TAgent);
- return this;
- }
}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Services/AgentResolver.cs b/src/modules/agents/Elsa.Agents.Core/Services/AgentResolver.cs
deleted file mode 100644
index 14ab5390..00000000
--- a/src/modules/agents/Elsa.Agents.Core/Services/AgentResolver.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-
-namespace Elsa.Agents;
-
-public class AgentResolver(IServiceProvider serviceProvider, IOptions options) : IAgentResolver
-{
- public Task ResolveAsync(string agentName, CancellationToken cancellationToken = default)
- {
- var agentType = options.Value.AgentTypes[agentName] ?? throw new InvalidOperationException($"No agent with name '{agentName}' was found.");
- var agent = (IAgent)ActivatorUtilities.CreateInstance(serviceProvider, agentType)!;
- return Task.FromResult(agent);
- }
-}
\ No newline at end of file
diff --git a/src/modules/agents/Elsa.Agents.Core/Services/ConfigurationKernelConfigProvider.cs b/src/modules/agents/Elsa.Agents.Core/Services/KernelConfigProvider.cs
similarity index 84%
rename from src/modules/agents/Elsa.Agents.Core/Services/ConfigurationKernelConfigProvider.cs
rename to src/modules/agents/Elsa.Agents.Core/Services/KernelConfigProvider.cs
index 469d8256..295d9899 100644
--- a/src/modules/agents/Elsa.Agents.Core/Services/ConfigurationKernelConfigProvider.cs
+++ b/src/modules/agents/Elsa.Agents.Core/Services/KernelConfigProvider.cs
@@ -7,7 +7,7 @@ namespace Elsa.Agents;
/// Provides kernel configuration from configuration.
///
[UsedImplicitly]
-public class ConfigurationKernelConfigProvider(IOptions options) : IKernelConfigProvider
+public class KernelConfigProvider(IOptions options) : IKernelConfigProvider
{
public Task GetKernelConfigAsync(CancellationToken cancellationToken = default)
{
diff --git a/src/modules/agents/Elsa.Agents/AgentsFeature.cs b/src/modules/agents/Elsa.Agents/AgentsFeature.cs
index 239850d6..0e94c49d 100644
--- a/src/modules/agents/Elsa.Agents/AgentsFeature.cs
+++ b/src/modules/agents/Elsa.Agents/AgentsFeature.cs
@@ -11,12 +11,6 @@ namespace Elsa.Agents;
[DependsOn(typeof(AgentActivitiesFeature))]
public class AgentsFeature(IModule module) : FeatureBase(module)
{
- public AgentsFeature AddAgent(string? key = null) where TAgent : class, IAgent
- {
- Module.Services.Configure(options => options.AddAgentType(key));
- return this;
- }
-
public AgentsFeature AddServiceDescriptor(ServiceDescriptor descriptor)
{
Module.Services.Configure(options => options.ServiceDescriptors.Add(descriptor));
diff --git a/src/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj b/src/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj
index aae3d865..fa34185c 100644
--- a/src/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj
+++ b/src/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj
@@ -30,6 +30,9 @@
+
+
+