diff --git a/impl/grpc/pom.xml b/impl/grpc/pom.xml
new file mode 100644
index 000000000..620584030
--- /dev/null
+++ b/impl/grpc/pom.xml
@@ -0,0 +1,48 @@
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-impl
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-impl-grpc
+ Serverless Workflow :: Impl :: gRPC
+
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ io.serverlessworkflow
+ serverlessworkflow-api
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-jackson
+
+
+ io.grpc
+ grpc-stub
+
+
+ com.google.protobuf
+ protobuf-java
+ 3.25.8
+
+
+ com.google.protobuf
+ protobuf-java-util
+ 3.25.8
+
+
+ com.github.os72
+ protoc-jar
+ ${version.com.github.os72.protoc.jar}
+
+
+ io.grpc
+ grpc-protobuf
+
+
+
\ No newline at end of file
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContext.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContext.java
new file mode 100644
index 000000000..a111e9dd0
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContext.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.grpc;
+
+import com.google.protobuf.DescriptorProtos;
+
+public record FileDescriptorContext(
+ DescriptorProtos.FileDescriptorSet fileDescriptorSet, String inputProto) {}
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContextSupplier.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContextSupplier.java
new file mode 100644
index 000000000..1f416a9a5
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorContextSupplier.java
@@ -0,0 +1,27 @@
+/*
+ * 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.grpc;
+
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowModel;
+
+@FunctionalInterface
+public interface FileDescriptorContextSupplier {
+
+ FileDescriptorContext get(
+ WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input);
+}
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorReader.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorReader.java
new file mode 100644
index 000000000..638d5c513
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/FileDescriptorReader.java
@@ -0,0 +1,111 @@
+/*
+ * 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.grpc;
+
+import com.github.os72.protocjar.Protoc;
+import com.google.protobuf.DescriptorProtos;
+import io.serverlessworkflow.impl.resources.ExternalResourceHandler;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Optional;
+
+public class FileDescriptorReader {
+
+ public FileDescriptorContext readDescriptor(ExternalResourceHandler externalResourceHandler) {
+ Path grpcDir =
+ tryCreateTempGrpcDir()
+ .orElseThrow(
+ () -> new IllegalStateException("Could not create temporary gRPC directory"));
+
+ try (InputStream inputStream = externalResourceHandler.open()) {
+
+ Path protoFile = grpcDir.resolve(externalResourceHandler.name());
+ if (!Files.exists(protoFile)) {
+ Files.createDirectories(protoFile);
+ }
+
+ Files.copy(inputStream, protoFile, StandardCopyOption.REPLACE_EXISTING);
+
+ Path descriptorOutput = grpcDir.resolve("descriptor.protobin");
+
+ try {
+
+ generateFileDescriptor(grpcDir, protoFile, descriptorOutput);
+
+ DescriptorProtos.FileDescriptorSet fileDescriptorSet =
+ DescriptorProtos.FileDescriptorSet.newBuilder()
+ .mergeFrom(Files.readAllBytes(descriptorOutput))
+ .build();
+
+ return new FileDescriptorContext(fileDescriptorSet, externalResourceHandler.name());
+
+ } catch (IOException e) {
+ throw new UncheckedIOException(
+ "Unable to read external resource handler: " + externalResourceHandler.name(), e);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Unable to read descriptor file", e);
+ }
+ }
+
+ private Optional tryCreateTempGrpcDir() {
+ try {
+ return Optional.of(Files.createTempDirectory("serverless-workflow-"));
+ } catch (IOException e) {
+ throw new UncheckedIOException("Error while creating temporary gRPC directory", e);
+ }
+ }
+
+ /**
+ * Calls protoc binary with --descriptor_set_out= option set.
+ *
+ * @param grpcDir a temporary directory
+ * @param protoFile the .proto file used by protoc to generate the file descriptor
+ * @param descriptorOutput the output directory where the descriptor file will be generated
+ */
+ private static void generateFileDescriptor(Path grpcDir, Path protoFile, Path descriptorOutput) {
+ String[] protocArgs =
+ new String[] {
+ "--include_imports",
+ "--descriptor_set_out=" + descriptorOutput.toAbsolutePath(),
+ "-I",
+ grpcDir.toAbsolutePath().toString(),
+ protoFile.toAbsolutePath().toString()
+ };
+
+ try {
+
+ int status = Protoc.runProtoc(protocArgs);
+
+ // ProcessBuilder processBuilder = new ProcessBuilder(protocArgs);
+ // int status = ScriptUtils.uncheckedStart(processBuilder).waitFor();
+
+ if (status != 0) {
+ throw new RuntimeException(
+ "Unable to generate file descriptor, 'protoc' execution failed with status " + status);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Unable to generate file descriptor", e);
+ } catch (IOException e) {
+ throw new UncheckedIOException("Unable to generate file descriptor", e);
+ }
+ }
+}
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcCallExecutor.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcCallExecutor.java
new file mode 100644
index 000000000..8de978253
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcCallExecutor.java
@@ -0,0 +1,32 @@
+/*
+ * 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.grpc;
+
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowModel;
+import java.util.Map;
+
+@FunctionalInterface
+public interface GrpcCallExecutor {
+
+ WorkflowModel apply(
+ GrpcRequestContext requestContext,
+ WorkflowContext workflowContext,
+ TaskContext taskContext,
+ WorkflowModel model,
+ Map arguments);
+}
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcChannelResolver.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcChannelResolver.java
new file mode 100644
index 000000000..c13f5de5a
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcChannelResolver.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.grpc;
+
+import io.grpc.Channel;
+import io.grpc.ManagedChannelBuilder;
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowContext;
+
+public class GrpcChannelResolver {
+
+ public static final String GRPC_CHANNEL_PROVIDER = "grpcChannelProvider";
+
+ public static Channel channel(
+ WorkflowContext workflowContext,
+ TaskContext taskContext,
+ GrpcRequestContext grpcRequestContext) {
+ WorkflowApplication appl = workflowContext.definition().application();
+ return appl.additionalObject(GRPC_CHANNEL_PROVIDER, workflowContext, taskContext)
+ .orElseGet(
+ () ->
+ ManagedChannelBuilder.forAddress(
+ grpcRequestContext.address(), grpcRequestContext.port())
+ .usePlaintext()
+ .build());
+ }
+}
diff --git a/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcExecutor.java b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcExecutor.java
new file mode 100644
index 000000000..36055c476
--- /dev/null
+++ b/impl/grpc/src/main/java/io/serverlessworkflow/impl/executors/grpc/GrpcExecutor.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.grpc;
+
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.WorkflowValueResolver;
+import io.serverlessworkflow.impl.executors.CallableTask;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+public class GrpcExecutor implements CallableTask {
+
+ private final GrpcRequestContext requestContext;
+ private final GrpcCallExecutor grpcCallExecutor;
+ private final WorkflowValueResolver