diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 75d38c7a6832af67920a926aa3eb1877ef952bde..c8d706ecb621275adc7fd92ac581a8a169b42f16 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -962,6 +962,7 @@
       <title>Start workflow</title>
       <onActionProcess>%aditoprj%/entity/Offer_entity/entityfields/startworkflow/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PLAY</iconId>
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/startworkflow/stateProcess.js</stateProcess>
     </entityActionField>
   </entityFields>
   <recordContainers>
diff --git a/entity/Offer_entity/entityfields/startworkflow/stateProcess.js b/entity/Offer_entity/entityfields/startworkflow/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef65dd9cffd2d6d81ae54a6ae35636ae946aff22
--- /dev/null
+++ b/entity/Offer_entity/entityfields/startworkflow/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("Workflow_lib");
+import("system.result");
+
+result.string(WorkflowUtils.engineIsEnabled()
+    ? neon.COMPONENTSTATE_EDITABLE
+    : neon.COMPONENTSTATE_INVISIBLE
+);
\ No newline at end of file
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 6e049802083c0df434135d38f67df82d1861742e..136ad209d51d2aa4aa2062c4f1be559dbd5c2769 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -1024,6 +1024,7 @@
       <title>Start workflow</title>
       <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/startworkflow/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PLAY</iconId>
+      <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/startworkflow/stateProcess.js</stateProcess>
     </entityActionField>
     <entityField>
       <name>STANDARD_ADDRESS</name>
diff --git a/entity/Organisation_entity/entityfields/startworkflow/stateProcess.js b/entity/Organisation_entity/entityfields/startworkflow/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef65dd9cffd2d6d81ae54a6ae35636ae946aff22
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/startworkflow/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("Workflow_lib");
+import("system.result");
+
+result.string(WorkflowUtils.engineIsEnabled()
+    ? neon.COMPONENTSTATE_EDITABLE
+    : neon.COMPONENTSTATE_INVISIBLE
+);
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 9c15a53ce05a2a603c85f70aeaedae4e05017e1b..bf4a87910fc9c95a5533dbfd7fec120fa0d71506 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -1035,6 +1035,7 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <isObjectAction v="false" />
           <isSelectionAction v="true" />
           <iconId>VAADIN:PLAY</iconId>
+          <stateProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js</stateProcess>
         </entityActionField>
       </children>
     </entityActionGroup>
@@ -1106,6 +1107,7 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
       <title>Start workflow</title>
       <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/startworkflow/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PLAY</iconId>
+      <stateProcess>%aditoprj%/entity/Person_entity/entityfields/startworkflow/stateProcess.js</stateProcess>
     </entityActionField>
     <entityActionField>
       <name>openAdminView</name>
diff --git a/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef65dd9cffd2d6d81ae54a6ae35636ae946aff22
--- /dev/null
+++ b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("Workflow_lib");
+import("system.result");
+
+result.string(WorkflowUtils.engineIsEnabled()
+    ? neon.COMPONENTSTATE_EDITABLE
+    : neon.COMPONENTSTATE_INVISIBLE
+);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/startworkflow/stateProcess.js b/entity/Person_entity/entityfields/startworkflow/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef65dd9cffd2d6d81ae54a6ae35636ae946aff22
--- /dev/null
+++ b/entity/Person_entity/entityfields/startworkflow/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("Workflow_lib");
+import("system.result");
+
+result.string(WorkflowUtils.engineIsEnabled()
+    ? neon.COMPONENTSTATE_EDITABLE
+    : neon.COMPONENTSTATE_INVISIBLE
+);
\ No newline at end of file
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index 14dae46d6d510c1da390704cc3ef4ea3836c64ee..6264e47b1343159fd643eb9d52ff7853825c145d 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -735,6 +735,7 @@
       <title>Start workflow</title>
       <onActionProcess>%aditoprj%/entity/Salesproject_entity/entityfields/startworkflow/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PLAY</iconId>
