You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by la...@apache.org on 2025/10/06 01:54:29 UTC

(airavata) 04/04: agent pull batch job unit assignment implementation

This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch vizfold
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit a31c44e6d288982c656eb759a684246f5de0fe55
Author: lahiruj <la...@gmail.com>
AuthorDate: Sun Oct 5 21:52:27 2025 -0400

    agent pull batch job unit assignment implementation
---
 .../connection/service/db/repo/JobUnitRepo.java    |   36 +-
 .../service/handlers/AgentConnectionHandler.java   |   41 +
 .../service/handlers/AgentWorkService.java         |   63 +
 .../service/handlers/JobUnitAllocator.java         |   66 +
 .../connection/service/models/AssignResult.java    |   47 +
 modules/agent-framework/airavata-agent/agent.go    |  125 +-
 .../protos/agent-communication.pb.go               | 1423 ++++++++++++++------
 .../protos/agent-communication_grpc.pb.go          |   22 +-
 .../proto/agent-communication.proto                |   28 +
 9 files changed, 1377 insertions(+), 474 deletions(-)

diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/db/repo/JobUnitRepo.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/db/repo/JobUnitRepo.java
index 02f9261352..5c8293af6a 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/db/repo/JobUnitRepo.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/db/repo/JobUnitRepo.java
@@ -1,4 +1,3 @@
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -21,8 +20,43 @@ package org.apache.airavata.agent.connection.service.db.repo;
 
 import org.apache.airavata.agent.connection.service.db.entity.JobUnitEntity;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public interface JobUnitRepo extends JpaRepository<JobUnitEntity, String> {
+
+    @Query(value = """
+            SELECT ID
+            FROM JOB_UNIT
+            WHERE BATCH_ID = :batchId AND STATUS = 'PENDING'
+            ORDER BY CREATED_AT, ID
+            FOR UPDATE SKIP LOCKED
+            LIMIT 1
+            """, nativeQuery = true)
+    String lockNextPending(@Param("batchId") String batchId);
+
+    @Modifying
+    @Query(value = """
+            UPDATE JOB_UNIT SET STATUS='IN_PROGRESS', AGENT_ID=:agentId, STARTED_AT=CURRENT_TIMESTAMP(6) WHERE ID=:id
+            """, nativeQuery = true)
+    int markInProgress(@Param("id") String id, @Param("agentId") String agentId);
+
+    @Query(value = "SELECT RESOLVED_COMMAND FROM JOB_UNIT WHERE ID=:id", nativeQuery = true)
+    String getResolvedCommand(@Param("id") String id);
+
+    @Modifying
+    @Query(value = """
+            UPDATE JOB_UNIT SET STATUS='COMPLETED', COMPLETED_AT=CURRENT_TIMESTAMP(6) WHERE ID=:id
+            """, nativeQuery = true)
+    int markCompleted(@Param("id") String id);
+
+    @Query(value = """
+            SELECT COUNT(*)
+            FROM JOB_UNIT
+            WHERE BATCH_ID = :batchId AND STATUS IN ('PENDING','IN_PROGRESS')
+            """, nativeQuery = true)
+    int countRemaining(@Param("batchId") String batchId);
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
index 56a8f54fce..693dc9345d 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
@@ -57,6 +57,8 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
     private final Map<String, PythonExecutionResponse> PYTHON_EXECUTION_RESPONSE_CACHE = new ConcurrentHashMap<>();
     private final Map<String, TunnelCreationResponse> TUNNEL_CREATION_RESPONSE_CACHE = new ConcurrentHashMap<>();
 
+    private final AgentWorkService agentWorkService;
+
     @Value("${airavata.tunnel.serverHost}")
     private String tunnelServerHost;
 
@@ -69,6 +71,10 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
     @Value("${airavata.tunnel.serverToken}")
     private String tunnelServerToken;
 
+    public AgentConnectionHandler(AgentWorkService agentWorkService) {
+        this.agentWorkService = agentWorkService;
+    }
+
     // response handling
     public AgentInfoResponse isAgentUp(String agentId) {
         if (AGENT_STREAM_MAPPING.containsKey(agentId)
@@ -602,6 +608,33 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
         PYTHON_EXECUTION_RESPONSE_CACHE.put(executionResponse.getExecutionId(), executionResponse);
     }
 
+    private void handleNextJobUnitRequest(String agentId, StreamObserver<ServerMessage> responseObserver) {
+        logger.info("Received next job unit request for agent id {}", agentId);
+        AssignResult assignResult = agentWorkService.assignNextForAgent(agentId);
+
+        try {
+            if (assignResult instanceof AssignResult.Assigned assigned) {
+                responseObserver.onNext(ServerMessage.newBuilder().setAssignJobUnit(AssignJobUnit.newBuilder()
+                        .setJobUnitId(assigned.jobUnitId())
+                        .setResolvedCommand(assigned.resolvedCommand())
+                        .build()).build());
+                logger.info("Assigned job unit id {} to agent id {}", assigned.jobUnitId(), agentId);
+
+            } else if (assignResult instanceof AssignResult.NoWork noWork) {
+                responseObserver.onNext(ServerMessage.newBuilder().setNoJobUnitAvailable(NoJobUnitAvailable.newBuilder()
+                        .setReason(noWork.reason())
+                        .build()).build());
+                logger.info("No job unit available for agent id {}, reason: {}", agentId, noWork.reason());
+            }
+        } catch (Exception e) {
+            logger.error("Failed to send reply to agent {}", agentId, e);
+        }
+    }
+
+    private void handleJobUnitCompletion(String jobUnitId) {
+        agentWorkService.markCompleted(jobUnitId);
+    }
+
     // routing
     private Optional<StreamObserver<ServerMessage>> getAgentStreamObserver(String agentId) {
         if (AGENT_STREAM_MAPPING.containsKey(agentId)
@@ -659,6 +692,14 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
                     case ASYNCCOMMANDTERMINATERESPONSE -> {
                         handleAsyncCommandTerminateResponse(request.getAsyncCommandTerminateResponse());
                     }
+
+                    case REQUESTNEXTJOBUNIT -> {
+                        handleNextJobUnitRequest(request.getRequestNextJobUnit().getAgentId(), responseObserver);
+                    }
+
+                    case JOBUNITCOMPLETED -> {
+                        handleJobUnitCompletion(request.getJobUnitCompleted().getJobUnitId());
+                    }
                 }
             }
 
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentWorkService.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentWorkService.java
new file mode 100644
index 0000000000..0771ddaa4c
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentWorkService.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.airavata.agent.connection.service.handlers;
+
+import org.apache.airavata.agent.connection.service.db.entity.AgentBatchAssignmentEntity;
+import org.apache.airavata.agent.connection.service.db.repo.AgentBatchAssignmentRepo;
+import org.apache.airavata.agent.connection.service.db.repo.JobUnitRepo;
+import org.apache.airavata.agent.connection.service.models.AssignResult;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Service
+public class AgentWorkService {
+
+    private final AgentBatchAssignmentRepo assignmentRepo;
+    private final JobUnitAllocator allocator;
+    private final JobUnitRepo jobUnitRepo;
+
+    public AgentWorkService(AgentBatchAssignmentRepo assignmentRepo, JobUnitAllocator allocator, JobUnitRepo jobUnitRepo) {
+        this.assignmentRepo = assignmentRepo;
+        this.allocator = allocator;
+        this.jobUnitRepo = jobUnitRepo;
+    }
+
+    public AssignResult assignNextForAgent(String agentId) {
+        Optional<AgentBatchAssignmentEntity> absOp = assignmentRepo.findByAgentId(agentId);
+        if (absOp.isEmpty()) {
+            return AssignResult.noAssignment();
+        }
+
+        var batchId = absOp.get().getBatchId();
+        Optional<JobUnitAllocator.JobUnitRow> next = allocator.allocateNext(batchId, agentId);
+        if (next.isPresent()) {
+            JobUnitAllocator.JobUnitRow row = next.get();
+            return AssignResult.assigned(row.id(), row.resolvedCommand());
+        }
+
+        int remaining = jobUnitRepo.countRemaining(batchId);
+        return (remaining == 0) ? AssignResult.emptyAllDone() : AssignResult.empty();
+    }
+
+    public void markCompleted(String jobUnitId) {
+        allocator.markCompleted(jobUnitId);
+    }
+}
+
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/JobUnitAllocator.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/JobUnitAllocator.java
new file mode 100644
index 0000000000..fd8b48bb6b
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/JobUnitAllocator.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.airavata.agent.connection.service.handlers;
+
+import jakarta.transaction.Transactional;
+import org.apache.airavata.agent.connection.service.db.repo.JobUnitRepo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Service
+public class JobUnitAllocator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JobUnitAllocator.class);
+
+    private final JobUnitRepo jobUnitRepo;
+
+    public record JobUnitRow(String id, String resolvedCommand) {
+    }
+
+    public JobUnitAllocator(JobUnitRepo jobUnitRepo) {
+        this.jobUnitRepo = jobUnitRepo;
+    }
+
+    @Transactional
+    public Optional<JobUnitRow> allocateNext(String batchId, String agentId) {
+        String id = jobUnitRepo.lockNextPending(batchId);
+        LOGGER.info("Job unit {} allocated to agent {}", id, agentId);
+        if (id == null) {
+            return Optional.empty();
+        }
+
+        if (jobUnitRepo.markInProgress(id, agentId) != 1) {
+            // If another agent grabbed the same job unit
+            LOGGER.warn("Job unit {} is already in progress by an agent", id);
+            return Optional.empty();
+        }
+
+        String cmd = jobUnitRepo.getResolvedCommand(id);
+        return Optional.of(new JobUnitRow(id, cmd));
+    }
+
+    @Transactional
+    public void markCompleted(String jobUnitId) {
+        int result = jobUnitRepo.markCompleted(jobUnitId);
+        LOGGER.info("Job unit {} marked as completed with result {}", jobUnitId, result);
+    }
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AssignResult.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AssignResult.java
new file mode 100644
index 0000000000..1103a9c408
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AssignResult.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.airavata.agent.connection.service.models;
+
+public sealed interface AssignResult permits AssignResult.Assigned, AssignResult.NoWork {
+
+    record Assigned(String jobUnitId, String resolvedCommand) implements AssignResult {
+    }
+
+    record NoWork(String reason) implements AssignResult {
+        public static final String EMPTY = "EMPTY";
+        public static final String EMPTY_ALL_DONE = "EMPTY_ALL_DONE";
+        public static final String NO_ASSIGNMENT = "NO_ASSIGNMENT";
+    }
+
+    static Assigned assigned(String id, String cmd) {
+        return new Assigned(id, cmd);
+    }
+
+    static NoWork empty() {
+        return new NoWork(NoWork.EMPTY);
+    }
+
+    static NoWork emptyAllDone() {
+        return new NoWork(NoWork.EMPTY_ALL_DONE);
+    }
+
+    static NoWork noAssignment() {
+        return new NoWork(NoWork.NO_ASSIGNMENT);
+    }
+}
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-agent/agent.go b/modules/agent-framework/airavata-agent/agent.go
index 06cfe6d6a3..e1d270b47f 100644
--- a/modules/agent-framework/airavata-agent/agent.go
+++ b/modules/agent-framework/airavata-agent/agent.go
@@ -20,12 +20,14 @@ package main
 import (
 	protos "airavata-agent/protos"
 	"context"
+	"errors"
 	"flag"
 	"io"
 	"log"
 	"os"
 	"os/exec"
 	"strings"
+	"time"
 
 	"airavata-agent/pkg"
 
@@ -37,6 +39,11 @@ type Stream = grpc.BidiStreamingClient[protos.AgentMessage, protos.ServerMessage
 
 var defaultLibs = []string{"python<3.12", "pip", "ipykernel", "git", "flask", "jupyter_client", "ttyd"}
 
+const (
+	noWorkBackoff   = 3 * time.Second // sleep between polls when no work
+	maxEmptyReplies = 3               // exit after 3 consecutive empty replies
+)
+
 func main() {
 
 	// Define flags with default empty values.
@@ -144,9 +151,11 @@ func main() {
 	}
 	log.Printf("[agent.go] main() Connected to the server.\n")
 
+	requestNextJobUnit(stream, *agentId)
+
 	// start interceptor
 	ch := make(chan struct{})
-	go startInterceptor(stream, ch)
+	go startInterceptor(stream, ch, *agentId, *environ)
 
 	<-ch
 
@@ -156,7 +165,9 @@ func main() {
 
 }
 
-func startInterceptor(stream Stream, grpcStreamChannel chan struct{}) {
+func startInterceptor(stream Stream, grpcStreamChannel chan struct{}, agentId string, envName string) {
+	consecutiveEmpty := 0
+	pollingJobEnabled := true
 
 	for {
 		in, err := stream.Recv()
@@ -173,34 +184,34 @@ func startInterceptor(stream Stream, grpcStreamChannel chan struct{}) {
 		case *protos.ServerMessage_EnvSetupRequest:
 			log.Printf("[agent.go] Recived a env setup request\n")
 			executionId := x.EnvSetupRequest.ExecutionId
-			envName := x.EnvSetupRequest.EnvName
+			envNameReq := x.EnvSetupRequest.EnvName
 			envLibs := x.EnvSetupRequest.Libraries
 			envPip := x.EnvSetupRequest.Pip
-			go pkg.CreateEnv(stream, executionId, envName, append(envLibs, defaultLibs...), envPip)
+			go pkg.CreateEnv(stream, executionId, envNameReq, append(envLibs, defaultLibs...), envPip)
 
 		case *protos.ServerMessage_PythonExecutionRequest:
 			log.Printf("[agent.go] Recived a python execution request\n")
 			executionId := x.PythonExecutionRequest.ExecutionId
-			envName := x.PythonExecutionRequest.EnvName
+			envNameReq := x.PythonExecutionRequest.EnvName
 			workingDir := x.PythonExecutionRequest.WorkingDir
 			code := x.PythonExecutionRequest.Code
-			go pkg.ExecutePython(stream, executionId, envName, workingDir, code)
+			go pkg.ExecutePython(stream, executionId, envNameReq, workingDir, code)
 
 		case *protos.ServerMessage_CommandExecutionRequest:
 			log.Printf("[agent.go] Recived a shell execution request\n")
 			executionId := x.CommandExecutionRequest.ExecutionId
-			envName := x.CommandExecutionRequest.EnvName
+			envNameReq := x.CommandExecutionRequest.EnvName
 			workingDir := x.CommandExecutionRequest.WorkingDir
 			execArgs := x.CommandExecutionRequest.Arguments
-			go pkg.ExecuteShell(stream, executionId, envName, workingDir, execArgs)
+			go pkg.ExecuteShell(stream, executionId, envNameReq, workingDir, execArgs)
 
 		case *protos.ServerMessage_AsyncCommandExecutionRequest:
 			log.Printf("[agent.go] Recived a async shell execution request\n")
 			executionId := x.AsyncCommandExecutionRequest.ExecutionId
-			envName := x.AsyncCommandExecutionRequest.EnvName
+			envNameReq := x.AsyncCommandExecutionRequest.EnvName
 			workingDir := x.AsyncCommandExecutionRequest.WorkingDir
 			execArgs := x.AsyncCommandExecutionRequest.Arguments
-			go pkg.ExecuteShellAsync(stream, executionId, envName, workingDir, execArgs)
+			go pkg.ExecuteShellAsync(stream, executionId, envNameReq, workingDir, execArgs)
 
 		case *protos.ServerMessage_AsyncCommandListRequest:
 			log.Printf("[agent.go] Recived async shell list request\n")
@@ -216,15 +227,15 @@ func startInterceptor(stream Stream, grpcStreamChannel chan struct{}) {
 		case *protos.ServerMessage_JupyterExecutionRequest:
 			log.Printf("[agent.go] Recived a jupyter execution request\n")
 			executionId := x.JupyterExecutionRequest.ExecutionId
-			envName := x.JupyterExecutionRequest.EnvName
+			envNameReq := x.JupyterExecutionRequest.EnvName
 			code := x.JupyterExecutionRequest.Code
-			go pkg.ExecuteJupyter(stream, executionId, envName, code)
+			go pkg.ExecuteJupyter(stream, executionId, envNameReq, code)
 
 		case *protos.ServerMessage_KernelRestartRequest:
 			log.Printf("[agent.go] Recived a kernel restart request\n")
 			executionId := x.KernelRestartRequest.ExecutionId
-			envName := x.KernelRestartRequest.EnvName
-			go pkg.RestartKernel(stream, executionId, envName)
+			envNameReq := x.KernelRestartRequest.EnvName
+			go pkg.RestartKernel(stream, executionId, envNameReq)
 
 		case *protos.ServerMessage_TunnelCreationRequest:
 			log.Printf("[agent.go] Received a tunnel creation request\n")
@@ -248,7 +259,93 @@ func startInterceptor(stream Stream, grpcStreamChannel chan struct{}) {
 			} else {
 				log.Printf("[agent.go] Closed tunnel: %s\n", tunnelId)
 			}
+
+		case *protos.ServerMessage_AssignJobUnit:
+			if !pollingJobEnabled {
+				// Shouldn't happen, but ignore if an agent is in interactive mode
+				break
+			}
+
+			consecutiveEmpty = 0 // reset on actual work
+			ju := x.AssignJobUnit
+			log.Printf("[agent.go] Assigned job unit: %s\n", ju.JobUnitId)
+
+			exitCode := runResolvedCommand(envName, ju.ResolvedCommand)
+
+			_ = stream.Send(&protos.AgentMessage{
+				Message: &protos.AgentMessage_JobUnitCompleted{
+					JobUnitCompleted: &protos.JobUnitCompleted{
+						JobUnitId: ju.JobUnitId,
+						ExitCode:  int32(exitCode),
+					},
+				},
+			})
+			requestNextJobUnit(stream, agentId)
+
+		case *protos.ServerMessage_NoJobUnitAvailable:
+			reason := x.NoJobUnitAvailable.Reason
+
+			// If the server says no batch jobs have assigned for the agent
+			if reason == "NO_ASSIGNMENT" {
+				if pollingJobEnabled {
+					log.Printf("[agent.go] No batch assignment for this agent; stopping job unit polling and staying in interactive mode.\n")
+				}
+				pollingJobEnabled = false
+				break
+			}
+
+			// If polling is disabled, ignore no work messages
+			if !pollingJobEnabled {
+				break
+			}
+
+			switch reason {
+			case "EMPTY", "EMPTY_ALL_DONE":
+				consecutiveEmpty++
+				log.Printf("[agent.go] No job unit available (%d/%d): %s\n", consecutiveEmpty, maxEmptyReplies, reason)
+
+				if consecutiveEmpty >= maxEmptyReplies {
+					log.Printf("[agent.go] No work after %d polls — shutting down agent (sweep complete).\n", maxEmptyReplies)
+					close(grpcStreamChannel)
+					return
+				}
+
+				time.Sleep(noWorkBackoff)
+				requestNextJobUnit(stream, agentId)
+
+			default:
+				// Unknown condition, retry without counting
+				time.Sleep(noWorkBackoff)
+				requestNextJobUnit(stream, agentId)
+			}
 		}
 
 	}
 }
+
+func requestNextJobUnit(stream Stream, agentId string) {
+	_ = stream.Send(&protos.AgentMessage{
+		Message: &protos.AgentMessage_RequestNextJobUnit{
+			RequestNextJobUnit: &protos.RequestNextJobUnit{
+				AgentId: agentId,
+			},
+		},
+	})
+}
+
+func runResolvedCommand(envName string, resolved string) int {
+	log.Printf("[agent.go] Running job unit command: %s\n", resolved)
+	cmd := exec.Command("micromamba", "run", "-n", envName, "bash", "-lc", resolved)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		var ee *exec.ExitError
+		if errors.As(err, &ee) {
+			log.Printf("[agent.go] Command exited with code %d\n", ee.ExitCode())
+			return ee.ExitCode()
+		}
+		log.Printf("[agent.go] Command failed to start/run: %v\n", err)
+		return 1
+	}
+	return 0
+}
diff --git a/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go b/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
index 4527355eac..85a4280797 100644
--- a/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
+++ b/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
@@ -1,25 +1,27 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.36.6
-// 	protoc        v4.25.3
-// source: agent-communication.proto
-
+//
 // Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
+// or more contributor license agreements. See the NOTICE file
 // distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
+// regarding copyright ownership. The ASF licenses this file
 // to you 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
+// 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
+// KIND, either express or implied. See the License for the
 // specific language governing permissions and limitations
 // under the License.
+//
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.35.1
+// 	protoc        v5.29.3
+// source: agent-communication.proto
 
 package protos
 
@@ -28,7 +30,6 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
-	unsafe "unsafe"
 )
 
 const (
@@ -40,10 +41,11 @@ const (
 
 // agent pinging the server
 type AgentPing struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	AgentId       string                 `protobuf:"bytes,1,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	AgentId string `protobuf:"bytes,1,opt,name=agentId,proto3" json:"agentId,omitempty"`
 }
 
 func (x *AgentPing) Reset() {
@@ -85,10 +87,11 @@ func (x *AgentPing) GetAgentId() string {
 
 // server requesting the agent to shutdown
 type ShutdownRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	AgentId       string                 `protobuf:"bytes,1,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	AgentId string `protobuf:"bytes,1,opt,name=agentId,proto3" json:"agentId,omitempty"`
 }
 
 func (x *ShutdownRequest) Reset() {
@@ -130,14 +133,15 @@ func (x *ShutdownRequest) GetAgentId() string {
 
 // server requesting the agent to create a new agent subprocess
 type CreateAgentRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	AgentId       string                 `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	ContainerId   string                 `protobuf:"bytes,3,opt,name=containerId,proto3" json:"containerId,omitempty"`
-	WorkingDir    string                 `protobuf:"bytes,4,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
-	Mounts        []string               `protobuf:"bytes,5,rep,name=mounts,proto3" json:"mounts,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	AgentId     string   `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
+	ContainerId string   `protobuf:"bytes,3,opt,name=containerId,proto3" json:"containerId,omitempty"`
+	WorkingDir  string   `protobuf:"bytes,4,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	Mounts      []string `protobuf:"bytes,5,rep,name=mounts,proto3" json:"mounts,omitempty"`
 }
 
 func (x *CreateAgentRequest) Reset() {
@@ -206,12 +210,13 @@ func (x *CreateAgentRequest) GetMounts() []string {
 }
 
 type CreateAgentResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	AgentId       string                 `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	Status        string                 `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	AgentId     string `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
+	Status      string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *CreateAgentResponse) Reset() {
@@ -267,11 +272,12 @@ func (x *CreateAgentResponse) GetStatus() string {
 
 // server requesting the agent to terminate an agent subprocess
 type TerminateAgentRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	AgentId       string                 `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	AgentId     string `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
 }
 
 func (x *TerminateAgentRequest) Reset() {
@@ -319,12 +325,13 @@ func (x *TerminateAgentRequest) GetAgentId() string {
 }
 
 type TerminateAgentResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	AgentId       string                 `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
-	Status        string                 `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	AgentId     string `protobuf:"bytes,2,opt,name=agentId,proto3" json:"agentId,omitempty"`
+	Status      string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *TerminateAgentResponse) Reset() {
@@ -380,13 +387,14 @@ func (x *TerminateAgentResponse) GetStatus() string {
 
 // server requesting the agent to setup an environment
 type EnvSetupRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	Libraries     []string               `protobuf:"bytes,3,rep,name=libraries,proto3" json:"libraries,omitempty"`
-	Pip           []string               `protobuf:"bytes,4,rep,name=pip,proto3" json:"pip,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string   `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
+	Libraries   []string `protobuf:"bytes,3,rep,name=libraries,proto3" json:"libraries,omitempty"`
+	Pip         []string `protobuf:"bytes,4,rep,name=pip,proto3" json:"pip,omitempty"`
 }
 
 func (x *EnvSetupRequest) Reset() {
@@ -448,11 +456,12 @@ func (x *EnvSetupRequest) GetPip() []string {
 }
 
 type EnvSetupResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Status        string                 `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *EnvSetupResponse) Reset() {
@@ -501,13 +510,14 @@ func (x *EnvSetupResponse) GetStatus() string {
 
 // server requesting the agent to execute a shell command in the environment
 type CommandExecutionRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	WorkingDir    string                 `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
-	Arguments     []string               `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string   `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
+	WorkingDir  string   `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	Arguments   []string `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
 }
 
 func (x *CommandExecutionRequest) Reset() {
@@ -569,11 +579,12 @@ func (x *CommandExecutionRequest) GetArguments() []string {
 }
 
 type CommandExecutionResponse struct {
-	state          protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId    string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ResponseString string                 `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
-	unknownFields  protoimpl.UnknownFields
-	sizeCache      protoimpl.SizeCache
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId    string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	ResponseString string `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
 }
 
 func (x *CommandExecutionResponse) Reset() {
@@ -621,13 +632,14 @@ func (x *CommandExecutionResponse) GetResponseString() string {
 }
 
 type AsyncCommandExecutionRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	WorkingDir    string                 `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
-	Arguments     []string               `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string   `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
+	WorkingDir  string   `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	Arguments   []string `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
 }
 
 func (x *AsyncCommandExecutionRequest) Reset() {
@@ -689,12 +701,13 @@ func (x *AsyncCommandExecutionRequest) GetArguments() []string {
 }
 
 type AsyncCommandExecutionResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ProcessId     int32                  `protobuf:"varint,2,opt,name=processId,proto3" json:"processId,omitempty"`
-	ErrorMessage  string                 `protobuf:"bytes,3,opt,name=errorMessage,proto3" json:"errorMessage,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId  string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	ProcessId    int32  `protobuf:"varint,2,opt,name=processId,proto3" json:"processId,omitempty"`
+	ErrorMessage string `protobuf:"bytes,3,opt,name=errorMessage,proto3" json:"errorMessage,omitempty"`
 }
 
 func (x *AsyncCommandExecutionResponse) Reset() {
@@ -749,10 +762,11 @@ func (x *AsyncCommandExecutionResponse) GetErrorMessage() string {
 }
 
 type AsyncCommandListRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
 }
 
 func (x *AsyncCommandListRequest) Reset() {
@@ -793,11 +807,12 @@ func (x *AsyncCommandListRequest) GetExecutionId() string {
 }
 
 type AsyncCommand struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ProcessId     int32                  `protobuf:"varint,1,opt,name=processId,proto3" json:"processId,omitempty"`
-	Arguments     []string               `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ProcessId int32    `protobuf:"varint,1,opt,name=processId,proto3" json:"processId,omitempty"`
+	Arguments []string `protobuf:"bytes,4,rep,name=arguments,proto3" json:"arguments,omitempty"`
 }
 
 func (x *AsyncCommand) Reset() {
@@ -845,11 +860,12 @@ func (x *AsyncCommand) GetArguments() []string {
 }
 
 type AsyncCommandListResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Commands      []*AsyncCommand        `protobuf:"bytes,2,rep,name=commands,proto3" json:"commands,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string          `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Commands    []*AsyncCommand `protobuf:"bytes,2,rep,name=commands,proto3" json:"commands,omitempty"`
 }
 
 func (x *AsyncCommandListResponse) Reset() {
@@ -897,11 +913,12 @@ func (x *AsyncCommandListResponse) GetCommands() []*AsyncCommand {
 }
 
 type AsyncCommandTerminateRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ProcessId     int32                  `protobuf:"varint,2,opt,name=processId,proto3" json:"processId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	ProcessId   int32  `protobuf:"varint,2,opt,name=processId,proto3" json:"processId,omitempty"`
 }
 
 func (x *AsyncCommandTerminateRequest) Reset() {
@@ -949,11 +966,12 @@ func (x *AsyncCommandTerminateRequest) GetProcessId() int32 {
 }
 
 type AsyncCommandTerminateResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Status        string                 `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *AsyncCommandTerminateResponse) Reset() {
@@ -1002,13 +1020,14 @@ func (x *AsyncCommandTerminateResponse) GetStatus() string {
 
 // server requesting the agent to execute a python script in the environment
 type PythonExecutionRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	WorkingDir    string                 `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
-	Code          string                 `protobuf:"bytes,4,opt,name=code,proto3" json:"code,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
+	WorkingDir  string `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	Code        string `protobuf:"bytes,4,opt,name=code,proto3" json:"code,omitempty"`
 }
 
 func (x *PythonExecutionRequest) Reset() {
@@ -1070,11 +1089,12 @@ func (x *PythonExecutionRequest) GetCode() string {
 }
 
 type PythonExecutionResponse struct {
-	state          protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId    string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ResponseString string                 `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
-	unknownFields  protoimpl.UnknownFields
-	sizeCache      protoimpl.SizeCache
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId    string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	ResponseString string `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
 }
 
 func (x *PythonExecutionResponse) Reset() {
@@ -1123,12 +1143,13 @@ func (x *PythonExecutionResponse) GetResponseString() string {
 
 // server requesting the agent to execute a jupyter notebook cell in the environment
 type JupyterExecutionRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	Code          string                 `protobuf:"bytes,3,opt,name=code,proto3" json:"code,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
+	Code        string `protobuf:"bytes,3,opt,name=code,proto3" json:"code,omitempty"`
 }
 
 func (x *JupyterExecutionRequest) Reset() {
@@ -1183,11 +1204,12 @@ func (x *JupyterExecutionRequest) GetCode() string {
 }
 
 type JupyterExecutionResponse struct {
-	state          protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId    string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ResponseString string                 `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
-	unknownFields  protoimpl.UnknownFields
-	sizeCache      protoimpl.SizeCache
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId    string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	ResponseString string `protobuf:"bytes,2,opt,name=responseString,proto3" json:"responseString,omitempty"`
 }
 
 func (x *JupyterExecutionResponse) Reset() {
@@ -1236,11 +1258,12 @@ func (x *JupyterExecutionResponse) GetResponseString() string {
 
 // server requesting the agent to restart a jupyter kernel
 type KernelRestartRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	EnvName       string                 `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	EnvName     string `protobuf:"bytes,2,opt,name=envName,proto3" json:"envName,omitempty"`
 }
 
 func (x *KernelRestartRequest) Reset() {
@@ -1288,11 +1311,12 @@ func (x *KernelRestartRequest) GetEnvName() string {
 }
 
 type KernelRestartResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Status        string                 `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *KernelRestartResponse) Reset() {
@@ -1341,16 +1365,17 @@ func (x *KernelRestartResponse) GetStatus() string {
 
 // server requesting the agent to create a ssh tunnel
 type TunnelCreationRequest struct {
-	state              protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId        string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	LocalPort          int32                  `protobuf:"varint,2,opt,name=localPort,proto3" json:"localPort,omitempty"`
-	LocalBindHost      string                 `protobuf:"bytes,3,opt,name=localBindHost,proto3" json:"localBindHost,omitempty"`
-	TunnelServerHost   string                 `protobuf:"bytes,4,opt,name=tunnelServerHost,proto3" json:"tunnelServerHost,omitempty"`
-	TunnelServerPort   int32                  `protobuf:"varint,5,opt,name=tunnelServerPort,proto3" json:"tunnelServerPort,omitempty"`
-	TunnelServerApiUrl string                 `protobuf:"bytes,6,opt,name=tunnelServerApiUrl,proto3" json:"tunnelServerApiUrl,omitempty"`
-	TunnelServerToken  string                 `protobuf:"bytes,7,opt,name=tunnelServerToken,proto3" json:"tunnelServerToken,omitempty"`
-	unknownFields      protoimpl.UnknownFields
-	sizeCache          protoimpl.SizeCache
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId        string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	LocalPort          int32  `protobuf:"varint,2,opt,name=localPort,proto3" json:"localPort,omitempty"`
+	LocalBindHost      string `protobuf:"bytes,3,opt,name=localBindHost,proto3" json:"localBindHost,omitempty"`
+	TunnelServerHost   string `protobuf:"bytes,4,opt,name=tunnelServerHost,proto3" json:"tunnelServerHost,omitempty"`
+	TunnelServerPort   int32  `protobuf:"varint,5,opt,name=tunnelServerPort,proto3" json:"tunnelServerPort,omitempty"`
+	TunnelServerApiUrl string `protobuf:"bytes,6,opt,name=tunnelServerApiUrl,proto3" json:"tunnelServerApiUrl,omitempty"`
+	TunnelServerToken  string `protobuf:"bytes,7,opt,name=tunnelServerToken,proto3" json:"tunnelServerToken,omitempty"`
 }
 
 func (x *TunnelCreationRequest) Reset() {
@@ -1433,14 +1458,15 @@ func (x *TunnelCreationRequest) GetTunnelServerToken() string {
 }
 
 type TunnelCreationResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Status        string                 `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
-	TunnelHost    string                 `protobuf:"bytes,3,opt,name=tunnelHost,proto3" json:"tunnelHost,omitempty"`
-	TunnelPort    int32                  `protobuf:"varint,4,opt,name=tunnelPort,proto3" json:"tunnelPort,omitempty"`
-	TunnelId      string                 `protobuf:"bytes,5,opt,name=tunnelId,proto3" json:"tunnelId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
+	TunnelHost  string `protobuf:"bytes,3,opt,name=tunnelHost,proto3" json:"tunnelHost,omitempty"`
+	TunnelPort  int32  `protobuf:"varint,4,opt,name=tunnelPort,proto3" json:"tunnelPort,omitempty"`
+	TunnelId    string `protobuf:"bytes,5,opt,name=tunnelId,proto3" json:"tunnelId,omitempty"`
 }
 
 func (x *TunnelCreationResponse) Reset() {
@@ -1510,11 +1536,12 @@ func (x *TunnelCreationResponse) GetTunnelId() string {
 
 // server requesting the agent to terminate a ssh tunnel
 type TunnelTerminationRequest struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	TunnelId      string                 `protobuf:"bytes,2,opt,name=tunnelId,proto3" json:"tunnelId,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	TunnelId    string `protobuf:"bytes,2,opt,name=tunnelId,proto3" json:"tunnelId,omitempty"`
 }
 
 func (x *TunnelTerminationRequest) Reset() {
@@ -1562,11 +1589,12 @@ func (x *TunnelTerminationRequest) GetTunnelId() string {
 }
 
 type TunnelTerminationResponse struct {
-	state         protoimpl.MessageState `protogen:"open.v1"`
-	ExecutionId   string                 `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Status        string                 `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
-	unknownFields protoimpl.UnknownFields
+	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 }
 
 func (x *TunnelTerminationResponse) Reset() {
@@ -1613,9 +1641,212 @@ func (x *TunnelTerminationResponse) GetStatus() string {
 	return ""
 }
 
+// Agent requesting the next job unit from the Job Workload
+type RequestNextJobUnit struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"`
+}
+
+func (x *RequestNextJobUnit) Reset() {
+	*x = RequestNextJobUnit{}
+	mi := &file_agent_communication_proto_msgTypes[27]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *RequestNextJobUnit) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RequestNextJobUnit) ProtoMessage() {}
+
+func (x *RequestNextJobUnit) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[27]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use RequestNextJobUnit.ProtoReflect.Descriptor instead.
+func (*RequestNextJobUnit) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{27}
+}
+
+func (x *RequestNextJobUnit) GetAgentId() string {
+	if x != nil {
+		return x.AgentId
+	}
+	return ""
+}
+
+// Agent letting know the job unit is completed
+type JobUnitCompleted struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	JobUnitId string `protobuf:"bytes,1,opt,name=job_unit_id,json=jobUnitId,proto3" json:"job_unit_id,omitempty"`
+	ExitCode  int32  `protobuf:"varint,2,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"`
+}
+
+func (x *JobUnitCompleted) Reset() {
+	*x = JobUnitCompleted{}
+	mi := &file_agent_communication_proto_msgTypes[28]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *JobUnitCompleted) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*JobUnitCompleted) ProtoMessage() {}
+
+func (x *JobUnitCompleted) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[28]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use JobUnitCompleted.ProtoReflect.Descriptor instead.
+func (*JobUnitCompleted) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{28}
+}
+
+func (x *JobUnitCompleted) GetJobUnitId() string {
+	if x != nil {
+		return x.JobUnitId
+	}
+	return ""
+}
+
+func (x *JobUnitCompleted) GetExitCode() int32 {
+	if x != nil {
+		return x.ExitCode
+	}
+	return 0
+}
+
+// Server assigning the job unit with the resolved command
+type AssignJobUnit struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	JobUnitId       string `protobuf:"bytes,1,opt,name=job_unit_id,json=jobUnitId,proto3" json:"job_unit_id,omitempty"`
+	ResolvedCommand string `protobuf:"bytes,2,opt,name=resolved_command,json=resolvedCommand,proto3" json:"resolved_command,omitempty"`
+}
+
+func (x *AssignJobUnit) Reset() {
+	*x = AssignJobUnit{}
+	mi := &file_agent_communication_proto_msgTypes[29]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *AssignJobUnit) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AssignJobUnit) ProtoMessage() {}
+
+func (x *AssignJobUnit) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[29]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AssignJobUnit.ProtoReflect.Descriptor instead.
+func (*AssignJobUnit) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{29}
+}
+
+func (x *AssignJobUnit) GetJobUnitId() string {
+	if x != nil {
+		return x.JobUnitId
+	}
+	return ""
+}
+
+func (x *AssignJobUnit) GetResolvedCommand() string {
+	if x != nil {
+		return x.ResolvedCommand
+	}
+	return ""
+}
+
+// Server indicating the agent that there are no job units to be consumed
+type NoJobUnitAvailable struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"` // "EMPTY" | "PREPARING"
+}
+
+func (x *NoJobUnitAvailable) Reset() {
+	*x = NoJobUnitAvailable{}
+	mi := &file_agent_communication_proto_msgTypes[30]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *NoJobUnitAvailable) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NoJobUnitAvailable) ProtoMessage() {}
+
+func (x *NoJobUnitAvailable) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[30]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NoJobUnitAvailable.ProtoReflect.Descriptor instead.
+func (*NoJobUnitAvailable) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{30}
+}
+
+func (x *NoJobUnitAvailable) GetReason() string {
+	if x != nil {
+		return x.Reason
+	}
+	return ""
+}
+
 type AgentMessage struct {
-	state protoimpl.MessageState `protogen:"open.v1"`
-	// Types that are valid to be assigned to Message:
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Types that are assignable to Message:
 	//
 	//	*AgentMessage_AgentPing
 	//	*AgentMessage_CreateAgentResponse
@@ -1630,14 +1861,14 @@ type AgentMessage struct {
 	//	*AgentMessage_AsyncCommandExecutionResponse
 	//	*AgentMessage_AsyncCommandListResponse
 	//	*AgentMessage_AsyncCommandTerminateResponse
-	Message       isAgentMessage_Message `protobuf_oneof:"message"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
+	//	*AgentMessage_RequestNextJobUnit
+	//	*AgentMessage_JobUnitCompleted
+	Message isAgentMessage_Message `protobuf_oneof:"message"`
 }
 
 func (x *AgentMessage) Reset() {
 	*x = AgentMessage{}
-	mi := &file_agent_communication_proto_msgTypes[27]
+	mi := &file_agent_communication_proto_msgTypes[31]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1649,7 +1880,7 @@ func (x *AgentMessage) String() string {
 func (*AgentMessage) ProtoMessage() {}
 
 func (x *AgentMessage) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[27]
+	mi := &file_agent_communication_proto_msgTypes[31]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1662,129 +1893,117 @@ func (x *AgentMessage) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use AgentMessage.ProtoReflect.Descriptor instead.
 func (*AgentMessage) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{27}
+	return file_agent_communication_proto_rawDescGZIP(), []int{31}
 }
 
-func (x *AgentMessage) GetMessage() isAgentMessage_Message {
-	if x != nil {
-		return x.Message
+func (m *AgentMessage) GetMessage() isAgentMessage_Message {
+	if m != nil {
+		return m.Message
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetAgentPing() *AgentPing {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_AgentPing); ok {
-			return x.AgentPing
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_AgentPing); ok {
+		return x.AgentPing
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetCreateAgentResponse() *CreateAgentResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_CreateAgentResponse); ok {
-			return x.CreateAgentResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_CreateAgentResponse); ok {
+		return x.CreateAgentResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetTerminateAgentResponse() *TerminateAgentResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_TerminateAgentResponse); ok {
-			return x.TerminateAgentResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_TerminateAgentResponse); ok {
+		return x.TerminateAgentResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetEnvSetupResponse() *EnvSetupResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_EnvSetupResponse); ok {
-			return x.EnvSetupResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_EnvSetupResponse); ok {
+		return x.EnvSetupResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetCommandExecutionResponse() *CommandExecutionResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_CommandExecutionResponse); ok {
-			return x.CommandExecutionResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_CommandExecutionResponse); ok {
+		return x.CommandExecutionResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetPythonExecutionResponse() *PythonExecutionResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_PythonExecutionResponse); ok {
-			return x.PythonExecutionResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_PythonExecutionResponse); ok {
+		return x.PythonExecutionResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetJupyterExecutionResponse() *JupyterExecutionResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_JupyterExecutionResponse); ok {
-			return x.JupyterExecutionResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_JupyterExecutionResponse); ok {
+		return x.JupyterExecutionResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetKernelRestartResponse() *KernelRestartResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_KernelRestartResponse); ok {
-			return x.KernelRestartResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_KernelRestartResponse); ok {
+		return x.KernelRestartResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetTunnelCreationResponse() *TunnelCreationResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_TunnelCreationResponse); ok {
-			return x.TunnelCreationResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_TunnelCreationResponse); ok {
+		return x.TunnelCreationResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetTunnelTerminationResponse() *TunnelTerminationResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_TunnelTerminationResponse); ok {
-			return x.TunnelTerminationResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_TunnelTerminationResponse); ok {
+		return x.TunnelTerminationResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetAsyncCommandExecutionResponse() *AsyncCommandExecutionResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_AsyncCommandExecutionResponse); ok {
-			return x.AsyncCommandExecutionResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_AsyncCommandExecutionResponse); ok {
+		return x.AsyncCommandExecutionResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetAsyncCommandListResponse() *AsyncCommandListResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_AsyncCommandListResponse); ok {
-			return x.AsyncCommandListResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_AsyncCommandListResponse); ok {
+		return x.AsyncCommandListResponse
 	}
 	return nil
 }
 
 func (x *AgentMessage) GetAsyncCommandTerminateResponse() *AsyncCommandTerminateResponse {
-	if x != nil {
-		if x, ok := x.Message.(*AgentMessage_AsyncCommandTerminateResponse); ok {
-			return x.AsyncCommandTerminateResponse
-		}
+	if x, ok := x.GetMessage().(*AgentMessage_AsyncCommandTerminateResponse); ok {
+		return x.AsyncCommandTerminateResponse
+	}
+	return nil
+}
+
+func (x *AgentMessage) GetRequestNextJobUnit() *RequestNextJobUnit {
+	if x, ok := x.GetMessage().(*AgentMessage_RequestNextJobUnit); ok {
+		return x.RequestNextJobUnit
+	}
+	return nil
+}
+
+func (x *AgentMessage) GetJobUnitCompleted() *JobUnitCompleted {
+	if x, ok := x.GetMessage().(*AgentMessage_JobUnitCompleted); ok {
+		return x.JobUnitCompleted
 	}
 	return nil
 }
@@ -1845,6 +2064,14 @@ type AgentMessage_AsyncCommandTerminateResponse struct {
 	AsyncCommandTerminateResponse *AsyncCommandTerminateResponse `protobuf:"bytes,13,opt,name=asyncCommandTerminateResponse,proto3,oneof"`
 }
 
+type AgentMessage_RequestNextJobUnit struct {
+	RequestNextJobUnit *RequestNextJobUnit `protobuf:"bytes,20,opt,name=requestNextJobUnit,proto3,oneof"`
+}
+
+type AgentMessage_JobUnitCompleted struct {
+	JobUnitCompleted *JobUnitCompleted `protobuf:"bytes,21,opt,name=jobUnitCompleted,proto3,oneof"`
+}
+
 func (*AgentMessage_AgentPing) isAgentMessage_Message() {}
 
 func (*AgentMessage_CreateAgentResponse) isAgentMessage_Message() {}
@@ -1871,9 +2098,16 @@ func (*AgentMessage_AsyncCommandListResponse) isAgentMessage_Message() {}
 
 func (*AgentMessage_AsyncCommandTerminateResponse) isAgentMessage_Message() {}
 
+func (*AgentMessage_RequestNextJobUnit) isAgentMessage_Message() {}
+
+func (*AgentMessage_JobUnitCompleted) isAgentMessage_Message() {}
+
 type ServerMessage struct {
-	state protoimpl.MessageState `protogen:"open.v1"`
-	// Types that are valid to be assigned to Message:
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Types that are assignable to Message:
 	//
 	//	*ServerMessage_ShutdownRequest
 	//	*ServerMessage_CreateAgentRequest
@@ -1888,14 +2122,14 @@ type ServerMessage struct {
 	//	*ServerMessage_AsyncCommandExecutionRequest
 	//	*ServerMessage_AsyncCommandListRequest
 	//	*ServerMessage_AsyncCommandTerminateRequest
-	Message       isServerMessage_Message `protobuf_oneof:"message"`
-	unknownFields protoimpl.UnknownFields
-	sizeCache     protoimpl.SizeCache
+	//	*ServerMessage_AssignJobUnit
+	//	*ServerMessage_NoJobUnitAvailable
+	Message isServerMessage_Message `protobuf_oneof:"message"`
 }
 
 func (x *ServerMessage) Reset() {
 	*x = ServerMessage{}
-	mi := &file_agent_communication_proto_msgTypes[28]
+	mi := &file_agent_communication_proto_msgTypes[32]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1907,7 +2141,7 @@ func (x *ServerMessage) String() string {
 func (*ServerMessage) ProtoMessage() {}
 
 func (x *ServerMessage) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[28]
+	mi := &file_agent_communication_proto_msgTypes[32]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1920,129 +2154,117 @@ func (x *ServerMessage) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead.
 func (*ServerMessage) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{28}
+	return file_agent_communication_proto_rawDescGZIP(), []int{32}
 }
 
-func (x *ServerMessage) GetMessage() isServerMessage_Message {
-	if x != nil {
-		return x.Message
+func (m *ServerMessage) GetMessage() isServerMessage_Message {
+	if m != nil {
+		return m.Message
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetShutdownRequest() *ShutdownRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_ShutdownRequest); ok {
-			return x.ShutdownRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_ShutdownRequest); ok {
+		return x.ShutdownRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetCreateAgentRequest() *CreateAgentRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_CreateAgentRequest); ok {
-			return x.CreateAgentRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_CreateAgentRequest); ok {
+		return x.CreateAgentRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetTerminateAgentRequest() *TerminateAgentRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_TerminateAgentRequest); ok {
-			return x.TerminateAgentRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_TerminateAgentRequest); ok {
+		return x.TerminateAgentRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetEnvSetupRequest() *EnvSetupRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_EnvSetupRequest); ok {
-			return x.EnvSetupRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_EnvSetupRequest); ok {
+		return x.EnvSetupRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetCommandExecutionRequest() *CommandExecutionRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_CommandExecutionRequest); ok {
-			return x.CommandExecutionRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_CommandExecutionRequest); ok {
+		return x.CommandExecutionRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetPythonExecutionRequest() *PythonExecutionRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_PythonExecutionRequest); ok {
-			return x.PythonExecutionRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_PythonExecutionRequest); ok {
+		return x.PythonExecutionRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetJupyterExecutionRequest() *JupyterExecutionRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_JupyterExecutionRequest); ok {
-			return x.JupyterExecutionRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_JupyterExecutionRequest); ok {
+		return x.JupyterExecutionRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetKernelRestartRequest() *KernelRestartRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_KernelRestartRequest); ok {
-			return x.KernelRestartRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_KernelRestartRequest); ok {
+		return x.KernelRestartRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetTunnelCreationRequest() *TunnelCreationRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_TunnelCreationRequest); ok {
-			return x.TunnelCreationRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_TunnelCreationRequest); ok {
+		return x.TunnelCreationRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetTunnelTerminationRequest() *TunnelTerminationRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_TunnelTerminationRequest); ok {
-			return x.TunnelTerminationRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_TunnelTerminationRequest); ok {
+		return x.TunnelTerminationRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetAsyncCommandExecutionRequest() *AsyncCommandExecutionRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_AsyncCommandExecutionRequest); ok {
-			return x.AsyncCommandExecutionRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_AsyncCommandExecutionRequest); ok {
+		return x.AsyncCommandExecutionRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetAsyncCommandListRequest() *AsyncCommandListRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_AsyncCommandListRequest); ok {
-			return x.AsyncCommandListRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_AsyncCommandListRequest); ok {
+		return x.AsyncCommandListRequest
 	}
 	return nil
 }
 
 func (x *ServerMessage) GetAsyncCommandTerminateRequest() *AsyncCommandTerminateRequest {
-	if x != nil {
-		if x, ok := x.Message.(*ServerMessage_AsyncCommandTerminateRequest); ok {
-			return x.AsyncCommandTerminateRequest
-		}
+	if x, ok := x.GetMessage().(*ServerMessage_AsyncCommandTerminateRequest); ok {
+		return x.AsyncCommandTerminateRequest
+	}
+	return nil
+}
+
+func (x *ServerMessage) GetAssignJobUnit() *AssignJobUnit {
+	if x, ok := x.GetMessage().(*ServerMessage_AssignJobUnit); ok {
+		return x.AssignJobUnit
+	}
+	return nil
+}
+
+func (x *ServerMessage) GetNoJobUnitAvailable() *NoJobUnitAvailable {
+	if x, ok := x.GetMessage().(*ServerMessage_NoJobUnitAvailable); ok {
+		return x.NoJobUnitAvailable
 	}
 	return nil
 }
@@ -2103,6 +2325,14 @@ type ServerMessage_AsyncCommandTerminateRequest struct {
 	AsyncCommandTerminateRequest *AsyncCommandTerminateRequest `protobuf:"bytes,13,opt,name=asyncCommandTerminateRequest,proto3,oneof"`
 }
 
+type ServerMessage_AssignJobUnit struct {
+	AssignJobUnit *AssignJobUnit `protobuf:"bytes,20,opt,name=assignJobUnit,proto3,oneof"`
+}
+
+type ServerMessage_NoJobUnitAvailable struct {
+	NoJobUnitAvailable *NoJobUnitAvailable `protobuf:"bytes,21,opt,name=noJobUnitAvailable,proto3,oneof"`
+}
+
 func (*ServerMessage_ShutdownRequest) isServerMessage_Message() {}
 
 func (*ServerMessage_CreateAgentRequest) isServerMessage_Message() {}
@@ -2129,173 +2359,455 @@ func (*ServerMessage_AsyncCommandListRequest) isServerMessage_Message() {}
 
 func (*ServerMessage_AsyncCommandTerminateRequest) isServerMessage_Message() {}
 
+func (*ServerMessage_AssignJobUnit) isServerMessage_Message() {}
+
+func (*ServerMessage_NoJobUnitAvailable) isServerMessage_Message() {}
+
 var File_agent_communication_proto protoreflect.FileDescriptor
 
-const file_agent_communication_proto_rawDesc = "" +
-	"\n" +
-	"\x19agent-communication.proto\x12\x19org.apache.airavata.agent\"%\n" +
-	"\tAgentPing\x12\x18\n" +
-	"\aagentId\x18\x01 \x01(\tR\aagentId\"+\n" +
-	"\x0fShutdownRequest\x12\x18\n" +
-	"\aagentId\x18\x01 \x01(\tR\aagentId\"\xaa\x01\n" +
-	"\x12CreateAgentRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aagentId\x18\x02 \x01(\tR\aagentId\x12 \n" +
-	"\vcontainerId\x18\x03 \x01(\tR\vcontainerId\x12\x1e\n" +
-	"\n" +
-	"workingDir\x18\x04 \x01(\tR\n" +
-	"workingDir\x12\x16\n" +
-	"\x06mounts\x18\x05 \x03(\tR\x06mounts\"i\n" +
-	"\x13CreateAgentResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aagentId\x18\x02 \x01(\tR\aagentId\x12\x16\n" +
-	"\x06status\x18\x03 \x01(\tR\x06status\"S\n" +
-	"\x15TerminateAgentRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aagentId\x18\x02 \x01(\tR\aagentId\"l\n" +
-	"\x16TerminateAgentResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aagentId\x18\x02 \x01(\tR\aagentId\x12\x16\n" +
-	"\x06status\x18\x03 \x01(\tR\x06status\"}\n" +
-	"\x0fEnvSetupRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\x12\x1c\n" +
-	"\tlibraries\x18\x03 \x03(\tR\tlibraries\x12\x10\n" +
-	"\x03pip\x18\x04 \x03(\tR\x03pip\"L\n" +
-	"\x10EnvSetupResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x16\n" +
-	"\x06status\x18\x02 \x01(\tR\x06status\"\x93\x01\n" +
-	"\x17CommandExecutionRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\x12\x1e\n" +
-	"\n" +
-	"workingDir\x18\x03 \x01(\tR\n" +
-	"workingDir\x12\x1c\n" +
-	"\targuments\x18\x04 \x03(\tR\targuments\"d\n" +
-	"\x18CommandExecutionResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12&\n" +
-	"\x0eresponseString\x18\x02 \x01(\tR\x0eresponseString\"\x98\x01\n" +
-	"\x1cAsyncCommandExecutionRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\x12\x1e\n" +
-	"\n" +
-	"workingDir\x18\x03 \x01(\tR\n" +
-	"workingDir\x12\x1c\n" +
-	"\targuments\x18\x04 \x03(\tR\targuments\"\x83\x01\n" +
-	"\x1dAsyncCommandExecutionResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x1c\n" +
-	"\tprocessId\x18\x02 \x01(\x05R\tprocessId\x12\"\n" +
-	"\ferrorMessage\x18\x03 \x01(\tR\ferrorMessage\";\n" +
-	"\x17AsyncCommandListRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\"J\n" +
-	"\fAsyncCommand\x12\x1c\n" +
-	"\tprocessId\x18\x01 \x01(\x05R\tprocessId\x12\x1c\n" +
-	"\targuments\x18\x04 \x03(\tR\targuments\"\x81\x01\n" +
-	"\x18AsyncCommandListResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12C\n" +
-	"\bcommands\x18\x02 \x03(\v2'.org.apache.airavata.agent.AsyncCommandR\bcommands\"^\n" +
-	"\x1cAsyncCommandTerminateRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x1c\n" +
-	"\tprocessId\x18\x02 \x01(\x05R\tprocessId\"Y\n" +
-	"\x1dAsyncCommandTerminateResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x16\n" +
-	"\x06status\x18\x02 \x01(\tR\x06status\"\x88\x01\n" +
-	"\x16PythonExecutionRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\x12\x1e\n" +
-	"\n" +
-	"workingDir\x18\x03 \x01(\tR\n" +
-	"workingDir\x12\x12\n" +
-	"\x04code\x18\x04 \x01(\tR\x04code\"c\n" +
-	"\x17PythonExecutionResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12&\n" +
-	"\x0eresponseString\x18\x02 \x01(\tR\x0eresponseString\"i\n" +
-	"\x17JupyterExecutionRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\x12\x12\n" +
-	"\x04code\x18\x03 \x01(\tR\x04code\"d\n" +
-	"\x18JupyterExecutionResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12&\n" +
-	"\x0eresponseString\x18\x02 \x01(\tR\x0eresponseString\"R\n" +
-	"\x14KernelRestartRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x18\n" +
-	"\aenvName\x18\x02 \x01(\tR\aenvName\"Q\n" +
-	"\x15KernelRestartResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x16\n" +
-	"\x06status\x18\x02 \x01(\tR\x06status\"\xb3\x02\n" +
-	"\x15TunnelCreationRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x1c\n" +
-	"\tlocalPort\x18\x02 \x01(\x05R\tlocalPort\x12$\n" +
-	"\rlocalBindHost\x18\x03 \x01(\tR\rlocalBindHost\x12*\n" +
-	"\x10tunnelServerHost\x18\x04 \x01(\tR\x10tunnelServerHost\x12*\n" +
-	"\x10tunnelServerPort\x18\x05 \x01(\x05R\x10tunnelServerPort\x12.\n" +
-	"\x12tunnelServerApiUrl\x18\x06 \x01(\tR\x12tunnelServerApiUrl\x12,\n" +
-	"\x11tunnelServerToken\x18\a \x01(\tR\x11tunnelServerToken\"\xae\x01\n" +
-	"\x16TunnelCreationResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x16\n" +
-	"\x06status\x18\x02 \x01(\tR\x06status\x12\x1e\n" +
-	"\n" +
-	"tunnelHost\x18\x03 \x01(\tR\n" +
-	"tunnelHost\x12\x1e\n" +
-	"\n" +
-	"tunnelPort\x18\x04 \x01(\x05R\n" +
-	"tunnelPort\x12\x1a\n" +
-	"\btunnelId\x18\x05 \x01(\tR\btunnelId\"X\n" +
-	"\x18TunnelTerminationRequest\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x1a\n" +
-	"\btunnelId\x18\x02 \x01(\tR\btunnelId\"U\n" +
-	"\x19TunnelTerminationResponse\x12 \n" +
-	"\vexecutionId\x18\x01 \x01(\tR\vexecutionId\x12\x16\n" +
-	"\x06status\x18\x02 \x01(\tR\x06status\"\xa7\v\n" +
-	"\fAgentMessage\x12D\n" +
-	"\tagentPing\x18\x01 \x01(\v2$.org.apache.airavata.agent.AgentPingH\x00R\tagentPing\x12b\n" +
-	"\x13createAgentResponse\x18\x02 \x01(\v2..org.apache.airavata.agent.CreateAgentResponseH\x00R\x13createAgentResponse\x12k\n" +
-	"\x16terminateAgentResponse\x18\x03 \x01(\v21.org.apache.airavata.agent.TerminateAgentResponseH\x00R\x16terminateAgentResponse\x12Y\n" +
-	"\x10envSetupResponse\x18\x04 \x01(\v2+.org.apache.airavata.agent.EnvSetupResponseH\x00R\x10envSetupResponse\x12q\n" +
-	"\x18commandExecutionResponse\x18\x05 \x01(\v23.org.apache.airavata.agent.CommandExecutionResponseH\x00R\x18commandExecutionResponse\x12n\n" +
-	"\x17pythonExecutionResponse\x18\x06 \x01(\v22.org.apache.airavata.agent.PythonExecutionResponseH\x00R\x17pythonExecutionResponse\x12q\n" +
-	"\x18jupyterExecutionResponse\x18\a \x01(\v23.org.apache.airavata.agent.JupyterExecutionResponseH\x00R\x18jupyterExecutionResponse\x12h\n" +
-	"\x15kernelRestartResponse\x18\b \x01(\v20.org.apache.airavata.agent.KernelRestartResponseH\x00R\x15kernelRestartResponse\x12k\n" +
-	"\x16tunnelCreationResponse\x18\t \x01(\v21.org.apache.airavata.agent.TunnelCreationResponseH\x00R\x16tunnelCreationResponse\x12t\n" +
-	"\x19tunnelTerminationResponse\x18\n" +
-	" \x01(\v24.org.apache.airavata.agent.TunnelTerminationResponseH\x00R\x19tunnelTerminationResponse\x12\x80\x01\n" +
-	"\x1dasyncCommandExecutionResponse\x18\v \x01(\v28.org.apache.airavata.agent.AsyncCommandExecutionResponseH\x00R\x1dasyncCommandExecutionResponse\x12q\n" +
-	"\x18asyncCommandListResponse\x18\f \x01(\v23.org.apache.airavata.agent.AsyncCommandListResponseH\x00R\x18asyncCommandListResponse\x12\x80\x01\n" +
-	"\x1dasyncCommandTerminateResponse\x18\r \x01(\v28.org.apache.airavata.agent.AsyncCommandTerminateResponseH\x00R\x1dasyncCommandTerminateResponseB\t\n" +
-	"\amessage\"\x94\v\n" +
-	"\rServerMessage\x12V\n" +
-	"\x0fshutdownRequest\x18\x01 \x01(\v2*.org.apache.airavata.agent.ShutdownRequestH\x00R\x0fshutdownRequest\x12_\n" +
-	"\x12createAgentRequest\x18\x02 \x01(\v2-.org.apache.airavata.agent.CreateAgentRequestH\x00R\x12createAgentRequest\x12h\n" +
-	"\x15terminateAgentRequest\x18\x03 \x01(\v20.org.apache.airavata.agent.TerminateAgentRequestH\x00R\x15terminateAgentRequest\x12V\n" +
-	"\x0fenvSetupRequest\x18\x04 \x01(\v2*.org.apache.airavata.agent.EnvSetupRequestH\x00R\x0fenvSetupRequest\x12n\n" +
-	"\x17commandExecutionRequest\x18\x05 \x01(\v22.org.apache.airavata.agent.CommandExecutionRequestH\x00R\x17commandExecutionRequest\x12k\n" +
-	"\x16pythonExecutionRequest\x18\x06 \x01(\v21.org.apache.airavata.agent.PythonExecutionRequestH\x00R\x16pythonExecutionRequest\x12n\n" +
-	"\x17jupyterExecutionRequest\x18\a \x01(\v22.org.apache.airavata.agent.JupyterExecutionRequestH\x00R\x17jupyterExecutionRequest\x12e\n" +
-	"\x14kernelRestartRequest\x18\b \x01(\v2/.org.apache.airavata.agent.KernelRestartRequestH\x00R\x14kernelRestartRequest\x12h\n" +
-	"\x15tunnelCreationRequest\x18\t \x01(\v20.org.apache.airavata.agent.TunnelCreationRequestH\x00R\x15tunnelCreationRequest\x12q\n" +
-	"\x18tunnelTerminationRequest\x18\n" +
-	" \x01(\v23.org.apache.airavata.agent.TunnelTerminationRequestH\x00R\x18tunnelTerminationRequest\x12}\n" +
-	"\x1casyncCommandExecutionRequest\x18\v \x01(\v27.org.apache.airavata.agent.AsyncCommandExecutionRequestH\x00R\x1casyncCommandExecutionRequest\x12n\n" +
-	"\x17asyncCommandListRequest\x18\f \x01(\v22.org.apache.airavata.agent.AsyncCommandListRequestH\x00R\x17asyncCommandListRequest\x12}\n" +
-	"\x1casyncCommandTerminateRequest\x18\r \x01(\v27.org.apache.airavata.agent.AsyncCommandTerminateRequestH\x00R\x1casyncCommandTerminateRequestB\t\n" +
-	"\amessage2\x86\x01\n" +
-	"\x19AgentCommunicationService\x12i\n" +
-	"\x10createMessageBus\x12'.org.apache.airavata.agent.AgentMessage\x1a(.org.apache.airavata.agent.ServerMessage(\x010\x01B?\n" +
-	"\x19org.apache.airavata.agentB\x17AgentCommunicationProtoP\x01Z\aprotos/b\x06proto3"
+var file_agent_communication_proto_rawDesc = []byte{
+	0x0a, 0x19, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x6f, 0x72, 0x67,
+	0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61,
+	0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x22, 0x25, 0x0a, 0x09, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x50,
+	0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x2b, 0x0a,
+	0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x43,
+	0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a,
+	0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12,
+	0x1e, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x12,
+	0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x69, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74,
+	0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
+	0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x22, 0x53, 0x0a, 0x15, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x41,
+	0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a,
+	0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x16, 0x54, 0x65, 0x72, 0x6d, 0x69,
+	0x6e, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a,
+	0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x7d, 0x0a, 0x0f, 0x45, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75,
+	0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e,
+	0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x76,
+	0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65,
+	0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69,
+	0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x03, 0x70, 0x69, 0x70, 0x22, 0x4c, 0x0a, 0x10, 0x45, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78,
+	0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20,
+	0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
+	0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x6f,
+	0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x72,
+	0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61,
+	0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x64, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75,
+	0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
+	0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x98,
+	0x01, 0x0a, 0x1c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49,
+	0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x77,
+	0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x61,
+	0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09,
+	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x1d, 0x41, 0x73,
+	0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a,
+	0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x65,
+	0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
+	0x3b, 0x0a, 0x17, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c,
+	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78,
+	0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x0c,
+	0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09,
+	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x72,
+	0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61,
+	0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x18, 0x41, 0x73, 0x79,
+	0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x43, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x72, 0x67, 0x2e,
+	0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e,
+	0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x5e, 0x0a, 0x1c,
+	0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x65, 0x72, 0x6d,
+	0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b,
+	0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c,
+	0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x22, 0x59, 0x0a, 0x1d,
+	0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x65, 0x72, 0x6d,
+	0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a,
+	0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
+	0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x88, 0x01, 0x0a, 0x16, 0x50, 0x79, 0x74, 0x68,
+	0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e,
+	0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x12, 0x12,
+	0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
+	0x64, 0x65, 0x22, 0x63, 0x0a, 0x17, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a,
+	0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
+	0x26, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e,
+	0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x69, 0x0a, 0x17, 0x4a, 0x75, 0x70, 0x79, 0x74,
+	0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12,
+	0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
+	0x64, 0x65, 0x22, 0x64, 0x0a, 0x18, 0x4a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45, 0x78, 0x65,
+	0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
+	0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69,
+	0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x52, 0x0a, 0x14, 0x4b, 0x65, 0x72, 0x6e,
+	0x65, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+	0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x51, 0x0a, 0x15,
+	0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22,
+	0xb3, 0x02, 0x0a, 0x15, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65,
+	0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+	0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6c,
+	0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
+	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x6f, 0x63,
+	0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x12,
+	0x2a, 0x0a, 0x10, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x48,
+	0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x75, 0x6e, 0x6e, 0x65,
+	0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x74,
+	0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x72,
+	0x76, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x74, 0x75, 0x6e, 0x6e, 0x65,
+	0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x70, 0x69, 0x55, 0x72, 0x6c, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x41, 0x70, 0x69, 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x11, 0x74, 0x75, 0x6e, 0x6e, 0x65,
+	0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x11, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+	0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xae, 0x01, 0x0a, 0x16, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+	0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x75,
+	0x6e, 0x6e, 0x65, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x75,
+	0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
+	0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x75,
+	0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x75,
+	0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x22, 0x58, 0x0a, 0x18, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
+	0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64,
+	0x22, 0x55, 0x0a, 0x19, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a,
+	0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
+	0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2f, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x4e, 0x65, 0x78, 0x74, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x19, 0x0a,
+	0x08, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x4f, 0x0a, 0x10, 0x4a, 0x6f, 0x62, 0x55,
+	0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0b,
+	0x6a, 0x6f, 0x62, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x09, 0x6a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09,
+	0x65, 0x78, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x08, 0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x5a, 0x0a, 0x0d, 0x41, 0x73, 0x73,
+	0x69, 0x67, 0x6e, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6a, 0x6f,
+	0x62, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x09, 0x6a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65,
+	0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x43, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x2c, 0x0a, 0x12, 0x4e, 0x6f, 0x4a, 0x6f, 0x62, 0x55, 0x6e,
+	0x69, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72,
+	0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61,
+	0x73, 0x6f, 0x6e, 0x22, 0xe3, 0x0c, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x50, 0x69, 0x6e,
+	0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52,
+	0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x62, 0x0a, 0x13, 0x63, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74,
+	0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b,
+	0x0a, 0x16, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31,
+	0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61,
+	0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x69,
+	0x6e, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x48, 0x00, 0x52, 0x16, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x41, 0x67,
+	0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x10, 0x65,
+	0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63,
+	0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e,
+	0x74, 0x2e, 0x45, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x48, 0x00, 0x52, 0x10, 0x65, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61,
+	0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61,
+	0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52,
+	0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x17, 0x70, 0x79, 0x74,
+	0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x72, 0x67,
+	0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61,
+	0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65,
+	0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00,
+	0x52, 0x17, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x18, 0x6a, 0x75, 0x70,
+	0x79, 0x74, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x6f, 0x72,
+	0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74,
+	0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x48, 0x00, 0x52, 0x18, 0x6a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x15,
+	0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72,
+	0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74,
+	0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65,
+	0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52,
+	0x15, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x16, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61,
+	0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65,
+	0x6e, 0x74, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x74, 0x75, 0x6e,
+	0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x19, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72,
+	0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61,
+	0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65,
+	0x6e, 0x74, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x19,
+	0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x1d, 0x61, 0x73,
+	0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x38, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61,
+	0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73,
+	0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1d, 0x61,
+	0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x18,
+	0x61, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33,
+	0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61,
+	0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63,
+	0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x18, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x80, 0x01, 0x0a, 0x1d, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x48, 0x00, 0x52, 0x1d, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x65, 0x78,
+	0x74, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d,
+	0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61,
+	0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x4e, 0x65, 0x78, 0x74, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52,
+	0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x65, 0x78, 0x74, 0x4a, 0x6f, 0x62, 0x55,
+	0x6e, 0x69, 0x74, 0x12, 0x59, 0x0a, 0x10, 0x6a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x43, 0x6f,
+	0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
+	0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76,
+	0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69,
+	0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x10, 0x6a, 0x6f,
+	0x62, 0x55, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x42, 0x09,
+	0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc7, 0x0c, 0x0a, 0x0d, 0x53, 0x65,
+	0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x73,
+	0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68,
+	0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
+	0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x48, 0x00, 0x52, 0x0f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x5f, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65,
+	0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x2d, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72,
+	0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61,
+	0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00,
+	0x52, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x15, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74,
+	0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65,
+	0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
+	0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x15, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61,
+	0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x56,
+	0x0a, 0x0f, 0x65, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x65, 0x6e, 0x76, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6e, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6b, 0x0a, 0x16, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e,
+	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61,
+	0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65,
+	0x6e, 0x74, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
+	0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x16, 0x70, 0x79, 0x74,
+	0x68, 0x6f, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x6e, 0x0a, 0x17, 0x6a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45, 0x78,
+	0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x07,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68,
+	0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
+	0x2e, 0x4a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x6a, 0x75, 0x70, 0x79,
+	0x74, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x65, 0x0a, 0x14, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73,
+	0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x2f, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61,
+	0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x65,
+	0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x74,
+	0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x15, 0x74, 0x75,
+	0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x67, 0x2e,
+	0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e,
+	0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x15, 0x74,
+	0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x71, 0x0a, 0x18, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65,
+	0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61,
+	0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65,
+	0x6e, 0x74, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x18, 0x74,
+	0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x1c, 0x61, 0x73, 0x79, 0x6e, 0x63,
+	0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e,
+	0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76,
+	0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6e, 0x0a, 0x17, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70,
+	0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x61,
+	0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x1c, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x6f,
+	0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61,
+	0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x50, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4a,
+	0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f,
+	0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61,
+	0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4a,
+	0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e,
+	0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x5f, 0x0a, 0x12, 0x6e, 0x6f, 0x4a, 0x6f, 0x62,
+	0x55, 0x6e, 0x69, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x15, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65,
+	0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
+	0x4e, 0x6f, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
+	0x6c, 0x65, 0x48, 0x00, 0x52, 0x12, 0x6e, 0x6f, 0x4a, 0x6f, 0x62, 0x55, 0x6e, 0x69, 0x74, 0x41,
+	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
+	0x61, 0x67, 0x65, 0x32, 0x86, 0x01, 0x0a, 0x19, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d,
+	0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+	0x65, 0x12, 0x69, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x42, 0x75, 0x73, 0x12, 0x27, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63,
+	0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e,
+	0x74, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x28,
+	0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61,
+	0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x3f, 0x0a, 0x19,
+	0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76,
+	0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x42, 0x17, 0x41, 0x67, 0x65, 0x6e, 0x74,
+	0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f,
+	0x74, 0x6f, 0x50, 0x01, 0x5a, 0x07, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x62, 0x06, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
 
 var (
 	file_agent_communication_proto_rawDescOnce sync.Once
-	file_agent_communication_proto_rawDescData []byte
+	file_agent_communication_proto_rawDescData = file_agent_communication_proto_rawDesc
 )
 
 func file_agent_communication_proto_rawDescGZIP() []byte {
 	file_agent_communication_proto_rawDescOnce.Do(func() {
-		file_agent_communication_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_agent_communication_proto_rawDesc), len(file_agent_communication_proto_rawDesc)))
+		file_agent_communication_proto_rawDescData = protoimpl.X.CompressGZIP(file_agent_communication_proto_rawDescData)
 	})
 	return file_agent_communication_proto_rawDescData
 }
 
-var file_agent_communication_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
+var file_agent_communication_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
 var file_agent_communication_proto_goTypes = []any{
 	(*AgentPing)(nil),                     // 0: org.apache.airavata.agent.AgentPing
 	(*ShutdownRequest)(nil),               // 1: org.apache.airavata.agent.ShutdownRequest
@@ -2324,8 +2836,12 @@ var file_agent_communication_proto_goTypes = []any{
 	(*TunnelCreationResponse)(nil),        // 24: org.apache.airavata.agent.TunnelCreationResponse
 	(*TunnelTerminationRequest)(nil),      // 25: org.apache.airavata.agent.TunnelTerminationRequest
 	(*TunnelTerminationResponse)(nil),     // 26: org.apache.airavata.agent.TunnelTerminationResponse
-	(*AgentMessage)(nil),                  // 27: org.apache.airavata.agent.AgentMessage
-	(*ServerMessage)(nil),                 // 28: org.apache.airavata.agent.ServerMessage
+	(*RequestNextJobUnit)(nil),            // 27: org.apache.airavata.agent.RequestNextJobUnit
+	(*JobUnitCompleted)(nil),              // 28: org.apache.airavata.agent.JobUnitCompleted
+	(*AssignJobUnit)(nil),                 // 29: org.apache.airavata.agent.AssignJobUnit
+	(*NoJobUnitAvailable)(nil),            // 30: org.apache.airavata.agent.NoJobUnitAvailable
+	(*AgentMessage)(nil),                  // 31: org.apache.airavata.agent.AgentMessage
+	(*ServerMessage)(nil),                 // 32: org.apache.airavata.agent.ServerMessage
 }
 var file_agent_communication_proto_depIdxs = []int32{
 	13, // 0: org.apache.airavata.agent.AsyncCommandListResponse.commands:type_name -> org.apache.airavata.agent.AsyncCommand
@@ -2342,26 +2858,30 @@ var file_agent_communication_proto_depIdxs = []int32{
 	11, // 11: org.apache.airavata.agent.AgentMessage.asyncCommandExecutionResponse:type_name -> org.apache.airavata.agent.AsyncCommandExecutionResponse
 	14, // 12: org.apache.airavata.agent.AgentMessage.asyncCommandListResponse:type_name -> org.apache.airavata.agent.AsyncCommandListResponse
 	16, // 13: org.apache.airavata.agent.AgentMessage.asyncCommandTerminateResponse:type_name -> org.apache.airavata.agent.AsyncCommandTerminateResponse
-	1,  // 14: org.apache.airavata.agent.ServerMessage.shutdownRequest:type_name -> org.apache.airavata.agent.ShutdownRequest
-	2,  // 15: org.apache.airavata.agent.ServerMessage.createAgentRequest:type_name -> org.apache.airavata.agent.CreateAgentRequest
-	4,  // 16: org.apache.airavata.agent.ServerMessage.terminateAgentRequest:type_name -> org.apache.airavata.agent.TerminateAgentRequest
-	6,  // 17: org.apache.airavata.agent.ServerMessage.envSetupRequest:type_name -> org.apache.airavata.agent.EnvSetupRequest
-	8,  // 18: org.apache.airavata.agent.ServerMessage.commandExecutionRequest:type_name -> org.apache.airavata.agent.CommandExecutionRequest
-	17, // 19: org.apache.airavata.agent.ServerMessage.pythonExecutionRequest:type_name -> org.apache.airavata.agent.PythonExecutionRequest
-	19, // 20: org.apache.airavata.agent.ServerMessage.jupyterExecutionRequest:type_name -> org.apache.airavata.agent.JupyterExecutionRequest
-	21, // 21: org.apache.airavata.agent.ServerMessage.kernelRestartRequest:type_name -> org.apache.airavata.agent.KernelRestartRequest
-	23, // 22: org.apache.airavata.agent.ServerMessage.tunnelCreationRequest:type_name -> org.apache.airavata.agent.TunnelCreationRequest
-	25, // 23: org.apache.airavata.agent.ServerMessage.tunnelTerminationRequest:type_name -> org.apache.airavata.agent.TunnelTerminationRequest
-	10, // 24: org.apache.airavata.agent.ServerMessage.asyncCommandExecutionRequest:type_name -> org.apache.airavata.agent.AsyncCommandExecutionRequest
-	12, // 25: org.apache.airavata.agent.ServerMessage.asyncCommandListRequest:type_name -> org.apache.airavata.agent.AsyncCommandListRequest
-	15, // 26: org.apache.airavata.agent.ServerMessage.asyncCommandTerminateRequest:type_name -> org.apache.airavata.agent.AsyncCommandTerminateRequest
-	27, // 27: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:input_type -> org.apache.airavata.agent.AgentMessage
-	28, // 28: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:output_type -> org.apache.airavata.agent.ServerMessage
-	28, // [28:29] is the sub-list for method output_type
-	27, // [27:28] is the sub-list for method input_type
-	27, // [27:27] is the sub-list for extension type_name
-	27, // [27:27] is the sub-list for extension extendee
-	0,  // [0:27] is the sub-list for field type_name
+	27, // 14: org.apache.airavata.agent.AgentMessage.requestNextJobUnit:type_name -> org.apache.airavata.agent.RequestNextJobUnit
+	28, // 15: org.apache.airavata.agent.AgentMessage.jobUnitCompleted:type_name -> org.apache.airavata.agent.JobUnitCompleted
+	1,  // 16: org.apache.airavata.agent.ServerMessage.shutdownRequest:type_name -> org.apache.airavata.agent.ShutdownRequest
+	2,  // 17: org.apache.airavata.agent.ServerMessage.createAgentRequest:type_name -> org.apache.airavata.agent.CreateAgentRequest
+	4,  // 18: org.apache.airavata.agent.ServerMessage.terminateAgentRequest:type_name -> org.apache.airavata.agent.TerminateAgentRequest
+	6,  // 19: org.apache.airavata.agent.ServerMessage.envSetupRequest:type_name -> org.apache.airavata.agent.EnvSetupRequest
+	8,  // 20: org.apache.airavata.agent.ServerMessage.commandExecutionRequest:type_name -> org.apache.airavata.agent.CommandExecutionRequest
+	17, // 21: org.apache.airavata.agent.ServerMessage.pythonExecutionRequest:type_name -> org.apache.airavata.agent.PythonExecutionRequest
+	19, // 22: org.apache.airavata.agent.ServerMessage.jupyterExecutionRequest:type_name -> org.apache.airavata.agent.JupyterExecutionRequest
+	21, // 23: org.apache.airavata.agent.ServerMessage.kernelRestartRequest:type_name -> org.apache.airavata.agent.KernelRestartRequest
+	23, // 24: org.apache.airavata.agent.ServerMessage.tunnelCreationRequest:type_name -> org.apache.airavata.agent.TunnelCreationRequest
+	25, // 25: org.apache.airavata.agent.ServerMessage.tunnelTerminationRequest:type_name -> org.apache.airavata.agent.TunnelTerminationRequest
+	10, // 26: org.apache.airavata.agent.ServerMessage.asyncCommandExecutionRequest:type_name -> org.apache.airavata.agent.AsyncCommandExecutionRequest
+	12, // 27: org.apache.airavata.agent.ServerMessage.asyncCommandListRequest:type_name -> org.apache.airavata.agent.AsyncCommandListRequest
+	15, // 28: org.apache.airavata.agent.ServerMessage.asyncCommandTerminateRequest:type_name -> org.apache.airavata.agent.AsyncCommandTerminateRequest
+	29, // 29: org.apache.airavata.agent.ServerMessage.assignJobUnit:type_name -> org.apache.airavata.agent.AssignJobUnit
+	30, // 30: org.apache.airavata.agent.ServerMessage.noJobUnitAvailable:type_name -> org.apache.airavata.agent.NoJobUnitAvailable
+	31, // 31: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:input_type -> org.apache.airavata.agent.AgentMessage
+	32, // 32: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:output_type -> org.apache.airavata.agent.ServerMessage
+	32, // [32:33] is the sub-list for method output_type
+	31, // [31:32] is the sub-list for method input_type
+	31, // [31:31] is the sub-list for extension type_name
+	31, // [31:31] is the sub-list for extension extendee
+	0,  // [0:31] is the sub-list for field type_name
 }
 
 func init() { file_agent_communication_proto_init() }
@@ -2369,7 +2889,7 @@ func file_agent_communication_proto_init() {
 	if File_agent_communication_proto != nil {
 		return
 	}
-	file_agent_communication_proto_msgTypes[27].OneofWrappers = []any{
+	file_agent_communication_proto_msgTypes[31].OneofWrappers = []any{
 		(*AgentMessage_AgentPing)(nil),
 		(*AgentMessage_CreateAgentResponse)(nil),
 		(*AgentMessage_TerminateAgentResponse)(nil),
@@ -2383,8 +2903,10 @@ func file_agent_communication_proto_init() {
 		(*AgentMessage_AsyncCommandExecutionResponse)(nil),
 		(*AgentMessage_AsyncCommandListResponse)(nil),
 		(*AgentMessage_AsyncCommandTerminateResponse)(nil),
+		(*AgentMessage_RequestNextJobUnit)(nil),
+		(*AgentMessage_JobUnitCompleted)(nil),
 	}
-	file_agent_communication_proto_msgTypes[28].OneofWrappers = []any{
+	file_agent_communication_proto_msgTypes[32].OneofWrappers = []any{
 		(*ServerMessage_ShutdownRequest)(nil),
 		(*ServerMessage_CreateAgentRequest)(nil),
 		(*ServerMessage_TerminateAgentRequest)(nil),
@@ -2398,14 +2920,16 @@ func file_agent_communication_proto_init() {
 		(*ServerMessage_AsyncCommandExecutionRequest)(nil),
 		(*ServerMessage_AsyncCommandListRequest)(nil),
 		(*ServerMessage_AsyncCommandTerminateRequest)(nil),
+		(*ServerMessage_AssignJobUnit)(nil),
+		(*ServerMessage_NoJobUnitAvailable)(nil),
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_communication_proto_rawDesc), len(file_agent_communication_proto_rawDesc)),
+			RawDescriptor: file_agent_communication_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   29,
+			NumMessages:   33,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
@@ -2414,6 +2938,7 @@ func file_agent_communication_proto_init() {
 		MessageInfos:      file_agent_communication_proto_msgTypes,
 	}.Build()
 	File_agent_communication_proto = out.File
+	file_agent_communication_proto_rawDesc = nil
 	file_agent_communication_proto_goTypes = nil
 	file_agent_communication_proto_depIdxs = nil
 }
diff --git a/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go b/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go
index cb3b6f99f4..fbf393bf7d 100644
--- a/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go
+++ b/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go
@@ -1,25 +1,27 @@
-// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
-// versions:
-// - protoc-gen-go-grpc v1.5.1
-// - protoc             v4.25.3
-// source: agent-communication.proto
-
+//
 // Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
+// or more contributor license agreements. See the NOTICE file
 // distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
+// regarding copyright ownership. The ASF licenses this file
 // to you 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
+// 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
+// KIND, either express or implied. See the License for the
 // specific language governing permissions and limitations
 // under the License.
+//
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc             v5.29.3
+// source: agent-communication.proto
 
 package protos
 
diff --git a/modules/agent-framework/proto/agent-communication.proto b/modules/agent-framework/proto/agent-communication.proto
index 9e1dd82542..16baa82a54 100644
--- a/modules/agent-framework/proto/agent-communication.proto
+++ b/modules/agent-framework/proto/agent-communication.proto
@@ -189,6 +189,28 @@ message TunnelTerminationResponse {
   string status = 2;
 }
 
+// Agent requesting the next job unit from the Job Workload
+message RequestNextJobUnit {
+  string agent_id = 1;
+}
+
+// Agent letting know the job unit is completed
+message JobUnitCompleted {
+  string job_unit_id = 1;
+  int32  exit_code   = 2;
+}
+
+// Server assigning the job unit with the resolved command
+message AssignJobUnit {
+  string job_unit_id      = 1;
+  string resolved_command = 2;
+}
+
+// Server indicating the agent that there are no job units to be consumed
+message NoJobUnitAvailable {
+  string reason = 1; // EMPTY, EMPTY_ALL_DONE, NO_ASSIGNMENT
+}
+
 message AgentMessage {
   oneof message {
     AgentPing agentPing = 1;
@@ -204,6 +226,9 @@ message AgentMessage {
     AsyncCommandExecutionResponse asyncCommandExecutionResponse = 11;
     AsyncCommandListResponse asyncCommandListResponse = 12;
     AsyncCommandTerminateResponse asyncCommandTerminateResponse = 13;
+
+    RequestNextJobUnit requestNextJobUnit = 20;
+    JobUnitCompleted   jobUnitCompleted   = 21;
   }
 }
 
@@ -222,5 +247,8 @@ message ServerMessage {
     AsyncCommandExecutionRequest asyncCommandExecutionRequest = 11;
     AsyncCommandListRequest asyncCommandListRequest = 12;
     AsyncCommandTerminateRequest asyncCommandTerminateRequest = 13;
+
+    AssignJobUnit       assignJobUnit       = 20;
+    NoJobUnitAvailable  noJobUnitAvailable  = 21;
   }
 }