diff --git a/experimental/ai/impl/pom.xml b/experimental/ai/impl/pom.xml
new file mode 100644
index 00000000..566efcc5
--- /dev/null
+++ b/experimental/ai/impl/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-parent
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-experimental-ai-impl
+ ServelessWorkflow:: Experimental:: AI:: Impl
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-types
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-types
+
+
+ dev.langchain4j
+ langchain4j
+ 1.1.0
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
diff --git a/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelCallExecutor.java b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelCallExecutor.java
new file mode 100644
index 00000000..7d64bb9a
--- /dev/null
+++ b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelCallExecutor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.impl.executors.ai;
+
+import io.serverlessworkflow.ai.api.types.CallAgentAI;
+import io.serverlessworkflow.api.types.TaskBase;
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.WorkflowModelFactory;
+import io.serverlessworkflow.impl.executors.CallableTask;
+import io.serverlessworkflow.impl.resources.ResourceLoader;
+import java.util.concurrent.CompletableFuture;
+
+public class AIChatModelCallExecutor implements CallableTask {
+
+ @Override
+ public void init(CallAgentAI task, WorkflowApplication application, ResourceLoader loader) {}
+
+ @Override
+ public CompletableFuture apply(
+ WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) {
+ WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory();
+ if (taskContext.task() instanceof CallAgentAI agenticAI) {
+ return CompletableFuture.completedFuture(
+ modelFactory.fromAny(new CallAgentAIExecutor().execute(agenticAI, input.asJavaObject())));
+ }
+ throw new IllegalArgumentException(
+ "AIChatModelCallExecutor can only process CallAgentAI tasks, but received: "
+ + taskContext.task().getClass().getName());
+ }
+
+ @Override
+ public boolean accept(Class extends TaskBase> clazz) {
+ return CallAgentAI.class.isAssignableFrom(clazz);
+ }
+}
diff --git a/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelTaskExecutorFactory.java b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelTaskExecutorFactory.java
new file mode 100644
index 00000000..c9f78360
--- /dev/null
+++ b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/AIChatModelTaskExecutorFactory.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.impl.executors.ai;
+
+import io.serverlessworkflow.impl.executors.DefaultTaskExecutorFactory;
+
+public class AIChatModelTaskExecutorFactory extends DefaultTaskExecutorFactory {}
diff --git a/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/CallAgentAIExecutor.java b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/CallAgentAIExecutor.java
new file mode 100644
index 00000000..b13ab474
--- /dev/null
+++ b/experimental/ai/impl/src/main/java/io/serverlessworkflow/impl/executors/ai/CallAgentAIExecutor.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.impl.executors.ai;
+
+import dev.langchain4j.agentic.Cognisphere;
+import dev.langchain4j.agentic.internal.AgentExecutor;
+import dev.langchain4j.agentic.internal.AgentUtil;
+import io.serverlessworkflow.ai.api.types.CallAgentAI;
+import java.util.Map;
+
+public class CallAgentAIExecutor {
+
+ private static final Cognisphere cognisphere = new Cognisphere();
+
+ public Object execute(CallAgentAI callAgentAI, Object input) {
+ AgentExecutor agentExecutor = AgentUtil.agentToExecutor(callAgentAI.getAgentInstance());
+
+ Map output = (Map) input;
+
+ cognisphere.writeStates(output);
+
+ Object result = agentExecutor.invoke(cognisphere);
+
+ output.put(callAgentAI.getAgentInstance().outputName(), result);
+ return output;
+ }
+}
diff --git a/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask b/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask
new file mode 100644
index 00000000..680fce77
--- /dev/null
+++ b/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask
@@ -0,0 +1 @@
+io.serverlessworkflow.impl.executors.ai.AIChatModelCallExecutor
\ No newline at end of file
diff --git a/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.TaskExecutorFactory b/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.TaskExecutorFactory
new file mode 100644
index 00000000..a370284d
--- /dev/null
+++ b/experimental/ai/impl/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.TaskExecutorFactory
@@ -0,0 +1 @@
+io.serverlessworkflow.impl.executors.ai.AIChatModelTaskExecutorFactory
\ No newline at end of file
diff --git a/experimental/ai/pom.xml b/experimental/ai/pom.xml
new file mode 100644
index 00000000..6856cf14
--- /dev/null
+++ b/experimental/ai/pom.xml
@@ -0,0 +1,18 @@
+
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-experimental-ai-parent
+ ServelessWorkflow:: Experimental:: AI:: Parent
+ pom
+
+ impl
+ types
+
+
\ No newline at end of file
diff --git a/experimental/ai/types/pom.xml b/experimental/ai/types/pom.xml
new file mode 100644
index 00000000..3136b81d
--- /dev/null
+++ b/experimental/ai/types/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-parent
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-experimental-ai-types
+ ServelessWorkflow:: Experimental:: AI:: Types
+
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-types
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ dev.langchain4j
+ langchain4j-agentic
+ 1.2.0-beta8-SNAPSHOT
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+ 1.2.0-SNAPSHOT
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-types
+
+
+
+
\ No newline at end of file
diff --git a/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallAgentAI.java b/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallAgentAI.java
new file mode 100644
index 00000000..dfe2910c
--- /dev/null
+++ b/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallAgentAI.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.ai.api.types;
+
+import dev.langchain4j.agentic.AgentServices;
+import dev.langchain4j.agentic.internal.AgentInstance;
+import dev.langchain4j.model.chat.ChatModel;
+import io.serverlessworkflow.api.types.TaskBase;
+import java.util.Objects;
+
+public class CallAgentAI extends TaskBase {
+
+ private AgentInstance instance;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public AgentInstance getAgentInstance() {
+ return instance;
+ }
+
+ public CallAgentAI setAgentInstance(Object object) {
+ this.instance = (AgentInstance) object;
+ return this;
+ }
+
+ public static class Builder {
+
+ private Class> agentClass;
+
+ private ChatModel chatModel;
+
+ private String outputName;
+
+ private Builder() {}
+
+ public CallAgentAI.Builder withAgentClass(Class> agentClass) {
+ this.agentClass = agentClass;
+ return this;
+ }
+
+ public CallAgentAI.Builder withChatModel(ChatModel chatModel) {
+ this.chatModel = chatModel;
+ return this;
+ }
+
+ public CallAgentAI.Builder withOutputName(String outputName) {
+ this.outputName = outputName;
+ return this;
+ }
+
+ public AgenticInnerBuilder withAgent(Object agent) {
+ return new AgenticInnerBuilder().withAgent(agent);
+ }
+
+ public CallAgentAI build() {
+ Objects.requireNonNull(agentClass, "agentClass must be provided");
+ Objects.requireNonNull(chatModel, "chatModel must be provided");
+ Objects.requireNonNull(outputName, "outputName must be provided");
+
+ if (outputName.isBlank()) {
+ throw new IllegalArgumentException("outputName must not be blank");
+ }
+
+ Object instance =
+ AgentServices.agentBuilder(agentClass)
+ .chatModel(chatModel)
+ .outputName(outputName)
+ .build();
+
+ return new AgenticInnerBuilder().withAgent(instance).build();
+ }
+
+ public static class AgenticInnerBuilder {
+
+ private Object agent;
+
+ public AgenticInnerBuilder withAgent(Object agent) {
+ this.agent = agent;
+ return this;
+ }
+
+ public CallAgentAI build() {
+ return new CallAgentAI().setAgentInstance(agent);
+ }
+ }
+ }
+}
diff --git a/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallTaskAIChatModel.java b/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallTaskAIChatModel.java
new file mode 100644
index 00000000..5dfec536
--- /dev/null
+++ b/experimental/ai/types/src/main/java/io/serverlessworkflow/ai/api/types/CallTaskAIChatModel.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.ai.api.types;
+
+import io.serverlessworkflow.api.types.CallTask;
+
+public class CallTaskAIChatModel extends CallTask {
+
+ private CallAgentAI callAIChatModel;
+
+ public CallTaskAIChatModel(CallAgentAI callAIChatModel) {
+ this.callAIChatModel = callAIChatModel;
+ }
+
+ public CallAgentAI getCallAIChatModel() {
+ return callAIChatModel;
+ }
+
+ @Override
+ public Object get() {
+ return callAIChatModel != null ? callAIChatModel : super.get();
+ }
+}
diff --git a/experimental/pom.xml b/experimental/pom.xml
index 3312207e..1c5efd8d 100644
--- a/experimental/pom.xml
+++ b/experimental/pom.xml
@@ -35,10 +35,16 @@
serverlessworkflow-fluent-func
${project.version}
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-types
+ ${project.version}
+
types
lambda
+ ai
-
\ No newline at end of file
+
diff --git a/fluent/pom.xml b/fluent/pom.xml
index ff19f4d5..caff7919 100644
--- a/fluent/pom.xml
+++ b/fluent/pom.xml
@@ -35,6 +35,11 @@
serverlessworkflow-fluent-spec
${project.version}
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-types
+ ${project.version}
+
@@ -43,4 +48,4 @@
func
-
\ No newline at end of file
+
diff --git a/fluent/spec/pom.xml b/fluent/spec/pom.xml
index 5ec62a98..fdd54289 100644
--- a/fluent/spec/pom.xml
+++ b/fluent/spec/pom.xml
@@ -27,6 +27,10 @@
junit-jupiter-api
test
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-ai-types
+
-
\ No newline at end of file
+
diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseDoTaskBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseDoTaskBuilder.java
index d4c70aec..67eaf431 100644
--- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseDoTaskBuilder.java
+++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseDoTaskBuilder.java
@@ -136,6 +136,16 @@ public TASK callHTTP(Consumer itemsConfigurer) {
return self();
}
+ public TASK callAgentAI(String name, Consumer itemsConfigurer) {
+ taskItemListBuilder.callAgentAI(name, itemsConfigurer);
+ return self();
+ }
+
+ public TASK callAgentAI(Consumer itemsConfigurer) {
+ taskItemListBuilder.callAgentAI(itemsConfigurer);
+ return self();
+ }
+
public DoTask build() {
this.doTask.setDo(this.taskItemListBuilder.build());
return this.doTask;
diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java
index bb2a34dc..934c903b 100644
--- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java
+++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java
@@ -15,6 +15,7 @@
*/
package io.serverlessworkflow.fluent.spec;
+import io.serverlessworkflow.ai.api.types.CallTaskAIChatModel;
import io.serverlessworkflow.api.types.CallTask;
import io.serverlessworkflow.api.types.Task;
import io.serverlessworkflow.api.types.TaskBase;
@@ -167,6 +168,19 @@ public SELF callHTTP(Consumer itemsConfigurer) {
return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer);
}
+ public SELF callAgentAI(String name, Consumer itemsConfigurer) {
+ requireNameAndConfig(name, itemsConfigurer);
+ final CallAgentAITaskBuilder callAgentAIBuilder = new CallAgentAITaskBuilder();
+ itemsConfigurer.accept(callAgentAIBuilder);
+ return addTaskItem(
+ new TaskItem(
+ name, new Task().withCallTask(new CallTaskAIChatModel(callAgentAIBuilder.build()))));
+ }
+
+ public SELF callAgentAI(Consumer itemsConfigurer) {
+ return this.callAgentAI(UUID.randomUUID().toString(), itemsConfigurer);
+ }
+
/**
* @return an immutable snapshot of all {@link TaskItem}s added so far
*/
diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/CallAgentAITaskBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/CallAgentAITaskBuilder.java
new file mode 100644
index 00000000..ef69342e
--- /dev/null
+++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/CallAgentAITaskBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.fluent.spec;
+
+import io.serverlessworkflow.ai.api.types.CallAgentAI;
+
+public class CallAgentAITaskBuilder extends TaskBaseBuilder {
+
+ private final CallAgentAI callAgentAI;
+
+ CallAgentAITaskBuilder() {
+ callAgentAI = new CallAgentAI();
+ super.setTask(this.callAgentAI);
+ }
+
+ @Override
+ protected CallAgentAITaskBuilder self() {
+ return this;
+ }
+
+ public CallAgentAITaskBuilder withAgent(Object agentInstance) {
+ this.callAgentAI.setAgentInstance(agentInstance);
+ return this;
+ }
+
+ public CallAgentAI build() {
+ return callAgentAI;
+ }
+}