+      <stateProcess>%aditoprj%/entity/Salesproject_entity/entityfields/startworkflow/stateProcess.js</stateProcess>
     </entityActionField>
   </entityFields>
   <recordContainers>
diff --git a/entity/Salesproject_entity/entityfields/startworkflow/stateProcess.js b/entity/Salesproject_entity/entityfields/startworkflow/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef65dd9cffd2d6d81ae54a6ae35636ae946aff22
--- /dev/null
+++ b/entity/Salesproject_entity/entityfields/startworkflow/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("Workflow_lib");
+import("system.result");
+
+result.string(WorkflowUtils.engineIsEnabled()
+    ? neon.COMPONENTSTATE_EDITABLE
+    : neon.COMPONENTSTATE_INVISIBLE
+);
\ No newline at end of file
diff --git a/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod b/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
index 74998e878cfd0acc8289e3b51af2e46c2f7bd3a3..f7bbe40886f6601c68134ddaefd9114e4861d66d 100644
--- a/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
+++ b/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
@@ -3,6 +3,7 @@
   <name>WorkflowDefinition_entity</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <title>Workflow definition</title>
+  <grantCreateProcess>%aditoprj%/entity/WorkflowDefinition_entity/grantCreateProcess.js</grantCreateProcess>
   <grantDelete v="false" />
   <contentTitleProcess>%aditoprj%/entity/WorkflowDefinition_entity/contentTitleProcess.js</contentTitleProcess>
   <iconId>VAADIN:DROP</iconId>
diff --git a/entity/WorkflowDefinition_entity/grantCreateProcess.js b/entity/WorkflowDefinition_entity/grantCreateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..93bb40efb619d7627f096d88bc8bcc67be15c46f
--- /dev/null
+++ b/entity/WorkflowDefinition_entity/grantCreateProcess.js
@@ -0,0 +1,4 @@
+import("Workflow_lib");
+import("system.result");
+
+result.object(WorkflowUtils.engineIsEnabled());
\ No newline at end of file
diff --git a/entity/WorkflowDefinition_entity/recordcontainers/jdito/contentProcess.js b/entity/WorkflowDefinition_entity/recordcontainers/jdito/contentProcess.js
index 2bd181e87346374beb8b6daffec4362244aaad50..6523e43702e8fd2ac39f3fbc8222069d5abd4eff 100644
--- a/entity/WorkflowDefinition_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/WorkflowDefinition_entity/recordcontainers/jdito/contentProcess.js
@@ -5,87 +5,94 @@ import("Workflow_lib");
 import("system.workflow");
 import("JditoFilter_lib");
 
-var workflowKey = vars.get("$param.ProcessDefinitionKey_param");
-var excludeVersion = vars.get("$param.CurrentVersion_param");
-var context = vars.get("$param.Context_param");
-var idvalues = vars.get("$local.idvalues");
-
-var workflowDefs;
-
-if (idvalues)
+//immediately invoked function is used so that a return statement can be utilized to end the function at any point
+result.object((function ()
 {
-    var loadConfig = workflow.createConfigForLoadingProcessDefinitions()
-        .processDefinitionIds(idvalues);
-    workflowDefs = JSON.parse(workflow.getProcessDefinitions(loadConfig));
+    if (!WorkflowUtils.engineIsEnabled())
+        return [];
     
-    //after new-mode, the given uid is not the actual id, but the key, so if
-    //no workflow definitions were found, try it again with the key
-    if (workflowDefs.length === 0)
-        workflowDefs = _getDefinitionsByKey(idvalues[0]);
-}
-else
-{
-    workflowDefs = _getDefinitionsByKey(workflowKey);
-}
+    var workflowKey = vars.get("$param.ProcessDefinitionKey_param");
+    var excludeVersion = vars.get("$param.CurrentVersion_param");
+    var context = vars.get("$param.Context_param");
+    var idvalues = vars.get("$local.idvalues");
 
-//structure = {processDefinitionKey : highest_version}
-var newestVersions = {};
+    var workflowDefs;
 
-workflowDefs = workflowDefs.map(function (def)
-{
-    //determine the most recent version of every definition
-    if (def.version > (newestVersions[def.key] || 0))
-        newestVersions[def.key] = def.version;
-    
-    return [
-        def.id,
-        def.name,
-        def.category,
-        def.key,
-        def.version,
-        def.active,
-        def.description || ""
-    ];
-});
+    if (idvalues)
+    {
+        var loadConfig = workflow.createConfigForLoadingProcessDefinitions()
+            .processDefinitionIds(idvalues);
+        workflowDefs = JSON.parse(workflow.getProcessDefinitions(loadConfig));
 
-var possibleKeysMap = null;
-if (context)
-{
-    possibleKeysMap = {};
-    WorkflowUtils.getPossibleWorkflowDefinitions(context, $KeywordRegistry.workflowTrigger$manual()).forEach(function (key)
+        //after new-mode, the given uid is not the actual id, but the key, so if
+        //no workflow definitions were found, try it again with the key
+        if (workflowDefs.length === 0)
+            workflowDefs = _getDefinitionsByKey(idvalues[0]);
+    }
+    else
     {
-        this[key] = true;
-    }, possibleKeysMap);
-}
+        workflowDefs = _getDefinitionsByKey(workflowKey);
+    }
 
-var filterFn;
-//if excludeVersion is set -> all definitions versions with a specific key are loaded
-//if not -> load just the newest versions of all definitions
-if (!excludeVersion)
-{
-    filterFn = function (currDef)
+    //structure = {processDefinitionKey : highest_version}
+    var newestVersions = {};
+
+    workflowDefs = workflowDefs.map(function (def)
     {
-        return newestVersions[currDef[3]] == currDef[4] && (possibleKeysMap ? possibleKeysMap[currDef[3]] : true);
-    };
-}
-else
-{
-    filterFn = function (currDef)
+        //determine the most recent version of every definition
+        if (def.version > (newestVersions[def.key] || 0))
+            newestVersions[def.key] = def.version;
+
+        return [
+            def.id,
+            def.name,
+            def.category,
+            def.key,
+            def.version,
+            def.active,
+            def.description || ""
+        ];
+    });
+
+    var possibleKeysMap = null;
+    if (context)
+    {
+        possibleKeysMap = {};
+        WorkflowUtils.getPossibleWorkflowDefinitions(context, $KeywordRegistry.workflowTrigger$manual()).forEach(function (key)
+        {
+            this[key] = true;
+        }, possibleKeysMap);
+    }
+
+    var filterFn;
+    //if excludeVersion is set -> all definitions versions with a specific key are loaded
+    //if not -> load just the newest versions of all definitions
+    if (!excludeVersion)
+    {
+        filterFn = function (currDef)
+        {
+            return newestVersions[currDef[3]] == currDef[4] && (possibleKeysMap ? possibleKeysMap[currDef[3]] : true);
+        };
+    }
+    else
     {
-        return excludeVersion != currDef[4];
-    };
-}
+        filterFn = function (currDef)
+        {
+            return excludeVersion != currDef[4];
+        };
+    }
 
-workflowDefs = workflowDefs.filter(filterFn);
+    workflowDefs = workflowDefs.filter(filterFn);
 
-workflowDefs = JditoFilterUtils.filterRecords(["UID", "NAME", "CATEGORY", "KEY", "VERSION", "ISACTIVE"], workflowDefs, vars.get("$local.filter").filter);
+    workflowDefs = JditoFilterUtils.filterRecords(["UID", "NAME", "CATEGORY", "KEY", "VERSION", "ISACTIVE"], workflowDefs, vars.get("$local.filter").filter);
 
-result.object(workflowDefs);
+    return workflowDefs;
 
-function _getDefinitionsByKey (pKey)
-{
-    var config = workflow.createConfigForLoadingProcessDefinitions();
-    if (pKey)
-        config.processDefinitionKey(pKey);
-    return JSON.parse(workflow.getProcessDefinitions(config));
-}
\ No newline at end of file
+    function _getDefinitionsByKey (pKey)
+    {
+        var config = workflow.createConfigForLoadingProcessDefinitions();
+        if (pKey)
+            config.processDefinitionKey(pKey);
+        return JSON.parse(workflow.getProcessDefinitions(config));
+    }
+})());
\ No newline at end of file
diff --git a/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js b/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
index d5314b2e14b073c5abb246b2659118b73943a428..9005006abf7ec25a907adc49073eac84509848be 100644
--- a/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
@@ -11,70 +11,74 @@ import("Workflow_lib");
 import("system.vars");
 import("system.workflow");
 
-var isOnlyForCurrentUser = vars.exists("$param.OnlyForCurrentUser_param") && vars.get("$param.OnlyForCurrentUser_param") == "true";
+//immediately invoked function is used so that a return statement can be utilized to end the function at any point
+result.object((function ()
+{
+    if (!WorkflowUtils.engineIsEnabled())
+        return [];
+    
+    var isOnlyForCurrentUser = vars.exists("$param.OnlyForCurrentUser_param") && vars.get("$param.OnlyForCurrentUser_param") == "true";
 
-var loadConfig = workflow.createConfigForLoadingTasks();
-var tasks, dummyTask;
+    var loadConfig = workflow.createConfigForLoadingTasks();
+    var tasks;
 
-if (vars.get("$local.idvalues") && vars.get("$local.idvalues")[0])
-{
-    var taskId = vars.get("$local.idvalues")[0];
-    loadConfig = workflow.createConfigForLoadingTask()
-        .taskId(taskId);
-        
-    //TODO: there shouldn't be an error
-    try {
-        tasks = [JSON.parse(workflow.getTask(loadConfig))];
-    } 
-    catch (err) 
+    if (vars.get("$local.idvalues") && vars.get("$local.idvalues")[0])
     {
-        //This can happen if the task is done, then it can't be loaded. If that's the case, return a dummy row
-        tasks = [];
-        var taskTitle = vars.exists("$param.TaskTitle_param") && vars.get("$param.TaskTitle_param") || "";
-        dummyTask = [taskId, translate.text("Task done"), taskTitle, "", vars.get("$sys.date"), "", "", "", "", "", "", "", "", "", "", "", ""];
+        var taskId = vars.get("$local.idvalues")[0];
+        loadConfig = workflow.createConfigForLoadingTask()
+            .taskId(taskId);
+
+        //TODO: there shouldn't be an error
+        try {
+            tasks = [JSON.parse(workflow.getTask(loadConfig))];
+        } 
+        catch (err) 
+        {
+            //This can happen if the task is done, then it can't be loaded. If that's the case, return a dummy row
+            var taskTitle = vars.exists("$param.TaskTitle_param") && vars.get("$param.TaskTitle_param") || "";
+            return [[taskId, translate.text("Task done"), taskTitle, "", vars.get("$sys.date"), "", "", "", "", "", "", "", "", "", "", "", ""]];
+        }
+    }
+    else 
+    {
+    //    if (isOnlyForCurrentUser)
+    //        loadConfig.candidateIdentifier(EmployeeUtils.getCurrentUserId());
+        tasks = JSON.parse(workflow.getTasks(loadConfig));
     }
-}
-else 
-{
-//    if (isOnlyForCurrentUser)
-//        loadConfig.candidateIdentifier(EmployeeUtils.getCurrentUserId());
-    tasks = JSON.parse(workflow.getTasks(loadConfig));
-}
 
-tasks = tasks.map(function (task)
-{
-    var variables = JSON.parse(workflow.getTaskVariables(task.id));
-    var targetTitle = "";
-    if (variables.targetId && variables.targetContext)
-        targetTitle = ContextUtils.loadContentTitle(project.getContextStructure(variables.targetContext).entity, variables.targetId); 
-    
-    var assigneeName = task.assignee ? ContextUtils.loadContentTitle("Employee_entity", task.assignee) : "";
-    
-    return [
-        task.id,
-        task.name,
-        task.processDefinitionId,
-        task.processInstanceId,
-        Date.parse(task.createTime).toString(),
-        workflow.getFormProperties(task.id),
-        "",
-        variables.USER_ID,
-        task.description || "",
-        task.category || "",
-        task.assignee || "",
-        assigneeName,
-        task.dueDate ? Date.parse(task.dueDate).toString() : "",
-        task.owner || "",
-        variables.targetContext || "",
-        variables.targetId || "",
-        targetTitle
-    ];
-});
+    tasks = tasks.map(function (task)
+    {
+        var variables = JSON.parse(workflow.getTaskVariables(task.id));
+        var targetTitle = "";
+        if (variables.targetId && variables.targetContext)
+            targetTitle = ContextUtils.loadContentTitle(project.getContextStructure(variables.targetContext).entity, variables.targetId); 
+
+        var assigneeName = task.assignee ? ContextUtils.loadContentTitle("Employee_entity", task.assignee) : "";
+
+        return [
+            task.id,
+            task.name,
+            task.processDefinitionId,
+            task.processInstanceId,
+            Date.parse(task.createTime).toString(),
+            workflow.getFormProperties(task.id),
+            "",
+            variables.USER_ID,
+            task.description || "",
+            task.category || "",
+            task.assignee || "",
+            assigneeName,
+            task.dueDate ? Date.parse(task.dueDate).toString() : "",
+            task.owner || "",
+            variables.targetContext || "",
+            variables.targetId || "",
+            targetTitle
+        ];
+    });
 
-tasks = JditoFilterUtils.filterRecords(["UID", "NAME", "PROCESSDEFINITION_ID", "PROCESSINSTANCE_ID", 
-    "CREATE_TIME", "FORMDEFINITION", "USER", "DESCRIPTION", "CATEGORY", "ASSIGNEE", "", "DUEDATE", "OWNER"], tasks, vars.get("$local.filter").filter);
+    tasks = JditoFilterUtils.filterRecords(["UID", "NAME", "PROCESSDEFINITION_ID", "PROCESSINSTANCE_ID", 
+        "CREATE_TIME", "FORMDEFINITION", "USER", "DESCRIPTION", "CATEGORY", "ASSIGNEE", "", "DUEDATE", "OWNER"], tasks, vars.get("$local.filter").filter);
 
-if (dummyTask)
-    tasks = [dummyTask];
 
-result.object(tasks);
\ No newline at end of file
+    return tasks;
+})());
\ No newline at end of file
diff --git a/process/Workflow_lib/process.js b/process/Workflow_lib/process.js
index cb3a3298f391859f412a964aa5b4b6430855a275..67b4340100ad618ec80c194e934d71b8eccbade7 100644
--- a/process/Workflow_lib/process.js
+++ b/process/Workflow_lib/process.js
@@ -1,3 +1,4 @@
+import("system.project");
 import("Sql_lib");
 import("system.neon");
 import("Context_lib");
@@ -71,6 +72,14 @@ WorkflowUtils.appendMandatoryVariables = function (pVariables, pTargetId, pTarge
     return pVariables;
 }
 
+/**
+ * @return {boolean} if the workflow engine is enabled
+ */
+WorkflowUtils.engineIsEnabled = function ()
+{
+    return project.getInstanceConfigValue("workflowEngineEnabled", "false") == "true";
+}
+
 function WorkflowStarter () {}
 
 WorkflowStarter.TRIGGER_INSERT = function ()