You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2025/04/04 21:52:49 UTC

(airavata) 02/10: update /api/v1/agent endpoints, modify protos for env creation, update agent go script with env creation code.

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

dimuthuupe pushed a commit to branch cybershuttle-staging
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit 8939f0ced4b396f7ea9f2ca9635cfca782ec9380
Author: yasith <ya...@gatech.edu>
AuthorDate: Thu Apr 3 03:34:38 2025 -0400

    update /api/v1/agent endpoints, modify protos for env creation, update agent go script with env creation code.
---
 .../airavata_jupyter_magic/__init__.py             |    4 +-
 .../service/controllers/AgentController.java       |   86 +-
 .../service/handlers/AgentConnectionHandler.java   |  324 ++--
 .../service/handlers/AgentManagementHandler.java   |   27 +-
 ...mmandAck.java => AgentCommandExecutionAck.java} |    2 +-
 ...uest.java => AgentCommandExecutionRequest.java} |   32 +-
 ...nse.java => AgentCommandExecutionResponse.java} |   20 +-
 ...{AgentCommandAck.java => AgentEnvSetupAck.java} |    2 +-
 .../service/models/AgentEnvSetupRequest.java       |   45 +
 .../service/models/AgentEnvSetupResponse.java      |   31 +
 .../service/models/AgentJupyterExecutionAck.java   |    4 +
 ...uest.java => AgentJupyterExecutionRequest.java} |   31 +-
 ...nse.java => AgentJupyterExecutionResponse.java} |   21 +-
 ...chAgentRequest.java => AgentLaunchRequest.java} |    2 +-
 ...AgentResponse.java => AgentLaunchResponse.java} |    4 +-
 .../service/models/AgentPythonExecutionAck.java    |    4 +
 ...quest.java => AgentPythonExecutionRequest.java} |   41 +-
 ...onse.java => AgentPythonExecutionResponse.java} |   23 +-
 .../service/models/AgentPythonRunAck.java          |    4 -
 .../service/models/AgentPythonRunRequest.java      |   61 -
 ...ntResponse.java => AgentTerminateResponse.java} |    4 +-
 ...reationRequest.java => AgentTunnelRequest.java} |    2 +-
 ...entCommandAck.java => AgentTunnelResponse.java} |   15 +-
 .../service/models/JupyterExecutionAck.java        |    4 -
 .../service/models/JupyterExecutionResponse.java   |   41 -
 .../service/services/AiravataFileService.java      |   20 +-
 .../service/services/AiravataService.java          |   13 +-
 modules/agent-framework/airavata-agent/README.md   |    8 +-
 modules/agent-framework/airavata-agent/agent.go    |  710 ++++----
 modules/agent-framework/airavata-agent/kernel.py   |    6 +-
 .../protos/agent-communication.pb.go               | 1777 ++++++++++++--------
 .../protos/agent-communication_grpc.pb.go          |   85 +-
 .../proto/agent-communication.proto                |  165 +-
 33 files changed, 1950 insertions(+), 1668 deletions(-)

diff --git a/airavata-api/airavata-client-sdks/airavata-python-sdk/airavata_jupyter_magic/__init__.py b/airavata-api/airavata-client-sdks/airavata-python-sdk/airavata_jupyter_magic/__init__.py
index 0f6a3e32d7..44e425fa36 100644
--- a/airavata-api/airavata-client-sdks/airavata-python-sdk/airavata_jupyter_magic/__init__.py
+++ b/airavata-api/airavata-client-sdks/airavata-python-sdk/airavata_jupyter_magic/__init__.py
@@ -386,7 +386,7 @@ def run_on_runtime(rt_name: str, cell: str, store_history=False, silent=False, s
         excResult.error_in_exec = Exception(f"Runtime {rt_name} not found.")
         return excResult
 
-    url = api_base_url + '/api/v1/agent/executejupyterrequest'
+    url = api_base_url + '/api/v1/agent/execute/jupyter'
     data = {
         "sessionId": "session1",
         "keepAlive": True,
@@ -410,7 +410,7 @@ def run_on_runtime(rt_name: str, cell: str, store_history=False, silent=False, s
         return excResult
 
     while True:
-        url = api_base_url + "/api/v1/agent/executejupyterresponse/" + execution_id
+        url = api_base_url + "/api/v1/agent/execute/jupyter/" + execution_id
         response = requests.get(url, headers={'Accept': 'application/json'})
         json_response = response.json()
         if json_response.get('available'):
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
index c0380f7a2a..dedd735293 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
@@ -1,22 +1,39 @@
 package org.apache.airavata.agent.connection.service.controllers;
 
+import javax.validation.Valid;
+
 import org.apache.airavata.agent.connection.service.handlers.AgentConnectionHandler;
-import org.apache.airavata.agent.connection.service.models.*;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupAck;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupRequest;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupResponse;
+import org.apache.airavata.agent.connection.service.models.AgentInfoResponse;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentTunnelAck;
+import org.apache.airavata.agent.connection.service.models.AgentTunnelRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.Valid;
-
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @RequestMapping("/api/v1/agent")
 public class AgentController {
 
     private final static Logger logger = LoggerFactory.getLogger(AgentController.class);
-
-    private AgentConnectionHandler agentConnectionHandler;
+    private final AgentConnectionHandler agentConnectionHandler;
 
     public AgentController(AgentConnectionHandler agentConnectionHandler) {
         this.agentConnectionHandler = agentConnectionHandler;
@@ -27,63 +44,80 @@ public class AgentController {
         return ResponseEntity.accepted().body(agentConnectionHandler.isAgentUp(agentId));
     }
 
-    @PostMapping("/tunnel")
-    public ResponseEntity<AgentTunnelAck> runTunnelCreationOnAgent(@Valid @RequestBody AgentTunnelCreationRequest tunnelRequest) {
+    @PostMapping("/create/tunnel")
+    public ResponseEntity<AgentTunnelAck> runTunnelCreationOnAgent(@Valid @RequestBody AgentTunnelRequest tunnelRequest) {
         return ResponseEntity.accepted().body(agentConnectionHandler.runTunnelOnAgent(tunnelRequest));
     }
 
-    @PostMapping("/executecommandrequest")
-    public ResponseEntity<AgentCommandAck> runCommandOnAgent(@Valid @RequestBody AgentCommandRequest commandRequest) {
+    @PostMapping("/create/env")
+    public ResponseEntity<AgentEnvSetupAck> runEnvSetupOnAgent(@Valid @RequestBody AgentEnvSetupRequest envSetupRequest) {
+        logger.info("Received env setup request to run on agent {}", envSetupRequest.getAgentId());
+        if (agentConnectionHandler.isAgentUp(envSetupRequest.getAgentId()).isAgentUp()) {
+            return ResponseEntity.accepted().body(agentConnectionHandler.runEnvSetupOnAgent(envSetupRequest));
+        } else {
+            logger.warn("No agent is available to run on agent {}", envSetupRequest.getAgentId());
+            AgentEnvSetupAck ack = new AgentEnvSetupAck();
+            ack.setError("Agent not found");
+            return ResponseEntity.accepted().body(ack);
+        }
+    }
+
+    @GetMapping("/create/env/{executionId}")
+    public ResponseEntity<AgentEnvSetupResponse> getEnvSetupResponse(@PathVariable("executionId") String executionId) {
+        return ResponseEntity.accepted().body(agentConnectionHandler.getEnvSetupResponse(executionId));
+    }
+
+    @PostMapping("/execute/shell")
+    public ResponseEntity<AgentCommandExecutionAck> runCommandOnAgent(@Valid @RequestBody AgentCommandExecutionRequest commandRequest) {
         logger.info("Received command request to run on agent {}", commandRequest.getAgentId());
         if (agentConnectionHandler.isAgentUp(commandRequest.getAgentId()).isAgentUp()) {
             return ResponseEntity.accepted().body(agentConnectionHandler.runCommandOnAgent(commandRequest));
         } else {
             logger.warn("No agent is available to run on agent {}", commandRequest.getAgentId());
-            AgentCommandAck ack = new AgentCommandAck();
+            AgentCommandExecutionAck ack = new AgentCommandExecutionAck();
             ack.setError("Agent not found");
             return ResponseEntity.accepted().body(ack);
         }
     }
 
-    @GetMapping("/executecommandresponse/{executionId}")
-    public ResponseEntity<AgentCommandResponse> getExecutionResponse(@PathVariable("executionId") String executionId) {
-        return ResponseEntity.accepted().body(agentConnectionHandler.getAgentCommandResponse(executionId));
+    @GetMapping("/execute/shell/{executionId}")
+    public ResponseEntity<AgentCommandExecutionResponse> getExecutionResponse(@PathVariable("executionId") String executionId) {
+        return ResponseEntity.accepted().body(agentConnectionHandler.getCommandExecutionResponse(executionId));
     }
 
-    @PostMapping("/executejupyterrequest")
-    public ResponseEntity<JupyterExecutionAck> runJupyterOnAgent(@Valid @RequestBody JupyterExecutionRequest executionRequest) {
+    @PostMapping("/execute/jupyter")
+    public ResponseEntity<AgentJupyterExecutionAck> runJupyterOnAgent(@Valid @RequestBody AgentJupyterExecutionRequest executionRequest) {
         logger.info("Received jupyter execution request to run on agent {}", executionRequest.getAgentId());
         if (agentConnectionHandler.isAgentUp(executionRequest.getAgentId()).isAgentUp()) {
             return ResponseEntity.accepted().body(agentConnectionHandler.runJupyterOnAgent(executionRequest));
         } else {
             logger.warn("No agent is available to run on agent {}", executionRequest.getAgentId());
-            JupyterExecutionAck ack = new JupyterExecutionAck();
+            AgentJupyterExecutionAck ack = new AgentJupyterExecutionAck();
             ack.setError("Agent not found");
             return ResponseEntity.accepted().body(ack);
         }
     }
 
-    @GetMapping("/executejupyterresponse/{executionId}")
-    public ResponseEntity<JupyterExecutionResponse> getJupyterResponse(@PathVariable("executionId") String executionId) {
+    @GetMapping("/execute/jupyter/{executionId}")
+    public ResponseEntity<AgentJupyterExecutionResponse> getJupyterResponse(@PathVariable("executionId") String executionId) {
         return ResponseEntity.accepted().body(agentConnectionHandler.getJupyterExecutionResponse(executionId));
     }
 
-
-    @PostMapping("/executepythonrequest")
-    public ResponseEntity<AgentPythonRunAck> runPythonOnAgent(@Valid @RequestBody AgentPythonRunRequest pythonRunRequest) {
+    @PostMapping("/execute/python")
+    public ResponseEntity<AgentPythonExecutionAck> runPythonOnAgent(@Valid @RequestBody AgentPythonExecutionRequest pythonRunRequest) {
         logger.info("Received python execution request to run on agent {}", pythonRunRequest.getAgentId());
         if (agentConnectionHandler.isAgentUp(pythonRunRequest.getAgentId()).isAgentUp()) {
             return ResponseEntity.accepted().body(agentConnectionHandler.runPythonOnAgent(pythonRunRequest));
         } else {
             logger.warn("No agent is available to run on agent {}", pythonRunRequest.getAgentId());
-            AgentPythonRunAck ack = new AgentPythonRunAck();
+            AgentPythonExecutionAck ack = new AgentPythonExecutionAck();
             ack.setError("Agent not found");
             return ResponseEntity.accepted().body(ack);
         }
     }
 
-    @GetMapping("/executepythonresponse/{executionId}")
-    public ResponseEntity<AgentPythonRunResponse> getPythonResponse(@PathVariable("executionId") String executionId) {
+    @GetMapping("/execute/python/{executionId}")
+    public ResponseEntity<AgentPythonExecutionResponse> getPythonResponse(@PathVariable("executionId") String executionId) {
         return ResponseEntity.accepted().body(agentConnectionHandler.getPythonExecutionResponse(executionId));
     }
 
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 5fdb003c89..9ce52d4fe7 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
@@ -1,21 +1,42 @@
 package org.apache.airavata.agent.connection.service.handlers;
 
-import io.grpc.stub.StreamObserver;
-import net.devh.boot.grpc.server.service.GrpcService;
-import org.apache.airavata.agent.*;
-import org.apache.airavata.agent.JupyterExecutionResponse;
-import org.apache.airavata.agent.connection.service.models.*;
-import org.apache.airavata.agent.connection.service.models.JupyterExecutionRequest;
-import org.apache.airavata.agent.connection.service.services.AiravataFileService;
-import org.apache.airavata.fuse.ReadDirReq;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.airavata.agent.AgentCommunicationServiceGrpc;
+import org.apache.airavata.agent.AgentMessage;
+import org.apache.airavata.agent.AgentPing;
+import org.apache.airavata.agent.CommandExecutionRequest;
+import org.apache.airavata.agent.CommandExecutionResponse;
+import org.apache.airavata.agent.EnvSetupResponse;
+import org.apache.airavata.agent.JupyterExecutionResponse;
+import org.apache.airavata.agent.PythonExecutionRequest;
+import org.apache.airavata.agent.PythonExecutionResponse;
+import org.apache.airavata.agent.ServerMessage;
+import org.apache.airavata.agent.TunnelCreationRequest;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentCommandExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupAck;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupRequest;
+import org.apache.airavata.agent.connection.service.models.AgentEnvSetupResponse;
+import org.apache.airavata.agent.connection.service.models.AgentInfoResponse;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentJupyterExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionAck;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionRequest;
+import org.apache.airavata.agent.connection.service.models.AgentPythonExecutionResponse;
+import org.apache.airavata.agent.connection.service.models.AgentTunnelAck;
+import org.apache.airavata.agent.connection.service.models.AgentTunnelRequest;
+import org.apache.airavata.agent.connection.service.models.AgentTunnelResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
 
 @GrpcService
 public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentCommunicationServiceImplBase {
@@ -28,151 +49,158 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
     // <agentId, streamId>
     private final Map<String, String> AGENT_STREAM_MAPPING = new ConcurrentHashMap<>();
 
+    private final Map<String, EnvSetupResponse> ENV_SETUP_RESPONSE_CACHE = new ConcurrentHashMap<>();
     private final Map<String, CommandExecutionResponse> COMMAND_EXECUTION_RESPONSE_CACHE = new ConcurrentHashMap<>();
     private final Map<String, JupyterExecutionResponse> JUPYTER_EXECUTION_RESPONSE_CACHE = new ConcurrentHashMap<>();
     private final Map<String, PythonExecutionResponse> PYTHON_EXECUTION_RESPONSE_CACHE = new ConcurrentHashMap<>();
 
-    private final AiravataFileService airavataFileService;
-
-    public AgentConnectionHandler(AiravataFileService airavataFileService) {
-        this.airavataFileService = airavataFileService;
-    }
-
+    // response handling
     public AgentInfoResponse isAgentUp(String agentId) {
-
-        if (AGENT_STREAM_MAPPING.containsKey(agentId) &&
-                ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(agentId))) {
+        if (AGENT_STREAM_MAPPING.containsKey(agentId)
+                && ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(agentId))) {
             return new AgentInfoResponse(agentId, true);
         } else {
             return new AgentInfoResponse(agentId, false);
         }
     }
 
-    public AgentCommandResponse getAgentCommandResponse(String executionId) {
-        AgentCommandResponse agentCommandResponse = new AgentCommandResponse();
+    public AgentEnvSetupResponse getEnvSetupResponse(String executionId) {
+        AgentEnvSetupResponse envCreationResponse = new AgentEnvSetupResponse();
+        if (ENV_SETUP_RESPONSE_CACHE.containsKey(executionId)) {
+            envCreationResponse.setStatus(ENV_SETUP_RESPONSE_CACHE.get(executionId).getStatus());
+            envCreationResponse.setExecutionId(executionId);
+            envCreationResponse.setSetup(true);
+            ENV_SETUP_RESPONSE_CACHE.remove(executionId);
+        } else {
+            envCreationResponse.setSetup(false);
+        }
+        return envCreationResponse;
+    }
+
+    public AgentCommandExecutionResponse getCommandExecutionResponse(String executionId) {
+        AgentCommandExecutionResponse agentCommandResponse = new AgentCommandExecutionResponse();
         if (COMMAND_EXECUTION_RESPONSE_CACHE.containsKey(executionId)) {
             agentCommandResponse.setResponseString(COMMAND_EXECUTION_RESPONSE_CACHE.get(executionId).getResponseString());
             agentCommandResponse.setExecutionId(executionId);
-            agentCommandResponse.setAvailable(true);
+            agentCommandResponse.setExecuted(true);
             COMMAND_EXECUTION_RESPONSE_CACHE.remove(executionId);
         } else {
-            agentCommandResponse.setAvailable(false);
+            agentCommandResponse.setExecuted(false);
         }
         return agentCommandResponse;
     }
 
-    public org.apache.airavata.agent.connection.service.models.JupyterExecutionResponse getJupyterExecutionResponse(String executionId) {
-        org.apache.airavata.agent.connection.service.models.JupyterExecutionResponse executionResponse = new org.apache.airavata.agent.connection.service.models.JupyterExecutionResponse();
+    public AgentJupyterExecutionResponse getJupyterExecutionResponse(String executionId) {
+        AgentJupyterExecutionResponse executionResponse = new AgentJupyterExecutionResponse();
         if (JUPYTER_EXECUTION_RESPONSE_CACHE.containsKey(executionId)) {
             executionResponse.setResponseString(JUPYTER_EXECUTION_RESPONSE_CACHE.get(executionId).getResponseString());
             executionResponse.setExecutionId(executionId);
-            executionResponse.setAvailable(true);
+            executionResponse.setExecuted(true);
             JUPYTER_EXECUTION_RESPONSE_CACHE.remove(executionId);
         } else {
-            executionResponse.setAvailable(false);
+            executionResponse.setExecuted(false);
         }
         return executionResponse;
     }
 
-    public AgentTunnelAck runTunnelOnAgent(AgentTunnelCreationRequest tunnelRequest) {
-        AgentTunnelAck ack = new AgentTunnelAck();
-
-        if (AGENT_STREAM_MAPPING.containsKey(tunnelRequest.getAgentId()) &&
-                ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(tunnelRequest.getAgentId()))) {
-            String agentId = AGENT_STREAM_MAPPING.get(tunnelRequest.getAgentId());
-            StreamObserver<ServerMessage> streamObserver = ACTIVE_STREAMS.get(agentId);
-
-            try {
-                streamObserver.onNext(ServerMessage.newBuilder().setTunnelCreationRequest(TunnelCreationRequest.newBuilder()
-                        .setDestinationHost(tunnelRequest.getDestinationHost())
-                        .setDestinationPort(tunnelRequest.getDestinationPort())
-                        .setSourcePort(tunnelRequest.getSourcePort())
-                        .setSshUserName(tunnelRequest.getSshUserName())
-                        .setPassword(Optional.ofNullable(tunnelRequest.getPassword()).orElse(""))
-                        .setSshKeyPath(Optional.ofNullable(tunnelRequest.getSshKeyPath()).orElse(""))
-                        .build()).build());
-            } catch (Exception e) {
-                logger.error("Failed to submit tunnel creation request on agent {}", agentId, e);
-                ack.setError(e.getMessage());
-            }
-
-        } else {
-            logger.warn("No agent found to run the tunnel for agent id ", tunnelRequest.getAgentId());
-            ack.setError("No agent found to run the tunnel for agent id " + tunnelRequest.getAgentId());
-        }
-
-        return ack;
-    }
-
-    public AgentPythonRunResponse getPythonExecutionResponse(String executionId) {
-        AgentPythonRunResponse runResponse = new AgentPythonRunResponse();
+    public AgentPythonExecutionResponse getPythonExecutionResponse(String executionId) {
+        AgentPythonExecutionResponse runResponse = new AgentPythonExecutionResponse();
         if (PYTHON_EXECUTION_RESPONSE_CACHE.containsKey(executionId)) {
-            runResponse.setResponseString(PYTHON_EXECUTION_RESPONSE_CACHE.get(executionId).getResponseString());
             runResponse.setExecutionId(executionId);
-            runResponse.setAvailable(true);
+            runResponse.setExecuted(true);
+            runResponse.setResponseString(PYTHON_EXECUTION_RESPONSE_CACHE.get(executionId).getResponseString());
             PYTHON_EXECUTION_RESPONSE_CACHE.remove(executionId);
         } else {
-            runResponse.setAvailable(false);
+            runResponse.setExecuted(false);
         }
         return runResponse;
     }
 
-    public AgentPythonRunAck runPythonOnAgent(AgentPythonRunRequest pythonRunRequest) {
+    public AgentTunnelResponse getTunnelResponse(String executionId) {
+        AgentTunnelResponse tunnelResponse = new AgentTunnelResponse();
+        if (AGENT_STREAM_MAPPING.containsKey(executionId)
+                && ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(executionId))) {
+            tunnelResponse.setExecutionId(executionId);
+            tunnelResponse.setTunneled(true);
+        } else {
+            tunnelResponse.setTunneled(false);
+        }
+        return tunnelResponse;
+    }
+
+    // request handling
+    public AgentEnvSetupAck runEnvSetupOnAgent(AgentEnvSetupRequest envSetupRequest) {
         String executionId = UUID.randomUUID().toString();
-        AgentPythonRunAck ack = new AgentPythonRunAck();
+        AgentEnvSetupAck ack = new AgentEnvSetupAck();
         ack.setExecutionId(executionId);
-
-        Optional<StreamObserver<ServerMessage>> agentStreamObserver = getAgentStreamObserver(pythonRunRequest.getAgentId());
+        Optional<StreamObserver<ServerMessage>> agentStreamObserver = getAgentStreamObserver(envSetupRequest.getAgentId());
         if (agentStreamObserver.isPresent()) {
             try {
-                logger.info("Running a python on agent {}", pythonRunRequest.getAgentId());
-                agentStreamObserver.get().onNext(ServerMessage.newBuilder().setPythonExecutionRequest(
-                        PythonExecutionRequest.newBuilder()
+                logger.info("Running an env setup on agent {}", envSetupRequest.getAgentId());
+                agentStreamObserver.get().onNext(ServerMessage.newBuilder().setEnvSetupRequest(
+                        org.apache.airavata.agent.EnvSetupRequest.newBuilder()
                                 .setExecutionId(executionId)
-                                .setKeepAlive(pythonRunRequest.isKeepAlive())
-                                .setCode(pythonRunRequest.getCode())
-                                .addAllLibraries(pythonRunRequest.getLibraries())
-                                .setWorkingDir(pythonRunRequest.getParentExperimentId())).build());
+                                .setEnvName(envSetupRequest.getEnvName())
+                                .addAllLibraries(envSetupRequest.getLibraries())
+                                .addAllPip(envSetupRequest.getPip())
+                                .build()
+                ).build());
 
             } catch (Exception e) {
-                logger.error("Failed to submit python execution request {} on agent {}",
-                        executionId, pythonRunRequest.getAgentId(), e);
+                logger.error("Failed to submit env setup request {} on agent {}",
+                        executionId, envSetupRequest.getAgentId(), e);
                 ack.setError(e.getMessage());
             }
         } else {
-            logger.warn("No agent found to run python execution on agent {}", pythonRunRequest.getAgentId());
-            ack.setError("No agent found to run python execution on agent " + pythonRunRequest.getAgentId());
+            logger.warn("No agent found to run the env setup on agent {}", envSetupRequest.getAgentId());
+            ack.setError("No agent found to run the env setup on agent " + envSetupRequest.getAgentId());
         }
-
         return ack;
     }
 
-    private Optional<StreamObserver<ServerMessage>> getAgentStreamObserver(String agentId) {
-        if (AGENT_STREAM_MAPPING.containsKey(agentId) &&
-                ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(agentId))) {
-            String streamId = AGENT_STREAM_MAPPING.get(agentId);
+    public AgentCommandExecutionAck runCommandOnAgent(AgentCommandExecutionRequest commandRequest) {
+        String executionId = UUID.randomUUID().toString();
+        AgentCommandExecutionAck ack = new AgentCommandExecutionAck();
+        ack.setExecutionId(executionId);
+        if (AGENT_STREAM_MAPPING.containsKey(commandRequest.getAgentId())
+                && ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(commandRequest.getAgentId()))) {
+            String streamId = AGENT_STREAM_MAPPING.get(commandRequest.getAgentId());
             StreamObserver<ServerMessage> streamObserver = ACTIVE_STREAMS.get(streamId);
-            return Optional.ofNullable(streamObserver);
+            try {
+                logger.info("Running a command on agent {}", commandRequest.getAgentId());
+                streamObserver.onNext(ServerMessage.newBuilder().setCommandExecutionRequest(
+                        CommandExecutionRequest.newBuilder()
+                                .setExecutionId(executionId)
+                                .setEnvName(commandRequest.getEnvName())
+                                .setWorkingDir(commandRequest.getWorkingDir())
+                                .addAllArguments(commandRequest.getArguments()).build()).build());
+            } catch (Exception e) {
+                logger.error("Failed to submit command execution request {} on agent {}",
+                        executionId, commandRequest.getAgentId(), e);
+                ack.setError(e.getMessage());
+            }
         } else {
-            return Optional.empty();
+            logger.warn("No agent found to run the command on agent {}", commandRequest.getAgentId());
+            ack.setError("No agent found to run the command on agent " + commandRequest.getAgentId());
         }
+        return ack;
     }
-    public JupyterExecutionAck runJupyterOnAgent(JupyterExecutionRequest jupyterExecutionRequest) {
+
+    public AgentJupyterExecutionAck runJupyterOnAgent(AgentJupyterExecutionRequest jupyterExecutionRequest) {
         String executionId = UUID.randomUUID().toString();
-        JupyterExecutionAck ack = new JupyterExecutionAck();
+        AgentJupyterExecutionAck ack = new AgentJupyterExecutionAck();
         ack.setExecutionId(executionId);
-
         Optional<StreamObserver<ServerMessage>> agentStreamObserver = getAgentStreamObserver(jupyterExecutionRequest.getAgentId());
         if (agentStreamObserver.isPresent()) {
             try {
                 logger.info("Running a jupyter on agent {}", jupyterExecutionRequest.getAgentId());
                 agentStreamObserver.get().onNext(ServerMessage.newBuilder().setJupyterExecutionRequest(
-                        org.apache.airavata.agent.JupyterExecutionRequest.newBuilder().build().newBuilder()
+                        org.apache.airavata.agent.JupyterExecutionRequest.newBuilder()
                                 .setExecutionId(executionId)
-                                .setSessionId(jupyterExecutionRequest.getSessionId())
+                                .setEnvName(jupyterExecutionRequest.getEnvName())
                                 .setCode(jupyterExecutionRequest.getCode())
-                                .setKeepAlive(jupyterExecutionRequest.isKeepAlive()).build()).build());
-
+                                .build()
+                ).build());
             } catch (Exception e) {
                 logger.error("Failed to submit jupyter execution request {} on agent {}",
                         executionId, jupyterExecutionRequest.getAgentId(), e);
@@ -185,80 +213,104 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
         return ack;
     }
 
-    public AgentCommandAck runCommandOnAgent(AgentCommandRequest commandRequest) {
-
+    public AgentPythonExecutionAck runPythonOnAgent(AgentPythonExecutionRequest pythonRunRequest) {
         String executionId = UUID.randomUUID().toString();
-        AgentCommandAck ack = new AgentCommandAck();
+        AgentPythonExecutionAck ack = new AgentPythonExecutionAck();
         ack.setExecutionId(executionId);
-
-        if (AGENT_STREAM_MAPPING.containsKey(commandRequest.getAgentId()) &&
-                ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(commandRequest.getAgentId()))) {
-            String streamId = AGENT_STREAM_MAPPING.get(commandRequest.getAgentId());
-            StreamObserver<ServerMessage> streamObserver = ACTIVE_STREAMS.get(streamId);
-
+        Optional<StreamObserver<ServerMessage>> agentStreamObserver = getAgentStreamObserver(pythonRunRequest.getAgentId());
+        if (agentStreamObserver.isPresent()) {
             try {
-                logger.info("Running a command on agent {}", commandRequest.getAgentId());
-                streamObserver.onNext(ServerMessage.newBuilder().setCommandExecutionRequest(
-                        CommandExecutionRequest.newBuilder()
+                logger.info("Running a python on agent {}", pythonRunRequest.getAgentId());
+                agentStreamObserver.get().onNext(ServerMessage.newBuilder().setPythonExecutionRequest(
+                        PythonExecutionRequest.newBuilder()
                                 .setExecutionId(executionId)
-                                .setWorkingDir(commandRequest.getWorkingDir())
-                                .addAllArguments(commandRequest.getArguments()).build()).build());
-
+                                .setEnvName(pythonRunRequest.getEnvName())
+                                .setWorkingDir(pythonRunRequest.getWorkingDir())
+                                .setCode(pythonRunRequest.getCode())
+                                .build()
+                ).build());
             } catch (Exception e) {
-                logger.error("Failed to submit command execution request {} on agent {}",
-                        executionId, commandRequest.getAgentId(), e);
+                logger.error("Failed to submit python execution request {} on agent {}",
+                        executionId, pythonRunRequest.getAgentId(), e);
                 ack.setError(e.getMessage());
             }
         } else {
-            logger.warn("No agent found to run the command on agent {}", commandRequest.getAgentId());
-            ack.setError("No agent found to run the command on agent " + commandRequest.getAgentId());
+            logger.warn("No agent found to run python execution on agent {}", pythonRunRequest.getAgentId());
+            ack.setError("No agent found to run python execution on agent " + pythonRunRequest.getAgentId());
         }
+        return ack;
+    }
 
+    public AgentTunnelAck runTunnelOnAgent(AgentTunnelRequest tunnelRequest) {
+        AgentTunnelAck ack = new AgentTunnelAck();
+        if (AGENT_STREAM_MAPPING.containsKey(tunnelRequest.getAgentId())
+                && ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(tunnelRequest.getAgentId()))) {
+            String agentId = AGENT_STREAM_MAPPING.get(tunnelRequest.getAgentId());
+            StreamObserver<ServerMessage> streamObserver = ACTIVE_STREAMS.get(agentId);
+            try {
+                streamObserver.onNext(ServerMessage.newBuilder().setTunnelCreationRequest(
+                        TunnelCreationRequest.newBuilder()
+                                .setDestinationHost(tunnelRequest.getDestinationHost())
+                                .setDestinationPort(tunnelRequest.getDestinationPort())
+                                .setSourcePort(tunnelRequest.getSourcePort())
+                                .setSshUserName(tunnelRequest.getSshUserName())
+                                .setPassword(Optional.ofNullable(tunnelRequest.getPassword()).orElse(""))
+                                .setSshKeyPath(Optional.ofNullable(tunnelRequest.getSshKeyPath()).orElse(""))
+                                .build()
+                ).build());
+            } catch (Exception e) {
+                logger.error("Failed to submit tunnel creation request on agent {}", agentId, e);
+                ack.setError(e.getMessage());
+            }
+        } else {
+            logger.warn("No agent found to run the tunnel for agent id ", tunnelRequest.getAgentId());
+            ack.setError("No agent found to run the tunnel for agent id " + tunnelRequest.getAgentId());
+        }
         return ack;
     }
 
+    // internal handlers
     private void handleAgentPing(AgentPing agentPing, String streamId) {
         logger.info("Received agent ping for agent id {}", agentPing.getAgentId());
         AGENT_STREAM_MAPPING.put(agentPing.getAgentId(), streamId);
     }
 
-    private void handleCommandExecutionResponse (CommandExecutionResponse commandExecutionResponse) {
-        logger.info("Received command execution response for execution id {}", commandExecutionResponse.getExecutionId());
-        COMMAND_EXECUTION_RESPONSE_CACHE.put(commandExecutionResponse.getExecutionId(), commandExecutionResponse);
+    private void handleEnvSetupResponse(EnvSetupResponse envSetupResponse) {
+        logger.info("Received env setup response for execution id {}", envSetupResponse.getExecutionId());
+        ENV_SETUP_RESPONSE_CACHE.put(envSetupResponse.getExecutionId(), envSetupResponse);
     }
 
-    private void handleContainerExecutionResponse (ContainerExecutionResponse containerExecutionResponse) {
-
-    }
-
-    private void handleAgentTerminationResponse (TerminateExecutionResponse terminateExecutionResponse) {
-
+    private void handleCommandExecutionResponse(CommandExecutionResponse commandExecutionResponse) {
+        logger.info("Received command execution response for execution id {}", commandExecutionResponse.getExecutionId());
+        COMMAND_EXECUTION_RESPONSE_CACHE.put(commandExecutionResponse.getExecutionId(), commandExecutionResponse);
     }
 
-    private void handleJupyterExecutionResponse (JupyterExecutionResponse executionResponse) {
+    private void handleJupyterExecutionResponse(JupyterExecutionResponse executionResponse) {
         logger.info("Received jupyter execution response for execution id {}", executionResponse.getExecutionId());
         JUPYTER_EXECUTION_RESPONSE_CACHE.put(executionResponse.getExecutionId(), executionResponse);
     }
 
-    private void handlePythonExecutionResponse (PythonExecutionResponse executionResponse) {
+    private void handlePythonExecutionResponse(PythonExecutionResponse executionResponse) {
         logger.info("Received python execution response for execution id {}", executionResponse.getExecutionId());
         PYTHON_EXECUTION_RESPONSE_CACHE.put(executionResponse.getExecutionId(), executionResponse);
     }
 
-
-    private void handleReadDirRequest(ReadDirReq readDirReq, StreamObserver<ServerMessage> responseObserver) {
-        airavataFileService.handleReadDirRequest(readDirReq, responseObserver);
-    }
-
-    private String generateStreamId() {
-        // Generate a unique ID for each stream
-        return java.util.UUID.randomUUID().toString();
+    // routing
+    private Optional<StreamObserver<ServerMessage>> getAgentStreamObserver(String agentId) {
+        if (AGENT_STREAM_MAPPING.containsKey(agentId)
+                && ACTIVE_STREAMS.containsKey(AGENT_STREAM_MAPPING.get(agentId))) {
+            String streamId = AGENT_STREAM_MAPPING.get(agentId);
+            StreamObserver<ServerMessage> streamObserver = ACTIVE_STREAMS.get(streamId);
+            return Optional.ofNullable(streamObserver);
+        } else {
+            return Optional.empty();
+        }
     }
 
     @Override
     public StreamObserver<AgentMessage> createMessageBus(StreamObserver<ServerMessage> responseObserver) {
 
-        String streamId = generateStreamId();
+        String streamId = UUID.randomUUID().toString();
         ACTIVE_STREAMS.put(streamId, responseObserver);
 
         return new StreamObserver<AgentMessage>() {
@@ -272,20 +324,14 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
                     case COMMANDEXECUTIONRESPONSE -> {
                         handleCommandExecutionResponse(request.getCommandExecutionResponse());
                     }
-                    case CONTAINEREXECUTIONRESPONSE -> {
-                        handleContainerExecutionResponse(request.getContainerExecutionResponse());
-                    }
-                    case TERMINATEEXECUTIONRESPONSE -> {
-                        handleAgentTerminationResponse(request.getTerminateExecutionResponse());
-                    }
                     case JUPYTEREXECUTIONRESPONSE -> {
                         handleJupyterExecutionResponse(request.getJupyterExecutionResponse());
                     }
                     case PYTHONEXECUTIONRESPONSE -> {
                         handlePythonExecutionResponse(request.getPythonExecutionResponse());
                     }
-                    case READDIRREQ -> {
-                        handleReadDirRequest(request.getReadDirReq(), responseObserver);
+                    case ENVSETUPRESPONSE -> {
+                        handleEnvSetupResponse(request.getEnvSetupResponse());
                     }
                 }
             }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
index f4e6bbb3b1..acc2e003a0 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
@@ -1,10 +1,15 @@
 package org.apache.airavata.agent.connection.service.handlers;
 
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
 import org.apache.airavata.agent.connection.service.UserContext;
 import org.apache.airavata.agent.connection.service.config.ClusterApplicationConfig;
-import org.apache.airavata.agent.connection.service.models.LaunchAgentRequest;
-import org.apache.airavata.agent.connection.service.models.LaunchAgentResponse;
-import org.apache.airavata.agent.connection.service.models.TerminateAgentResponse;
+import org.apache.airavata.agent.connection.service.models.AgentLaunchRequest;
+import org.apache.airavata.agent.connection.service.models.AgentLaunchResponse;
+import org.apache.airavata.agent.connection.service.models.AgentTerminateResponse;
 import org.apache.airavata.agent.connection.service.services.AiravataService;
 import org.apache.airavata.api.Airavata;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
@@ -22,12 +27,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.io.File;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
 @Service
 public class AgentManagementHandler {
 
@@ -46,12 +45,12 @@ public class AgentManagementHandler {
         this.clusterApplicationConfig = clusterApplicationConfig;
     }
 
-    public TerminateAgentResponse terminateExperiment(String experimentId) {
+    public AgentTerminateResponse terminateExperiment(String experimentId) {
         try {
             Airavata.Client airavata = airavataService.airavata();
             ExperimentModel experiment = airavata.getExperiment(UserContext.authzToken(), experimentId);
             airavata.terminateExperiment(UserContext.authzToken(), experiment.getExperimentId(), experiment.getGatewayId());
-            return new TerminateAgentResponse(experimentId, true);
+            return new AgentTerminateResponse(experimentId, true);
         } catch (Exception e) {
             LOGGER.error("Error terminating experiment {}", experimentId, e);
             throw new RuntimeException("Error terminating experiment with the id: " + experimentId, e);
@@ -79,7 +78,7 @@ public class AgentManagementHandler {
         }
     }
 
-    public LaunchAgentResponse createAndLaunchExperiment(LaunchAgentRequest req) {
+    public AgentLaunchResponse createAndLaunchExperiment(AgentLaunchRequest req) {
         try {
             String agentId = "agent_" + UUID.randomUUID().toString();
             LOGGER.info("Creating an Airavata Experiment for {} with agent id {}", req.getExperimentName(), agentId);
@@ -88,7 +87,7 @@ public class AgentManagementHandler {
             String experimentId = airavataService.airavata().createExperiment(UserContext.authzToken(), experiment.getGatewayId(), experiment);
             LOGGER.info("Launching the application, Id: {}, Name: {}", experimentId, experiment.getExperimentName());
             airavataService.airavata().launchExperiment(UserContext.authzToken(), experimentId, experiment.getGatewayId());
-            return new LaunchAgentResponse(agentId, experimentId);
+            return new AgentLaunchResponse(agentId, experimentId);
         } catch (TException e) {
             LOGGER.error("Error while creating the experiment with the name: {}", req.getExperimentName(), e);
             throw new RuntimeException("Error while creating the experiment with the name: " + req.getExperimentName(), e);
@@ -121,7 +120,7 @@ public class AgentManagementHandler {
         }
     }
 
-    private ExperimentModel generateExperiment(LaunchAgentRequest req, String agentId) throws TException {
+    private ExperimentModel generateExperiment(AgentLaunchRequest req, String agentId) throws TException {
         Airavata.Client airavataClient = airavataService.airavata();
 
         String experimentName = req.getExperimentName();
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionAck.java
similarity index 91%
copy from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
copy to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionAck.java
index ad1e2843db..7faa0f6a3e 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionAck.java
@@ -1,6 +1,6 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentCommandAck {
+public class AgentCommandExecutionAck {
     private String executionId;
     private String error;
 
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionRequest.java
similarity index 76%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionRequest.java
index 4e90e5f0f0..d9d61fe11d 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionRequest.java
@@ -3,17 +3,27 @@ package org.apache.airavata.agent.connection.service.models;
 import java.util.ArrayList;
 import java.util.List;
 
-public class AgentCommandRequest {
-    private List<String> arguments = new ArrayList<>();
-    private String workingDir;
+public class AgentCommandExecutionRequest {
+
     private String agentId;
+    private String envName;
+    private String workingDir;
+    private List<String> arguments = new ArrayList<>();
 
-    public List<String> getArguments() {
-        return arguments;
+    public String getAgentId() {
+        return agentId;
     }
 
-    public void setArguments(List<String> arguments) {
-        this.arguments = arguments;
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+    public String getEnvName() {
+        return envName;
+    }
+
+    public void setEnvName(String envName) {
+        this.envName = envName;
     }
 
     public String getWorkingDir() {
@@ -24,11 +34,11 @@ public class AgentCommandRequest {
         this.workingDir = workingDir;
     }
 
-    public String getAgentId() {
-        return agentId;
+    public List<String> getArguments() {
+        return arguments;
     }
 
-    public void setAgentId(String agentId) {
-        this.agentId = agentId;
+    public void setArguments(List<String> arguments) {
+        this.arguments = arguments;
     }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionResponse.java
similarity index 70%
copy from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java
copy to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionResponse.java
index 74cfb4734f..10bdb90960 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandExecutionResponse.java
@@ -1,9 +1,9 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentCommandResponse {
+public class AgentCommandExecutionResponse {
     private String executionId;
+    private boolean executed;
     private String responseString;
-    private boolean isAvailable;
 
     public String getExecutionId() {
         return executionId;
@@ -13,19 +13,19 @@ public class AgentCommandResponse {
         this.executionId = executionId;
     }
 
-    public String getResponseString() {
-        return responseString;
+    public boolean getExecuted() {
+        return executed;
     }
 
-    public void setResponseString(String responseString) {
-        this.responseString = responseString;
+    public void setExecuted(boolean executed) {
+        this.executed = executed;
     }
 
-    public boolean isAvailable() {
-        return isAvailable;
+    public String getResponseString() {
+        return responseString;
     }
 
-    public void setAvailable(boolean available) {
-        isAvailable = available;
+    public void setResponseString(String responseString) {
+        this.responseString = responseString;
     }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupAck.java
similarity index 92%
copy from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
copy to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupAck.java
index ad1e2843db..eafd602f8a 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupAck.java
@@ -1,6 +1,6 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentCommandAck {
+public class AgentEnvSetupAck {
     private String executionId;
     private String error;
 
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupRequest.java
new file mode 100644
index 0000000000..89dc60646d
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupRequest.java
@@ -0,0 +1,45 @@
+package org.apache.airavata.agent.connection.service.models;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AgentEnvSetupRequest {
+
+    private String agentId;
+    private String envName;
+    private List<String> libraries = new ArrayList<>();
+    private List<String> pip = new ArrayList<>();
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+    public String getEnvName() {
+        return envName;
+    }
+
+    public void setEnvName(String envName) {
+        this.envName = envName;
+    }
+
+    public List<String> getLibraries() {
+        return libraries;
+    }
+
+    public void setLibraries(List<String> libraries) {
+        this.libraries = libraries;
+    }
+
+    public List<String> getPip() {
+        return pip;
+    }
+
+    public void setPip(List<String> pip) {
+        this.pip = pip;
+    }
+
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupResponse.java
new file mode 100644
index 0000000000..f76d798e1c
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentEnvSetupResponse.java
@@ -0,0 +1,31 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentEnvSetupResponse {
+    private String executionId;
+    private boolean setup;
+    private String status;
+
+    public String getExecutionId() {
+        return executionId;
+    }
+
+    public void setExecutionId(String executionId) {
+        this.executionId = executionId;
+    }
+
+    public boolean getSetup() {
+        return setup;
+    }
+
+    public void setSetup(boolean setup) {
+        this.setup = setup;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionAck.java
new file mode 100644
index 0000000000..1bb76e9984
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionAck.java
@@ -0,0 +1,4 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentJupyterExecutionAck extends AgentCommandExecutionAck {
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionRequest.java
similarity index 50%
copy from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java
copy to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionRequest.java
index 2fe60f7c06..d5a62cb0c5 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionRequest.java
@@ -1,25 +1,24 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class JupyterExecutionRequest {
-    private String sessionId;
-    private boolean keepAlive;
-    private String code;
+public class AgentJupyterExecutionRequest {
     private String agentId;
+    private String envName;
+    private String code;
 
-    public String getSessionId() {
-        return sessionId;
+    public String getAgentId() {
+        return agentId;
     }
 
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
     }
 
-    public boolean isKeepAlive() {
-        return keepAlive;
+    public String getEnvName() {
+        return envName;
     }
 
-    public void setKeepAlive(boolean keepAlive) {
-        this.keepAlive = keepAlive;
+    public void setEnvName(String envName) {
+        this.envName = envName;
     }
 
     public String getCode() {
@@ -29,12 +28,4 @@ public class JupyterExecutionRequest {
     public void setCode(String code) {
         this.code = code;
     }
-
-    public String getAgentId() {
-        return agentId;
-    }
-
-    public void setAgentId(String agentId) {
-        this.agentId = agentId;
-    }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionResponse.java
similarity index 55%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunResponse.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionResponse.java
index 1cdeccf64a..3efbf2d966 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunResponse.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentJupyterExecutionResponse.java
@@ -1,11 +1,10 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentPythonRunResponse {
+public class AgentJupyterExecutionResponse {
 
     private String executionId;
-    private String sessionId;
+    private boolean executed;
     private String responseString;
-    private boolean isAvailable;
 
     public String getExecutionId() {
         return executionId;
@@ -15,12 +14,12 @@ public class AgentPythonRunResponse {
         this.executionId = executionId;
     }
 
-    public String getSessionId() {
-        return sessionId;
+    public boolean getExecuted() {
+        return executed;
     }
 
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
+    public void setExecuted(boolean executed) {
+        this.executed = executed;
     }
 
     public String getResponseString() {
@@ -30,12 +29,4 @@ public class AgentPythonRunResponse {
     public void setResponseString(String responseString) {
         this.responseString = responseString;
     }
-
-    public boolean isAvailable() {
-        return isAvailable;
-    }
-
-    public void setAvailable(boolean available) {
-        isAvailable = available;
-    }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchRequest.java
similarity index 98%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentRequest.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchRequest.java
index cb12e7fd17..c39536f1bf 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentRequest.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchRequest.java
@@ -2,7 +2,7 @@ package org.apache.airavata.agent.connection.service.models;
 
 import org.apache.commons.lang3.StringUtils;
 
-public class LaunchAgentRequest {
+public class AgentLaunchRequest {
 
     private String experimentName;
     private String projectName;
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchResponse.java
similarity index 88%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentResponse.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchResponse.java
index 23c5650b33..ad833d30b9 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/LaunchAgentResponse.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentLaunchResponse.java
@@ -1,11 +1,11 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class LaunchAgentResponse {
+public class AgentLaunchResponse {
     private String agentId;
     private String experimentId;
     private String processId;
 
-    public LaunchAgentResponse(String agentId, String experimentId) {
+    public AgentLaunchResponse(String agentId, String experimentId) {
         this.agentId = agentId;
         this.experimentId = experimentId;
     }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionAck.java
new file mode 100644
index 0000000000..7fa7930174
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionAck.java
@@ -0,0 +1,4 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentPythonExecutionAck extends AgentCommandExecutionAck {
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionRequest.java
similarity index 51%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionRequest.java
index 2fe60f7c06..a0b5d7b2c9 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionRequest.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionRequest.java
@@ -1,40 +1,41 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class JupyterExecutionRequest {
-    private String sessionId;
-    private boolean keepAlive;
-    private String code;
+public class AgentPythonExecutionRequest {
+
     private String agentId;
+    private String envName;
+    private String workingDir;
+    private String code;
 
-    public String getSessionId() {
-        return sessionId;
+    public String getAgentId() {
+        return agentId;
     }
 
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
     }
 
-    public boolean isKeepAlive() {
-        return keepAlive;
+    public String getEnvName() {
+        return envName;
     }
 
-    public void setKeepAlive(boolean keepAlive) {
-        this.keepAlive = keepAlive;
+    public void setEnvName(String envName) {
+        this.envName = envName;
     }
 
-    public String getCode() {
-        return code;
+    public String getWorkingDir() {
+        return workingDir;
     }
 
-    public void setCode(String code) {
-        this.code = code;
+    public void setWorkingDir(String workingDir) {
+        this.workingDir = workingDir;
     }
 
-    public String getAgentId() {
-        return agentId;
+    public String getCode() {
+        return code;
     }
 
-    public void setAgentId(String agentId) {
-        this.agentId = agentId;
+    public void setCode(String code) {
+        this.code = code;
     }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionResponse.java
similarity index 60%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionResponse.java
index 74cfb4734f..d4e128e28b 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandResponse.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonExecutionResponse.java
@@ -1,31 +1,32 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentCommandResponse {
+public class AgentPythonExecutionResponse {
+
     private String executionId;
+    private boolean executed;
     private String responseString;
-    private boolean isAvailable;
 
     public String getExecutionId() {
-        return executionId;
+        return this.executionId;
     }
 
     public void setExecutionId(String executionId) {
         this.executionId = executionId;
     }
 
-    public String getResponseString() {
-        return responseString;
+    public boolean getExecuted() {
+        return this.executed;
     }
 
-    public void setResponseString(String responseString) {
-        this.responseString = responseString;
+    public void setExecuted(boolean executed) {
+        this.executed = executed;
     }
 
-    public boolean isAvailable() {
-        return isAvailable;
+    public String getResponseString() {
+        return this.responseString;
     }
 
-    public void setAvailable(boolean available) {
-        isAvailable = available;
+    public void setResponseString(String responseString) {
+        this.responseString = responseString;
     }
 }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunAck.java
deleted file mode 100644
index 368d2d7888..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunAck.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.apache.airavata.agent.connection.service.models;
-
-public class AgentPythonRunAck extends AgentCommandAck {
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunRequest.java
deleted file mode 100644
index b5673c14de..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentPythonRunRequest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.apache.airavata.agent.connection.service.models;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class AgentPythonRunRequest {
-    private List<String> libraries = new ArrayList<>();
-    private String code;
-    private String pythonVersion;
-    private String parentExperimentId;
-    private boolean keepAlive;
-    private String agentId;
-
-    public List<String> getLibraries() {
-        return libraries;
-    }
-
-    public void setLibraries(List<String> libraries) {
-        this.libraries = libraries;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getPythonVersion() {
-        return pythonVersion;
-    }
-
-    public void setPythonVersion(String pythonVersion) {
-        this.pythonVersion = pythonVersion;
-    }
-
-    public String getParentExperimentId() {
-        return parentExperimentId;
-    }
-
-    public void setParentExperimentId(String parentExperimentId) {
-        this.parentExperimentId = parentExperimentId;
-    }
-
-    public boolean isKeepAlive() {
-        return keepAlive;
-    }
-
-    public void setKeepAlive(boolean keepAlive) {
-        this.keepAlive = keepAlive;
-    }
-
-    public String getAgentId() {
-        return agentId;
-    }
-
-    public void setAgentId(String agentId) {
-        this.agentId = agentId;
-    }
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/TerminateAgentResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTerminateResponse.java
similarity index 84%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/TerminateAgentResponse.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTerminateResponse.java
index e41644fe7e..a60c0ac9e8 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/TerminateAgentResponse.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTerminateResponse.java
@@ -1,10 +1,10 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class TerminateAgentResponse {
+public class AgentTerminateResponse {
     private String experimentId;
     private boolean terminated;
 
-    public TerminateAgentResponse(String experimentId, boolean terminated) {
+    public AgentTerminateResponse(String experimentId, boolean terminated) {
         this.experimentId = experimentId;
         this.terminated = terminated;
     }
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelRequest.java
similarity index 97%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelRequest.java
index 71c954fc00..3c3f59cbae 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelRequest.java
@@ -1,6 +1,6 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentTunnelCreationRequest {
+public class AgentTunnelRequest {
     private String agentId;
     private String destinationHost;
     private String destinationPort;
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelResponse.java
similarity index 57%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
rename to modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelResponse.java
index ad1e2843db..a38df90cd8 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelResponse.java
@@ -1,8 +1,9 @@
 package org.apache.airavata.agent.connection.service.models;
 
-public class AgentCommandAck {
+public class AgentTunnelResponse {
+
     private String executionId;
-    private String error;
+    private boolean tunneled;
 
     public String getExecutionId() {
         return executionId;
@@ -12,11 +13,11 @@ public class AgentCommandAck {
         this.executionId = executionId;
     }
 
-    public String getError() {
-        return error;
+    public boolean isTunneled() {
+        return tunneled;
     }
 
-    public void setError(String error) {
-        this.error = error;
+    public void setTunneled(boolean tunneled) {
+        this.tunneled = tunneled;
     }
-}
\ No newline at end of file
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionAck.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionAck.java
deleted file mode 100644
index 125adcc2bd..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionAck.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.apache.airavata.agent.connection.service.models;
-
-public class JupyterExecutionAck extends AgentCommandAck {
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionResponse.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionResponse.java
deleted file mode 100644
index bd58c80ffa..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/models/JupyterExecutionResponse.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.apache.airavata.agent.connection.service.models;
-
-public class JupyterExecutionResponse {
-
-    private String executionId;
-    private String sessionId;
-    private String responseString;
-    private boolean isAvailable;
-
-    public String getExecutionId() {
-        return executionId;
-    }
-
-    public void setExecutionId(String executionId) {
-        this.executionId = executionId;
-    }
-
-    public String getSessionId() {
-        return sessionId;
-    }
-
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
-    }
-
-    public String getResponseString() {
-        return responseString;
-    }
-
-    public void setResponseString(String responseString) {
-        this.responseString = responseString;
-    }
-
-    public boolean isAvailable() {
-        return isAvailable;
-    }
-
-    public void setAvailable(boolean available) {
-        isAvailable = available;
-    }
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
index 0398341d10..ac56bd3895 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
@@ -1,10 +1,9 @@
 package org.apache.airavata.agent.connection.service.services;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.protobuf.Timestamp;
-import io.grpc.Status;
-import io.grpc.stub.StreamObserver;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.airavata.agent.ServerMessage;
 import org.apache.airavata.agent.connection.service.UserContext;
 import org.apache.airavata.agent.connection.service.models.DirectoryInfo;
@@ -25,9 +24,12 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.protobuf.Timestamp;
+
+import io.grpc.Status;
+import io.grpc.stub.StreamObserver;
 
 @Service
 public class AiravataFileService {
@@ -96,7 +98,7 @@ public class AiravataFileService {
             responseObserver.onError(Status.INTERNAL.withDescription("Failed to fetch experiments  when trying to read the directory").asRuntimeException());
         }
 
-        responseObserver.onNext(ServerMessage.newBuilder().setReadDirRes(readDirResBuilder.build()).build());
+        // responseObserver.onNext(ServerMessage.newBuilder().setReadDirRes(readDirResBuilder.build()).build());
         responseObserver.onCompleted();
     }
 
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
index 85adb15b89..69b30a1a51 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
@@ -1,6 +1,11 @@
 package org.apache.airavata.agent.connection.service.services;
 
-import io.micrometer.common.util.StringUtils;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import org.apache.airavata.agent.connection.service.UserContext;
 import org.apache.airavata.api.Airavata;
 import org.apache.airavata.api.client.AiravataClientFactory;
@@ -16,11 +21,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import io.micrometer.common.util.StringUtils;
 
 @Service
 public class AiravataService {
diff --git a/modules/agent-framework/airavata-agent/README.md b/modules/agent-framework/airavata-agent/README.md
index f8f4963f3e..2868723b54 100644
--- a/modules/agent-framework/airavata-agent/README.md
+++ b/modules/agent-framework/airavata-agent/README.md
@@ -36,7 +36,7 @@ env GOOS=linux GOARCH=amd64 go build
 
 
 ```
-POST http://localhost:18880/api/v1/agent/executecommandrequest
+POST http://localhost:18880/api/v1/agent/execute/shell
 
 {
     "agentId": "agent1",
@@ -46,7 +46,7 @@ POST http://localhost:18880/api/v1/agent/executecommandrequest
 ```
 
 ```
-http://localhost:18880/api/v1/agent/executejupyterrequest
+http://localhost:18880/api/v1/agent/execute/jupyter
 
 {
     "sessionId": "session1",
@@ -63,7 +63,7 @@ Response
 }
 ```
 ```
-http://localhost:18880/api/v1/agent/executejupyterresponse/22f02087-87cc-4e90-bc3b-3b969179c31b
+http://localhost:18880/api/v1/agent/execute/jupyter/22f02087-87cc-4e90-bc3b-3b969179c31b
 
 Response
 
@@ -76,7 +76,7 @@ Response
 ```
 
 ```
-POST http://localhost:18880/api/v1/agent/tunnel
+POST http://localhost:18880/api/v1/agent/create/tunnel
 
 {
     "destinationHost": "32.241.33.22",
diff --git a/modules/agent-framework/airavata-agent/agent.go b/modules/agent-framework/airavata-agent/agent.go
index 3ae86fb793..a89c30f258 100644
--- a/modules/agent-framework/airavata-agent/agent.go
+++ b/modules/agent-framework/airavata-agent/agent.go
@@ -11,6 +11,7 @@ import (
 	"log"
 	"net"
 	"net/http"
+	"net/url"
 	"os"
 	"os/exec"
 	"strings"
@@ -20,462 +21,397 @@ import (
 	"google.golang.org/grpc/credentials/insecure"
 )
 
+type Stream = grpc.BidiStreamingClient[protos.AgentMessage, protos.ServerMessage]
+
 func main() {
 
-	args := os.Args[1:]
-	serverUrl := args[0]
-	agentId := args[1]
-	grpcStreamChannel := make(chan struct{})
-	kernelChannel := make(chan struct{})
+	// get CLI args
+	serverUrl := os.Args[0]
+	agentId := os.Args[1]
 
 	conn, err := grpc.NewClient(serverUrl, grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
-		log.Fatalf("did not connect: %v", err)
+		log.Fatalf("[agent.go] main() Did not connect to %s: %v\n", serverUrl, err)
 	}
+	log.Printf("[agent.go] main() Connected to %s\n", serverUrl)
 	defer conn.Close()
 
 	c := protos.NewAgentCommunicationServiceClient(conn)
-
 	stream, err := c.CreateMessageBus(context.Background())
-
 	if err != nil {
-		log.Fatalf("Error creating stream: %v", err)
+		log.Fatalf("[agent.go] main() Error creating stream: %v\n", err)
+	}
+	log.Printf("[agent.go] main() Created stream...\n")
+
+	log.Printf("[agent.go] main() Trying to connect to %s with agent id %s\n", serverUrl, agentId)
+	msg := &protos.AgentMessage{
+		Message: &protos.AgentMessage_AgentPing{
+			AgentPing: &protos.AgentPing{
+				AgentId: agentId,
+			},
+		},
+	}
+	if err = stream.Send(msg); err != nil {
+		log.Fatalf("[agent.go] main() Failed to connect to the server: %v\n", err)
 	}
+	log.Printf("[agent.go] main() Connected to the server.\n")
 
-	log.Printf("Trying to connect to %s with agent id %s", serverUrl, agentId)
+	// start interceptor
+	ch := make(chan struct{})
+	go startInterceptor(stream, ch)
 
-	if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_AgentPing{AgentPing: &protos.AgentPing{AgentId: agentId}}}); err != nil {
-		log.Fatalf("Failed to connect to the server: %v", err)
-	} else {
-		log.Printf("Connected to the server...")
+	<-ch
+
+	if err := stream.CloseSend(); err != nil {
+		log.Fatalf("[agent.go] main() failed to close the stream: %v\n", err)
 	}
 
-	go func() {
-		log.Printf("Starting jupyter kernel")
-		cmd := exec.Command("micromamba", "run", "-n", "base", "python", "/opt/jupyter/kernel.py")
-		//cmd := exec.Command("jupyter/venv/bin/python", "jupyter/kernel.py")
-		stdout, err := cmd.StdoutPipe()
+}
 
-		if err != nil {
-			fmt.Println("[agent.go] Error creating StdoutPipe:", err)
+func startInterceptor(stream Stream, grpcStreamChannel chan struct{}) {
+
+	envName := "base"
+
+	for {
+		in, err := stream.Recv()
+		if err == io.EOF {
+			close(grpcStreamChannel)
 			return
 		}
-
-		// Get stderr pipe
-		stderr, err := cmd.StderrPipe()
 		if err != nil {
-			fmt.Println("[agent.go] Error creating StderrPipe:", err)
-			return
+			log.Fatalf("[agent.go] Failed to receive a message : %v\n", err)
 		}
-
-		log.Printf("[agent.go] Starting command for execution")
-		// Start the command
-		if err := cmd.Start(); err != nil {
-			fmt.Println("[agent.go] Error starting command:", err)
-			return
+		log.Printf("[agent.go] Received message %s\n", in.Message)
+		switch x := in.GetMessage().(type) {
+
+		case *protos.ServerMessage_EnvSetupRequest:
+			log.Printf("[agent.go] Recived a env setup request\n")
+			executionId := x.EnvSetupRequest.ExecutionId
+			envName = x.EnvSetupRequest.EnvName
+			envLibs := x.EnvSetupRequest.Libraries
+			envPip := x.EnvSetupRequest.Pip
+			go createEnv(stream, executionId, envName, envLibs, envPip)
+
+		case *protos.ServerMessage_PythonExecutionRequest:
+			log.Printf("[agent.go] Recived a python execution request\n")
+			executionId := x.PythonExecutionRequest.ExecutionId
+			envName = x.PythonExecutionRequest.EnvName
+			code := x.PythonExecutionRequest.Code
+			workDir := x.PythonExecutionRequest.WorkingDir
+			go executePython(stream, executionId, envName, workDir, code)
+
+		case *protos.ServerMessage_CommandExecutionRequest:
+			log.Printf("[agent.go] Recived a shell execution request\n")
+			executionId := x.CommandExecutionRequest.ExecutionId
+			execArgs := x.CommandExecutionRequest.Arguments
+			go executeShell(stream, executionId, envName, execArgs)
+
+		case *protos.ServerMessage_JupyterExecutionRequest:
+			log.Printf("[agent.go] Recived a jupyter execution request\n")
+			executionId := x.JupyterExecutionRequest.ExecutionId
+			envName := x.JupyterExecutionRequest.EnvName
+			code := x.JupyterExecutionRequest.Code
+			go executeJupyter(stream, executionId, envName, code)
+
+		case *protos.ServerMessage_TunnelCreationRequest:
+			log.Printf("[agent.go] Received a tunnel creation request\n")
+			executionId := x.TunnelCreationRequest.ExecutionId
+			destHost := x.TunnelCreationRequest.DestinationHost
+			destPort := x.TunnelCreationRequest.DestinationPort
+			srcPort := x.TunnelCreationRequest.SourcePort
+			sshUser := x.TunnelCreationRequest.SshUserName
+			keyPath := x.TunnelCreationRequest.SshKeyPath
+			go openRemoteTunnel(stream, executionId, destHost, destPort, srcPort, sshUser, keyPath)
 		}
+	}
+}
 
-		// Create channels to read from stdout and stderr
-		stdoutScanner := bufio.NewScanner(stdout)
-		stderrScanner := bufio.NewScanner(stderr)
-
-		// Stream stdout
-		go func() {
-			for stdoutScanner.Scan() {
-				fmt.Printf("[agent.go] stdout: %s\n", stdoutScanner.Text())
-			}
-		}()
-
-		// Stream stderr
-		go func() {
-			for stderrScanner.Scan() {
-				fmt.Printf("[agent.go] stderr: %s\n", stderrScanner.Text())
-			}
-		}()
+func createEnv(stream Stream, executionId string, envName string, envLibs []string, envPip []string) {
+	log.Printf("[agent.go] createEnv() Execution id %s\n", executionId)
+	log.Printf("[agent.go] createEnv() Env name %s\n", envName)
+	log.Printf("[agent.go] createEnv() Env libs %s\n", envLibs)
+	log.Printf("[agent.go] createEnv() Env pip %s\n", envPip)
+	// create environment
+	createEnvCmd := exec.Command("micromamba", "create", "-n", envName, "--yes", "--quiet")
+	if err := createEnvCmd.Wait(); err != nil {
+		log.Printf("[agent.go] createEnv() Error creating environment: %v\n", err)
+		return
+	}
+	log.Printf("[agent.go] createEnv() Environment created: %s\n", envName)
+	installDepsCmd := exec.Command("micromamba", "install", "-n", envName, "--yes", "--quiet", strings.Join(envLibs, " "))
+	if err := installDepsCmd.Wait(); err != nil {
+		log.Printf("[agent.go] createEnv() Error waiting for command: %v\n", err)
+		return
+	}
+	installPipCmd := exec.Command("micromamba", "run", "-n", envName, "pip", "install", strings.Join(envLibs, " "))
+	if err := installPipCmd.Wait(); err != nil {
+		log.Printf("[agent.go] createEnv() Error waiting for command: %v\n", err)
+		return
+	}
+	// start python server
+	go startPythonServer(envName)
+	msg := &protos.AgentMessage{
+		Message: &protos.AgentMessage_EnvSetupResponse{
+			EnvSetupResponse: &protos.EnvSetupResponse{
+				ExecutionId: executionId,
+				Status:      "OK",
+			},
+		},
+	}
+	if err := stream.Send(msg); err != nil {
+		log.Printf("[agent.go] executePython() failed to send result to server: %v\n", err)
+	} else {
+		log.Printf("[agent.go] executePython() sent result to server\n")
+	}
+}
 
-		// Wait for the command to finish
-		if err := cmd.Wait(); err != nil {
-			fmt.Println("[agent.go] Error waiting for command:", err)
-			return
+func startPythonServer(envName string) {
+	log.Printf("[agent.go] startPythonServer() Starting python server in env: %s...\n", envName)
+	// Run command
+	cmd := exec.Command("micromamba", "run", "-n", envName, "python", "/opt/jupyter/kernel.py")
+	stdout, err := cmd.StdoutPipe()
+	if err != nil {
+		log.Printf("[agent.go] startPythonServer() Error creating StdoutPipe for cmd: %v\n", err)
+		return
+	}
+	stderr, err := cmd.StderrPipe()
+	if err != nil {
+		log.Printf("[agent.go] startPythonServer() Error creating StderrPipe for cmd: %v\n", err)
+		return
+	}
+	if err := cmd.Start(); err != nil {
+		log.Printf("[agent.go] startPythonServer() Error during start: %v\n", err)
+		return
+	}
+	log.Printf("[agent.go] startPythonServer() Started python server.\n")
+	go func() {
+		stdoutScanner := bufio.NewScanner(stdout)
+		for stdoutScanner.Scan() {
+			log.Printf("[agent.go] startPythonServer() stdout: %s\n", stdoutScanner.Text())
 		}
-
-		fmt.Println("[agent.go] Command finished")
 	}()
-
 	go func() {
-		for {
-			in, err := stream.Recv()
-			if err == io.EOF {
-				close(grpcStreamChannel)
-				return
-			}
-			if err != nil {
-				log.Fatalf("[agent.go] Failed to receive a message : %v", err)
-			}
-			log.Printf("[agent.go] Received message %s", in.Message)
-			switch x := in.GetMessage().(type) {
-			case *protos.ServerMessage_PythonExecutionRequest:
-				log.Printf("[agent.go] Recived a python execution request")
-				executionId := x.PythonExecutionRequest.ExecutionId
-				sessionId := x.PythonExecutionRequest.SessionId
-				code := x.PythonExecutionRequest.Code
-				workingDir := x.PythonExecutionRequest.WorkingDir
-				libraries := x.PythonExecutionRequest.Libraries
-
-				log.Printf("[agent.go] Execution id %s", executionId)
-				log.Printf("[agent.go] Session id %s", sessionId)
-				log.Printf("[agent.go] Code %s", code)
-				log.Printf("[agent.go] Working Dir %s", workingDir)
-				log.Printf("[agent.go] Libraries %s", libraries)
-
-				go func() {
-
-					// setup the venv
-					venvCmd := fmt.Sprintf(`
-					agentId="%s"
-					pkgs="%s"
-
-					if [ ! -f "/tmp/$agentId/venv" ]; then
-						mkdir -p /tmp/$agentId
-						python3 -m venv /tmp/$agentId/venv
-					fi
-
-					source /tmp/$agentId/venv/bin/activate
-					python3 -m pip install $pkgs
-					
-					`, agentId, strings.Join(libraries, " "))
-					log.Println("[agent.go] venv setup:", venvCmd)
-					venvExc := exec.Command("bash", "-c", venvCmd)
-					venvOut, venvErr := venvExc.CombinedOutput()
-					if venvErr != nil {
-						fmt.Println("[agent.go] venv setup: ERR", venvErr)
-						return
-					}
-					venvStdout := string(venvOut)
-					fmt.Println("[agent.go] venv setup:", venvStdout)
-
-					// execute the python code
-					pyCmd := fmt.Sprintf(`
-					workingDir="%s";
-					agentId="%s";
-
-					cd $workingDir;
-					source /tmp/$agentId/venv/bin/activate;
-					python3 <<EOF
-%s
-EOF`, workingDir, agentId, code)
-					log.Println("[agent.go] python code:", pyCmd)
-					pyExc := exec.Command("bash", "-c", pyCmd)
-					pyOut, pyErr := pyExc.CombinedOutput()
-					if pyErr != nil {
-						fmt.Println("[agent.go] python code: ERR", pyErr)
-					}
-
-					// send the result back to the server
-					pyStdout := string(pyOut)
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_PythonExecutionResponse{
-						PythonExecutionResponse: &protos.PythonExecutionResponse{
-							SessionId:      sessionId,
-							ExecutionId:    executionId,
-							ResponseString: pyStdout}}}); err != nil {
-						log.Printf("[agent.go] Failed to send execution result to server: %v", err)
-					} else {
-						log.Printf("[agent.go] Sent execution result to the server: %v", pyStdout)
-					}
-				}()
-
-			case *protos.ServerMessage_CommandExecutionRequest:
-				log.Printf("[agent.go] Recived a command execution request")
-				executionId := x.CommandExecutionRequest.ExecutionId
-				execArgs := x.CommandExecutionRequest.Arguments
-				log.Printf("[agent.go] Execution id %s", executionId)
-				cmd := exec.Command(execArgs[0], execArgs[1:]...)
-				log.Printf("[agent.go] Completed execution with the id %s", executionId)
-				output, err := cmd.CombinedOutput() // combined output of stdout and stderr
-				if err != nil {
-					log.Printf("[agent.go] command execution failed: %s", err)
-				}
-
-				outputString := string(output)
-				log.Printf("[agent.go] Execution output is %s", outputString)
-
-				if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_CommandExecutionResponse{
-					CommandExecutionResponse: &protos.CommandExecutionResponse{ExecutionId: executionId, ResponseString: outputString}}}); err != nil {
-					log.Printf("[agent.go] Failed to send execution result to server: %v", err)
-				}
-
-			case *protos.ServerMessage_JupyterExecutionRequest:
-				log.Printf("[agent.go] Recived a jupyter execution request")
-				executionId := x.JupyterExecutionRequest.ExecutionId
-				sessionId := x.JupyterExecutionRequest.SessionId
-				code := x.JupyterExecutionRequest.Code
-
-				log.Printf("[agent.go] Execution ID: %s, Session ID: %s, Code: %s", executionId, sessionId, code)
-
-				url := "http://127.0.0.1:15000/start"
-				client := &http.Client{}
-				req, err := http.NewRequest("GET", url, nil)
-				if err != nil {
-					log.Printf("[agent.go] Failed to create the request start jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-
-				log.Printf("[agent.go] Sending the jupyter kernel start request to server...")
-				resp, err := client.Do(req)
-				if err != nil {
-					log.Printf("[agent.go] Failed to send the request start jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-				log.Printf("[agent.go] Successfully sent the jupyter kernel start request to server")
-
-				defer func() {
-					err := resp.Body.Close()
-					if err != nil {
-						log.Printf("[agent.go] Failed to close the response body for kernel start: %v", err)
-
-						jupyterResponse := "Failed while running the cell in remote. Please retry"
-						if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-							JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-							log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-						}
-						return
-
-					}
-				}()
-
-				body, err := io.ReadAll(resp.Body)
-				if err != nil {
-					log.Printf("[agent.go] Failed to read response for start jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-
-				log.Printf("[agent.go] Starting to marshal execution request JSON data...")
-				url = "http://127.0.0.1:15000/execute"
-				data := map[string]string{
-					"code":        code,
-					"executionId": executionId,
-				}
-				jsonData, err := json.Marshal(data)
-
-				if err != nil {
-					log.Fatalf("[agent.go] Failed to marshal JSON: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-				log.Printf("[agent.go] Successful marshaling the JSON data")
-
-				req, err = http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
-				if err != nil {
-					log.Printf("[agent.go] Failed to create the request run jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-				req.Header.Set("Content-Type", "application/json")
-
-				client = &http.Client{}
-
-				resp, err = client.Do(req)
-				if err != nil {
-					log.Printf("[agent.go] Failed to send the request run jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-
-				defer func() {
-					log.Printf("[agent.go] Closing the response...")
-					err := resp.Body.Close()
-					if err != nil {
-						log.Printf("[agent.go] Failed to close the response body for kernel execution: %v", err)
-
-						jupyterResponse := "Failed while running the cell in remote. Please retry"
-						if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-							JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-							log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-						}
-						return
-
-					}
-				}()
-
-				log.Printf("[agent.go] Sending the jupyter execution " + executionId + "result to server...")
-				body, err = io.ReadAll(resp.Body)
-				if err != nil {
-					log.Printf("[agent.go] Failed to read response for run jupyter kernel: %v", err)
-
-					jupyterResponse := "Failed while running the cell in remote. Please retry"
-					if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-						JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-						log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-					}
-					return
-
-				}
-
-				jupyterResponse := string(body)
-				log.Println("[agent.go] Jupyter execution " + executionId + "response: " + jupyterResponse)
-
-				if err := stream.Send(&protos.AgentMessage{Message: &protos.AgentMessage_JupyterExecutionResponse{
-					JupyterExecutionResponse: &protos.JupyterExecutionResponse{ExecutionId: executionId, ResponseString: jupyterResponse, SessionId: sessionId}}}); err != nil {
-					log.Printf("[agent.go] Failed to send jupyter execution result to server: %v", err)
-				}
-
-			case *protos.ServerMessage_TunnelCreationRequest:
-				log.Printf("[agent.go] Received a tunnel creation request")
-				host := x.TunnelCreationRequest.DestinationHost
-				destPort := x.TunnelCreationRequest.DestinationPort
-				srcPort := x.TunnelCreationRequest.SourcePort
-				keyPath := x.TunnelCreationRequest.SshKeyPath
-				sshUser := x.TunnelCreationRequest.SshUserName
-				log.Printf("[agent.go] Tunnel details - Host: %s, DestPort: %s, SrcPort: %s, KeyPath: %s, SSH User: %s", host, destPort, srcPort, keyPath, sshUser)
-				openRemoteTunnel(host, destPort, srcPort, sshUser, keyPath)
-			}
-
+		stderrScanner := bufio.NewScanner(stderr)
+		for stderrScanner.Scan() {
+			log.Printf("[agent.go] startPythonServer() stderr: %s\n", stderrScanner.Text())
 		}
 	}()
-
-	<-grpcStreamChannel
-	<-kernelChannel
-
-	if err := stream.CloseSend(); err != nil {
-		log.Fatalf("failed to close the stream: %v", err)
+	if err := cmd.Wait(); err != nil {
+		log.Printf("[agent.go] startPythonServer() Error waiting for command: %v\n", err)
+		return
 	}
+	log.Printf("[agent.go] startPythonServer() Command finished.\n")
+}
 
+func executePython(stream Stream, executionId string, envName string, workingDir string, code string) {
+	log.Printf("[agent.go] executePython() Execution id %s\n", executionId)
+	log.Printf("[agent.go] executePython() Env name %s\n", envName)
+	log.Printf("[agent.go] executePython() Working Dir %s\n", workingDir)
+	log.Printf("[agent.go] executePython() Code %s\n", code)
+	// Run command
+	pythonCmd := exec.Command("micromamba", "run", "-n", envName, "python", "-c", code)
+	output, err := pythonCmd.CombinedOutput()
+	var responseString string
+	if err != nil {
+		responseString = fmt.Sprintf("Error: %v", err)
+		log.Printf("[agent.go] executePython() error: %v\n", err)
+	} else {
+		responseString = string(output)
+		log.Printf("[agent.go] executePython() completed: %s\n", responseString)
+	}
+	msg := &protos.AgentMessage{
+		Message: &protos.AgentMessage_PythonExecutionResponse{
+			PythonExecutionResponse: &protos.PythonExecutionResponse{
+				ExecutionId:    executionId,
+				ResponseString: responseString,
+			},
+		},
+	}
+	if err := stream.Send(msg); err != nil {
+		log.Printf("[agent.go] executePython() failed to send result to server: %v\n", err)
+	} else {
+		log.Printf("[agent.go] executePython() Sent result to server: %s\n", output)
+	}
 }
 
-func openRemoteTunnel(remoteHost string, remotePort string, localPort string, sshUser string, sshKeyFile string) {
-	log.Printf("Opening remote SSH tunnel - Remote Host: %s, Remote Port: %s, Local Port: %s", remoteHost, remotePort, localPort)
-	// SSH server details
-	sshHost := remoteHost + ":22"
-	//sshPassword := "your_ssh_password"
+func executeShell(stream Stream, executionId string, envName string, execArgs []string) {
+	log.Printf("[agent.go] executeShell() Execution id %s\n", executionId)
+	log.Printf("[agent.go] executeShell() Env name %s\n", envName)
+	log.Printf("[agent.go] executeShell() Exec args %s\n", execArgs)
+	// Run command
+	cmd := exec.Command("micromamba", "run", "-n", envName, strings.Join(execArgs, " "))
+	output, err := cmd.CombinedOutput()
+	var responseString string
+	if err != nil {
+		responseString = fmt.Sprintf("Error: %v", err)
+		log.Printf("[agent.go] executeShell() %s failed: %v\n", executionId, err)
+	} else {
+		responseString = string(output)
+		log.Printf("[agent.go] executeShell() %s done: %s\n", executionId, responseString)
+	}
+	msg := &protos.AgentMessage{
+		Message: &protos.AgentMessage_CommandExecutionResponse{
+			CommandExecutionResponse: &protos.CommandExecutionResponse{
+				ExecutionId:    executionId,
+				ResponseString: responseString,
+			},
+		},
+	}
+	if err := stream.Send(msg); err != nil {
+		log.Printf("[agent.go] executeShell() Failed to send execution result to server: %v\n", err)
+	} else {
+		log.Printf("[agent.go] executeShell() Sent execution result to server: %s\n", output)
+	}
+}
 
-	// Remote and local ports
-	localHost := "localhost"
+func executeJupyter(stream Stream, executionId string, envName string, code string) {
+	log.Printf("[agent.go] executeJupyter() Execution ID: %s, Env: %s, Code: %s\n", executionId, envName, code)
+	unixSock := os.Getenv("KERNEL_SOCK")
+	client := &http.Client{
+		Transport: &http.Transport{
+			DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
+				return net.Dial("unix", unixSock)
+			},
+		},
+	}
+	sendResponse := func(response string, err error) {
+		if err != nil {
+			log.Printf("[agent.go] executeJupyter() Error: %v\n", err)
+			response = "Failed while running the cell in remote. Please retry"
+		}
+		msg := &protos.AgentMessage{
+			Message: &protos.AgentMessage_JupyterExecutionResponse{
+				JupyterExecutionResponse: &protos.JupyterExecutionResponse{
+					ExecutionId:    executionId,
+					ResponseString: response,
+				},
+			},
+		}
+		if streamErr := stream.Send(msg); streamErr != nil {
+			log.Printf("[agent.go] executeJupyter() Failed to send jupyter execution result to server: %v\n", streamErr)
+		}
+	}
+	// Start kernel
+	startUrl := &url.URL{Scheme: "http", Host: "localhost", Path: "/start"}
+	req, err := http.NewRequest("GET", startUrl.String(), nil)
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to create start kernel request: %w", err))
+		return
+	}
+	resp, err := client.Do(req)
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to send start kernel request: %w", err))
+		return
+	}
+	defer resp.Body.Close()
+	if _, err := io.ReadAll(resp.Body); err != nil {
+		sendResponse("", fmt.Errorf("failed to read start kernel response: %w", err))
+		return
+	}
+	log.Printf("[agent.go] executeJupyter() Successfully started the jupyter kernel\n")
+	// Execute code on kernel
+	executeUrl := &url.URL{Scheme: "http", Host: "localhost", Path: "/execute"}
+	data := map[string]string{"code": code, "executionId": executionId}
+	jsonData, err := json.Marshal(data)
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to marshal JSON: %w", err))
+		return
+	}
+	req, err = http.NewRequest("POST", executeUrl.String(), bytes.NewBuffer(jsonData))
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to create execute code request: %w", err))
+		return
+	}
+	req.Header.Set("Content-Type", "application/json")
+	resp, err = client.Do(req)
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to send execute code request: %w", err))
+		return
+	}
+	defer resp.Body.Close()
+	bodyBytes, err := io.ReadAll(resp.Body)
+	if err != nil {
+		sendResponse("", fmt.Errorf("failed to read execute code response: %w", err))
+		return
+	}
+	jupyterResponse := string(bodyBytes)
+	log.Printf("[agent.go] executeJupyter() id: %s response: %s\n", executionId, jupyterResponse)
+	sendResponse(jupyterResponse, nil)
+}
 
+func openRemoteTunnel(stream Stream, executionId string, destHost string, destPort string, localPort string, sshUser string, sshKeyFile string) {
+	log.Printf("[agent.go] openRemoteTunnel() rhost: %s, rport: %s, lport: %s, user: %s, keyfile: %s\n", destHost, destPort, localPort, sshUser, sshKeyFile)
 	key, err := os.ReadFile(sshKeyFile)
 	if err != nil {
-		log.Fatalf("unable to read private key: %v", err)
+		log.Printf("[agent.go] openRemoteTunnel() unable to read private key: %v\n", err)
+		return
 	}
-
-	// Create the Signer for this private key.
 	signer, err := ssh.ParsePrivateKey(key)
 	if err != nil {
-		log.Fatalf("unable to parse private key: %v", err)
+		log.Printf("[agent.go] openRemoteTunnel() unable to parse private key: %v\n", err)
+		return
 	}
-
-	// Create SSH client configuration
 	sshConfig := &ssh.ClientConfig{
-		User: sshUser,
-		Auth: []ssh.AuthMethod{
-			//ssh.Password(sshPassword),
-			ssh.PublicKeys(signer),
-		},
-		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // Replace with proper host key verification for production
+		User:            sshUser,
+		Auth:            []ssh.AuthMethod{ssh.PublicKeys(signer)},
+		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 	}
-
-	log.Println("Connecting to SSH server...")
-	// Connect to the SSH server
-	sshConn, err := ssh.Dial("tcp", sshHost, sshConfig)
+	sshConn, err := ssh.Dial("tcp", net.JoinHostPort(destHost, "22"), sshConfig)
 	if err != nil {
-		log.Fatalf("Failed to dial SSH: %s", err)
+		log.Printf("[agent.go] openRemoteTunnel() failed to dial SSH: %v\n", err)
+		return
 	}
 	defer sshConn.Close()
-	log.Println("SSH connection established.")
-
-	// Listen on the remote port
-	remoteListener, err := sshConn.Listen("tcp", fmt.Sprintf("0.0.0.0:%s", remotePort))
+	log.Printf("[agent.go] openRemoteTunnel() SSH connection established.\n")
+	remoteListener, err := sshConn.Listen("tcp", fmt.Sprintf("0.0.0.0:%s", destPort))
 	if err != nil {
-		log.Fatalf("Failed to listen on remote port %s: %s", remotePort, err)
+		log.Printf("[agent.go] openRemoteTunnel() failed to listen on remote port %s: %s\n", destPort, err)
+		return
 	}
 	defer remoteListener.Close()
-
-	log.Printf("Reverse SSH tunnel established. Listening on remote port %s", remotePort)
-
+	log.Printf("[agent.go] openRemoteTunnel() reverse SSH tunnel established. Listening on remote port: %s\n", destPort)
+	msg := &protos.AgentMessage{
+		Message: &protos.AgentMessage_TunnelCreationResponse{
+			TunnelCreationResponse: &protos.TunnelCreationResponse{
+				ExecutionId: executionId,
+				Status:      "OK",
+			},
+		},
+	}
+	if streamErr := stream.Send(msg); streamErr != nil {
+		log.Printf("[agent.go] openRemoteTunnel() failed to inform the server: %v\n", streamErr)
+	}
 	for {
 		remoteConn, err := remoteListener.Accept()
 		if err != nil {
-			log.Printf("Failed to accept remote connection: %s", err)
+			log.Printf("[agent.go] openRemoteTunnel() failed to accept remote connection: %v\n", err)
 			continue
 		}
-
-		go handleConnection(remoteConn, localHost, localPort)
+		go handleConnection(remoteConn, "localhost", localPort)
 	}
 }
 
 func handleConnection(remoteConn net.Conn, localHost, localPort string) {
-	log.Printf("Handling connection to local host %s:%s", localHost, localPort)
+	log.Printf("[agent.go] handleConnection() Handling connection to local host %s:%s\n", localHost, localPort)
 	defer remoteConn.Close()
-
-	// Connect to the local host
 	localConn, err := net.Dial("tcp", net.JoinHostPort(localHost, localPort))
 	if err != nil {
-		log.Printf("Failed to connect to local host %s:%s: %s", localHost, localPort, err)
+		log.Printf("[agent.go] handleConnection() failed to connect to local host %s:%s! %v\n", localHost, localPort, err)
 		return
 	}
 	defer localConn.Close()
-
-	// Create channels to signal when copying is done
-	done := make(chan struct{})
-
-	log.Println("Starting data transfer between remote and local connections...")
-	// Start copying data between remote and local connections
+	done := make(chan struct{}, 2) // Buffered channel to prevent goroutine leaks
+	log.Printf("[agent.go] handleConnection() starting data transfer between remote and local connections...\n")
 	go copyConn(remoteConn, localConn, done)
 	go copyConn(localConn, remoteConn, done)
-
-	// Wait for both copy operations to complete
+	<-done // Wait for both copy operations to complete
 	<-done
-	<-done
-	log.Println("Data transfer completed.")
+	log.Printf("[agent.go] handleConnection() Data transfer completed.\n")
 }
 
 func copyConn(writer, reader net.Conn, done chan struct{}) {
-	defer func() {
-		// Signal that copying is done
-		done <- struct{}{}
-	}()
-
-	_, err := io.Copy(writer, reader)
-	if err != nil {
-		if err != io.EOF {
-			log.Printf("Data copy error: %s", err)
-		}
+	defer func() { done <- struct{}{} }()
+	if _, err := io.Copy(writer, reader); err != nil && err != io.EOF {
+		log.Printf("[agent.go] copyConn() Data copy error: %v\n", err)
 	}
 }
diff --git a/modules/agent-framework/airavata-agent/kernel.py b/modules/agent-framework/airavata-agent/kernel.py
index c9bd281479..ef4f143197 100644
--- a/modules/agent-framework/airavata-agent/kernel.py
+++ b/modules/agent-framework/airavata-agent/kernel.py
@@ -134,7 +134,7 @@ def stop():
 
     if not kernel_running:
         return "Kernel is not running to shut down"
-    
+
     kc.stop_channels()
     km.shutdown_kernel()
     kernel_running = False
@@ -142,4 +142,6 @@ def stop():
 
 
 if __name__ == '__main__':
-    app.run(port=15000)
+    unix_socket = os.getenv("KERNEL_SOCK")
+    assert unix_socket is not None
+    app.run(host=f"unix://{unix_socket}")
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 ba08688ed9..f602f05030 100644
--- a/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
+++ b/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.34.2
-// 	protoc        v4.24.4
+// 	protoc        v5.29.3
 // source: agent-communication.proto
 
 package protos
@@ -20,6 +20,7 @@ const (
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
+// agent pinging the server
 type AgentPing struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -67,17 +68,17 @@ func (x *AgentPing) GetAgentId() string {
 	return ""
 }
 
-type CommandExecutionResponse struct {
+// server requesting the agent to shutdown
+type ShutdownRequest struct {
 	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"`
+	AgentId string `protobuf:"bytes,1,opt,name=agentId,proto3" json:"agentId,omitempty"`
 }
 
-func (x *CommandExecutionResponse) Reset() {
-	*x = CommandExecutionResponse{}
+func (x *ShutdownRequest) Reset() {
+	*x = ShutdownRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[1]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -85,13 +86,13 @@ func (x *CommandExecutionResponse) Reset() {
 	}
 }
 
-func (x *CommandExecutionResponse) String() string {
+func (x *ShutdownRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*CommandExecutionResponse) ProtoMessage() {}
+func (*ShutdownRequest) ProtoMessage() {}
 
-func (x *CommandExecutionResponse) ProtoReflect() protoreflect.Message {
+func (x *ShutdownRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[1]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -103,36 +104,33 @@ func (x *CommandExecutionResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use CommandExecutionResponse.ProtoReflect.Descriptor instead.
-func (*CommandExecutionResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead.
+func (*ShutdownRequest) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{1}
 }
 
-func (x *CommandExecutionResponse) GetExecutionId() string {
-	if x != nil {
-		return x.ExecutionId
-	}
-	return ""
-}
-
-func (x *CommandExecutionResponse) GetResponseString() string {
+func (x *ShutdownRequest) GetAgentId() string {
 	if x != nil {
-		return x.ResponseString
+		return x.AgentId
 	}
 	return ""
 }
 
-type ContainerExecutionResponse struct {
+// server requesting the agent to create a new agent subprocess
+type CreateAgentRequest struct {
 	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"`
+	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 *ContainerExecutionResponse) Reset() {
-	*x = ContainerExecutionResponse{}
+func (x *CreateAgentRequest) Reset() {
+	*x = CreateAgentRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[2]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -140,13 +138,13 @@ func (x *ContainerExecutionResponse) Reset() {
 	}
 }
 
-func (x *ContainerExecutionResponse) String() string {
+func (x *CreateAgentRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*ContainerExecutionResponse) ProtoMessage() {}
+func (*CreateAgentRequest) ProtoMessage() {}
 
-func (x *ContainerExecutionResponse) ProtoReflect() protoreflect.Message {
+func (x *CreateAgentRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[2]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -158,37 +156,58 @@ func (x *ContainerExecutionResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use ContainerExecutionResponse.ProtoReflect.Descriptor instead.
-func (*ContainerExecutionResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use CreateAgentRequest.ProtoReflect.Descriptor instead.
+func (*CreateAgentRequest) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{2}
 }
 
-func (x *ContainerExecutionResponse) GetExecutionId() string {
+func (x *CreateAgentRequest) GetExecutionId() string {
 	if x != nil {
 		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *ContainerExecutionResponse) GetResponseString() string {
+func (x *CreateAgentRequest) GetAgentId() string {
 	if x != nil {
-		return x.ResponseString
+		return x.AgentId
 	}
 	return ""
 }
 
-type JupyterExecutionResponse struct {
+func (x *CreateAgentRequest) GetContainerId() string {
+	if x != nil {
+		return x.ContainerId
+	}
+	return ""
+}
+
+func (x *CreateAgentRequest) GetWorkingDir() string {
+	if x != nil {
+		return x.WorkingDir
+	}
+	return ""
+}
+
+func (x *CreateAgentRequest) GetMounts() []string {
+	if x != nil {
+		return x.Mounts
+	}
+	return nil
+}
+
+type CreateAgentResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	ExecutionId    string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	SessionId      string `protobuf:"bytes,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
-	ResponseString string `protobuf:"bytes,3,opt,name=responseString,proto3" json:"responseString,omitempty"`
+	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 *JupyterExecutionResponse) Reset() {
-	*x = JupyterExecutionResponse{}
+func (x *CreateAgentResponse) Reset() {
+	*x = CreateAgentResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[3]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -196,13 +215,13 @@ func (x *JupyterExecutionResponse) Reset() {
 	}
 }
 
-func (x *JupyterExecutionResponse) String() string {
+func (x *CreateAgentResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*JupyterExecutionResponse) ProtoMessage() {}
+func (*CreateAgentResponse) ProtoMessage() {}
 
-func (x *JupyterExecutionResponse) ProtoReflect() protoreflect.Message {
+func (x *CreateAgentResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[3]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -214,44 +233,44 @@ func (x *JupyterExecutionResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use JupyterExecutionResponse.ProtoReflect.Descriptor instead.
-func (*JupyterExecutionResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use CreateAgentResponse.ProtoReflect.Descriptor instead.
+func (*CreateAgentResponse) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{3}
 }
 
-func (x *JupyterExecutionResponse) GetExecutionId() string {
+func (x *CreateAgentResponse) GetExecutionId() string {
 	if x != nil {
 		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *JupyterExecutionResponse) GetSessionId() string {
+func (x *CreateAgentResponse) GetAgentId() string {
 	if x != nil {
-		return x.SessionId
+		return x.AgentId
 	}
 	return ""
 }
 
-func (x *JupyterExecutionResponse) GetResponseString() string {
+func (x *CreateAgentResponse) GetStatus() string {
 	if x != nil {
-		return x.ResponseString
+		return x.Status
 	}
 	return ""
 }
 
-type PythonExecutionResponse struct {
+// server requesting the agent to terminate an agent subprocess
+type TerminateAgentRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	ExecutionId    string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	SessionId      string `protobuf:"bytes,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
-	ResponseString string `protobuf:"bytes,3,opt,name=responseString,proto3" json:"responseString,omitempty"`
+	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 *PythonExecutionResponse) Reset() {
-	*x = PythonExecutionResponse{}
+func (x *TerminateAgentRequest) Reset() {
+	*x = TerminateAgentRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[4]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -259,13 +278,13 @@ func (x *PythonExecutionResponse) Reset() {
 	}
 }
 
-func (x *PythonExecutionResponse) String() string {
+func (x *TerminateAgentRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*PythonExecutionResponse) ProtoMessage() {}
+func (*TerminateAgentRequest) ProtoMessage() {}
 
-func (x *PythonExecutionResponse) ProtoReflect() protoreflect.Message {
+func (x *TerminateAgentRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[4]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -277,43 +296,37 @@ func (x *PythonExecutionResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use PythonExecutionResponse.ProtoReflect.Descriptor instead.
-func (*PythonExecutionResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use TerminateAgentRequest.ProtoReflect.Descriptor instead.
+func (*TerminateAgentRequest) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{4}
 }
 
-func (x *PythonExecutionResponse) GetExecutionId() string {
+func (x *TerminateAgentRequest) GetExecutionId() string {
 	if x != nil {
 		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *PythonExecutionResponse) GetSessionId() string {
-	if x != nil {
-		return x.SessionId
-	}
-	return ""
-}
-
-func (x *PythonExecutionResponse) GetResponseString() string {
+func (x *TerminateAgentRequest) GetAgentId() string {
 	if x != nil {
-		return x.ResponseString
+		return x.AgentId
 	}
 	return ""
 }
 
-type TerminateExecutionResponse struct {
+type TerminateAgentResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Status      string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
-	Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
+	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 *TerminateExecutionResponse) Reset() {
-	*x = TerminateExecutionResponse{}
+func (x *TerminateAgentResponse) Reset() {
+	*x = TerminateAgentResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -321,13 +334,13 @@ func (x *TerminateExecutionResponse) Reset() {
 	}
 }
 
-func (x *TerminateExecutionResponse) String() string {
+func (x *TerminateAgentResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TerminateExecutionResponse) ProtoMessage() {}
+func (*TerminateAgentResponse) ProtoMessage() {}
 
-func (x *TerminateExecutionResponse) ProtoReflect() protoreflect.Message {
+func (x *TerminateAgentResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -339,35 +352,46 @@ func (x *TerminateExecutionResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TerminateExecutionResponse.ProtoReflect.Descriptor instead.
-func (*TerminateExecutionResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use TerminateAgentResponse.ProtoReflect.Descriptor instead.
+func (*TerminateAgentResponse) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{5}
 }
 
-func (x *TerminateExecutionResponse) GetStatus() string {
+func (x *TerminateAgentResponse) GetExecutionId() string {
 	if x != nil {
-		return x.Status
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *TerminateAgentResponse) GetAgentId() string {
+	if x != nil {
+		return x.AgentId
 	}
 	return ""
 }
 
-func (x *TerminateExecutionResponse) GetDescription() string {
+func (x *TerminateAgentResponse) GetStatus() string {
 	if x != nil {
-		return x.Description
+		return x.Status
 	}
 	return ""
 }
 
-type TunnelCreationResponse struct {
+// server requesting the agent to setup an environment
+type EnvSetupRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+	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 *TunnelCreationResponse) Reset() {
-	*x = TunnelCreationResponse{}
+func (x *EnvSetupRequest) Reset() {
+	*x = EnvSetupRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -375,13 +399,13 @@ func (x *TunnelCreationResponse) Reset() {
 	}
 }
 
-func (x *TunnelCreationResponse) String() string {
+func (x *EnvSetupRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TunnelCreationResponse) ProtoMessage() {}
+func (*EnvSetupRequest) ProtoMessage() {}
 
-func (x *TunnelCreationResponse) ProtoReflect() protoreflect.Message {
+func (x *EnvSetupRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -393,28 +417,50 @@ func (x *TunnelCreationResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TunnelCreationResponse.ProtoReflect.Descriptor instead.
-func (*TunnelCreationResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use EnvSetupRequest.ProtoReflect.Descriptor instead.
+func (*EnvSetupRequest) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{6}
 }
 
-func (x *TunnelCreationResponse) GetStatus() string {
+func (x *EnvSetupRequest) GetExecutionId() string {
 	if x != nil {
-		return x.Status
+		return x.ExecutionId
 	}
 	return ""
 }
 
-type TunnelTerminationResponse struct {
+func (x *EnvSetupRequest) GetEnvName() string {
+	if x != nil {
+		return x.EnvName
+	}
+	return ""
+}
+
+func (x *EnvSetupRequest) GetLibraries() []string {
+	if x != nil {
+		return x.Libraries
+	}
+	return nil
+}
+
+func (x *EnvSetupRequest) GetPip() []string {
+	if x != nil {
+		return x.Pip
+	}
+	return nil
+}
+
+type EnvSetupResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+	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() {
-	*x = TunnelTerminationResponse{}
+func (x *EnvSetupResponse) Reset() {
+	*x = EnvSetupResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[7]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -422,13 +468,13 @@ func (x *TunnelTerminationResponse) Reset() {
 	}
 }
 
-func (x *TunnelTerminationResponse) String() string {
+func (x *EnvSetupResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TunnelTerminationResponse) ProtoMessage() {}
+func (*EnvSetupResponse) ProtoMessage() {}
 
-func (x *TunnelTerminationResponse) ProtoReflect() protoreflect.Message {
+func (x *EnvSetupResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[7]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -440,36 +486,39 @@ func (x *TunnelTerminationResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TunnelTerminationResponse.ProtoReflect.Descriptor instead.
-func (*TunnelTerminationResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use EnvSetupResponse.ProtoReflect.Descriptor instead.
+func (*EnvSetupResponse) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{7}
 }
 
-func (x *TunnelTerminationResponse) GetStatus() string {
+func (x *EnvSetupResponse) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *EnvSetupResponse) GetStatus() string {
 	if x != nil {
 		return x.Status
 	}
 	return ""
 }
 
-type AgentMessage struct {
+// server requesting the agent to execute a shell command in the environment
+type CommandExecutionRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	// Types that are assignable to Message:
-	//
-	//	*AgentMessage_AgentPing
-	//	*AgentMessage_CommandExecutionResponse
-	//	*AgentMessage_ContainerExecutionResponse
-	//	*AgentMessage_TerminateExecutionResponse
-	//	*AgentMessage_JupyterExecutionResponse
-	//	*AgentMessage_PythonExecutionResponse
-	Message isAgentMessage_Message `protobuf_oneof:"message"`
+	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 *AgentMessage) Reset() {
-	*x = AgentMessage{}
+func (x *CommandExecutionRequest) Reset() {
+	*x = CommandExecutionRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[8]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -477,13 +526,13 @@ func (x *AgentMessage) Reset() {
 	}
 }
 
-func (x *AgentMessage) String() string {
+func (x *CommandExecutionRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*AgentMessage) ProtoMessage() {}
+func (*CommandExecutionRequest) ProtoMessage() {}
 
-func (x *AgentMessage) ProtoReflect() protoreflect.Message {
+func (x *CommandExecutionRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[8]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -495,113 +544,50 @@ func (x *AgentMessage) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use AgentMessage.ProtoReflect.Descriptor instead.
-func (*AgentMessage) Descriptor() ([]byte, []int) {
+// Deprecated: Use CommandExecutionRequest.ProtoReflect.Descriptor instead.
+func (*CommandExecutionRequest) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{8}
 }
 
-func (m *AgentMessage) GetMessage() isAgentMessage_Message {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (x *AgentMessage) GetAgentPing() *AgentPing {
-	if x, ok := x.GetMessage().(*AgentMessage_AgentPing); ok {
-		return x.AgentPing
-	}
-	return nil
-}
-
-func (x *AgentMessage) GetCommandExecutionResponse() *CommandExecutionResponse {
-	if x, ok := x.GetMessage().(*AgentMessage_CommandExecutionResponse); ok {
-		return x.CommandExecutionResponse
-	}
-	return nil
-}
-
-func (x *AgentMessage) GetContainerExecutionResponse() *ContainerExecutionResponse {
-	if x, ok := x.GetMessage().(*AgentMessage_ContainerExecutionResponse); ok {
-		return x.ContainerExecutionResponse
+func (x *CommandExecutionRequest) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
 	}
-	return nil
+	return ""
 }
 
-func (x *AgentMessage) GetTerminateExecutionResponse() *TerminateExecutionResponse {
-	if x, ok := x.GetMessage().(*AgentMessage_TerminateExecutionResponse); ok {
-		return x.TerminateExecutionResponse
+func (x *CommandExecutionRequest) GetEnvName() string {
+	if x != nil {
+		return x.EnvName
 	}
-	return nil
+	return ""
 }
 
-func (x *AgentMessage) GetJupyterExecutionResponse() *JupyterExecutionResponse {
-	if x, ok := x.GetMessage().(*AgentMessage_JupyterExecutionResponse); ok {
-		return x.JupyterExecutionResponse
+func (x *CommandExecutionRequest) GetWorkingDir() string {
+	if x != nil {
+		return x.WorkingDir
 	}
-	return nil
+	return ""
 }
 
-func (x *AgentMessage) GetPythonExecutionResponse() *PythonExecutionResponse {
-	if x, ok := x.GetMessage().(*AgentMessage_PythonExecutionResponse); ok {
-		return x.PythonExecutionResponse
+func (x *CommandExecutionRequest) GetArguments() []string {
+	if x != nil {
+		return x.Arguments
 	}
 	return nil
 }
 
-type isAgentMessage_Message interface {
-	isAgentMessage_Message()
-}
-
-type AgentMessage_AgentPing struct {
-	AgentPing *AgentPing `protobuf:"bytes,1,opt,name=agentPing,proto3,oneof"`
-}
-
-type AgentMessage_CommandExecutionResponse struct {
-	CommandExecutionResponse *CommandExecutionResponse `protobuf:"bytes,2,opt,name=commandExecutionResponse,proto3,oneof"`
-}
-
-type AgentMessage_ContainerExecutionResponse struct {
-	ContainerExecutionResponse *ContainerExecutionResponse `protobuf:"bytes,3,opt,name=containerExecutionResponse,proto3,oneof"`
-}
-
-type AgentMessage_TerminateExecutionResponse struct {
-	TerminateExecutionResponse *TerminateExecutionResponse `protobuf:"bytes,4,opt,name=terminateExecutionResponse,proto3,oneof"`
-}
-
-type AgentMessage_JupyterExecutionResponse struct {
-	JupyterExecutionResponse *JupyterExecutionResponse `protobuf:"bytes,5,opt,name=jupyterExecutionResponse,proto3,oneof"`
-}
-
-type AgentMessage_PythonExecutionResponse struct {
-	PythonExecutionResponse *PythonExecutionResponse `protobuf:"bytes,6,opt,name=pythonExecutionResponse,proto3,oneof"`
-}
-
-func (*AgentMessage_AgentPing) isAgentMessage_Message() {}
-
-func (*AgentMessage_CommandExecutionResponse) isAgentMessage_Message() {}
-
-func (*AgentMessage_ContainerExecutionResponse) isAgentMessage_Message() {}
-
-func (*AgentMessage_TerminateExecutionResponse) isAgentMessage_Message() {}
-
-func (*AgentMessage_JupyterExecutionResponse) isAgentMessage_Message() {}
-
-func (*AgentMessage_PythonExecutionResponse) isAgentMessage_Message() {}
-
-type ContainerExecutionRequest struct {
+type CommandExecutionResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	ExecutionId   string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	ContainerName string   `protobuf:"bytes,2,opt,name=containerName,proto3" json:"containerName,omitempty"`
-	Arguments     []string `protobuf:"bytes,3,rep,name=arguments,proto3" json:"arguments,omitempty"`
-	MountPath     string   `protobuf:"bytes,4,opt,name=mountPath,proto3" json:"mountPath,omitempty"`
+	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 *ContainerExecutionRequest) Reset() {
-	*x = ContainerExecutionRequest{}
+func (x *CommandExecutionResponse) Reset() {
+	*x = CommandExecutionResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_agent_communication_proto_msgTypes[9]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -609,13 +595,13 @@ func (x *ContainerExecutionRequest) Reset() {
 	}
 }
 
-func (x *ContainerExecutionRequest) String() string {
+func (x *CommandExecutionResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*ContainerExecutionRequest) ProtoMessage() {}
+func (*CommandExecutionResponse) ProtoMessage() {}
 
-func (x *ContainerExecutionRequest) ProtoReflect() protoreflect.Message {
+func (x *CommandExecutionResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_agent_communication_proto_msgTypes[9]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -627,56 +613,290 @@ func (x *ContainerExecutionRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use ContainerExecutionRequest.ProtoReflect.Descriptor instead.
-func (*ContainerExecutionRequest) Descriptor() ([]byte, []int) {
+// Deprecated: Use CommandExecutionResponse.ProtoReflect.Descriptor instead.
+func (*CommandExecutionResponse) Descriptor() ([]byte, []int) {
 	return file_agent_communication_proto_rawDescGZIP(), []int{9}
 }
 
-func (x *ContainerExecutionRequest) GetExecutionId() string {
+func (x *CommandExecutionResponse) GetExecutionId() string {
 	if x != nil {
 		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *ContainerExecutionRequest) GetContainerName() string {
-	if x != nil {
-		return x.ContainerName
-	}
-	return ""
-}
-
-func (x *ContainerExecutionRequest) GetArguments() []string {
-	if x != nil {
-		return x.Arguments
-	}
-	return nil
-}
-
-func (x *ContainerExecutionRequest) GetMountPath() string {
+func (x *CommandExecutionResponse) GetResponseString() string {
 	if x != nil {
-		return x.MountPath
+		return x.ResponseString
 	}
 	return ""
 }
 
-type TunnelCreationRequest struct {
+// server requesting the agent to execute a python script in the environment
+type PythonExecutionRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	DestinationHost string `protobuf:"bytes,1,opt,name=destinationHost,proto3" json:"destinationHost,omitempty"`
-	DestinationPort string `protobuf:"bytes,2,opt,name=destinationPort,proto3" json:"destinationPort,omitempty"`
-	SshUserName     string `protobuf:"bytes,3,opt,name=sshUserName,proto3" json:"sshUserName,omitempty"`
-	SourcePort      string `protobuf:"bytes,4,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
-	SshKeyPath      string `protobuf:"bytes,5,opt,name=sshKeyPath,proto3" json:"sshKeyPath,omitempty"`
-	Password        string `protobuf:"bytes,6,opt,name=password,proto3" json:"password,omitempty"`
+	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() {
+	*x = PythonExecutionRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_agent_communication_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *PythonExecutionRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PythonExecutionRequest) ProtoMessage() {}
+
+func (x *PythonExecutionRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use PythonExecutionRequest.ProtoReflect.Descriptor instead.
+func (*PythonExecutionRequest) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *PythonExecutionRequest) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *PythonExecutionRequest) GetEnvName() string {
+	if x != nil {
+		return x.EnvName
+	}
+	return ""
+}
+
+func (x *PythonExecutionRequest) GetWorkingDir() string {
+	if x != nil {
+		return x.WorkingDir
+	}
+	return ""
+}
+
+func (x *PythonExecutionRequest) GetCode() string {
+	if x != nil {
+		return x.Code
+	}
+	return ""
+}
+
+type PythonExecutionResponse struct {
+	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() {
+	*x = PythonExecutionResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_agent_communication_proto_msgTypes[11]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *PythonExecutionResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PythonExecutionResponse) ProtoMessage() {}
+
+func (x *PythonExecutionResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[11]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use PythonExecutionResponse.ProtoReflect.Descriptor instead.
+func (*PythonExecutionResponse) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *PythonExecutionResponse) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *PythonExecutionResponse) GetResponseString() string {
+	if x != nil {
+		return x.ResponseString
+	}
+	return ""
+}
+
+// server requesting the agent to execute a jupyter notebook cell in the environment
+type JupyterExecutionRequest struct {
+	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() {
+	*x = JupyterExecutionRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_agent_communication_proto_msgTypes[12]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *JupyterExecutionRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*JupyterExecutionRequest) ProtoMessage() {}
+
+func (x *JupyterExecutionRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[12]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use JupyterExecutionRequest.ProtoReflect.Descriptor instead.
+func (*JupyterExecutionRequest) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *JupyterExecutionRequest) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *JupyterExecutionRequest) GetEnvName() string {
+	if x != nil {
+		return x.EnvName
+	}
+	return ""
+}
+
+func (x *JupyterExecutionRequest) GetCode() string {
+	if x != nil {
+		return x.Code
+	}
+	return ""
+}
+
+type JupyterExecutionResponse struct {
+	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() {
+	*x = JupyterExecutionResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_agent_communication_proto_msgTypes[13]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *JupyterExecutionResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*JupyterExecutionResponse) ProtoMessage() {}
+
+func (x *JupyterExecutionResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[13]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use JupyterExecutionResponse.ProtoReflect.Descriptor instead.
+func (*JupyterExecutionResponse) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *JupyterExecutionResponse) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
+}
+
+func (x *JupyterExecutionResponse) GetResponseString() string {
+	if x != nil {
+		return x.ResponseString
+	}
+	return ""
+}
+
+// server requesting the agent to create a ssh tunnel
+type TunnelCreationRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ExecutionId     string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	DestinationHost string `protobuf:"bytes,2,opt,name=destinationHost,proto3" json:"destinationHost,omitempty"`
+	DestinationPort string `protobuf:"bytes,3,opt,name=destinationPort,proto3" json:"destinationPort,omitempty"`
+	SshUserName     string `protobuf:"bytes,4,opt,name=sshUserName,proto3" json:"sshUserName,omitempty"`
+	SourcePort      string `protobuf:"bytes,5,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
+	SshKeyPath      string `protobuf:"bytes,6,opt,name=sshKeyPath,proto3" json:"sshKeyPath,omitempty"`
+	Password        string `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"`
 }
 
 func (x *TunnelCreationRequest) Reset() {
 	*x = TunnelCreationRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[10]
+		mi := &file_agent_communication_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -689,7 +909,7 @@ func (x *TunnelCreationRequest) String() string {
 func (*TunnelCreationRequest) ProtoMessage() {}
 
 func (x *TunnelCreationRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[10]
+	mi := &file_agent_communication_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -702,7 +922,14 @@ func (x *TunnelCreationRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use TunnelCreationRequest.ProtoReflect.Descriptor instead.
 func (*TunnelCreationRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{10}
+	return file_agent_communication_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *TunnelCreationRequest) GetExecutionId() string {
+	if x != nil {
+		return x.ExecutionId
+	}
+	return ""
 }
 
 func (x *TunnelCreationRequest) GetDestinationHost() string {
@@ -747,33 +974,32 @@ func (x *TunnelCreationRequest) GetPassword() string {
 	return ""
 }
 
-type TunnelTerminationRequest struct {
+type TunnelCreationResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	DestinationHost string `protobuf:"bytes,1,opt,name=destinationHost,proto3" json:"destinationHost,omitempty"`
-	DestinationPort int32  `protobuf:"varint,2,opt,name=destinationPort,proto3" json:"destinationPort,omitempty"`
-	SourcePort      string `protobuf:"bytes,3,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
+	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 *TunnelTerminationRequest) Reset() {
-	*x = TunnelTerminationRequest{}
+func (x *TunnelCreationResponse) Reset() {
+	*x = TunnelCreationResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[11]
+		mi := &file_agent_communication_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *TunnelTerminationRequest) String() string {
+func (x *TunnelCreationResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TunnelTerminationRequest) ProtoMessage() {}
+func (*TunnelCreationResponse) ProtoMessage() {}
 
-func (x *TunnelTerminationRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[11]
+func (x *TunnelCreationResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -784,59 +1010,53 @@ func (x *TunnelTerminationRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TunnelTerminationRequest.ProtoReflect.Descriptor instead.
-func (*TunnelTerminationRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{11}
+// Deprecated: Use TunnelCreationResponse.ProtoReflect.Descriptor instead.
+func (*TunnelCreationResponse) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{15}
 }
 
-func (x *TunnelTerminationRequest) GetDestinationHost() string {
+func (x *TunnelCreationResponse) GetExecutionId() string {
 	if x != nil {
-		return x.DestinationHost
+		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *TunnelTerminationRequest) GetDestinationPort() int32 {
-	if x != nil {
-		return x.DestinationPort
-	}
-	return 0
-}
-
-func (x *TunnelTerminationRequest) GetSourcePort() string {
+func (x *TunnelCreationResponse) GetStatus() string {
 	if x != nil {
-		return x.SourcePort
+		return x.Status
 	}
 	return ""
 }
 
-type CommandExecutionRequest struct {
+// server requesting the agent to terminate a ssh tunnel
+type TunnelTerminationRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	ExecutionId string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	Arguments   []string `protobuf:"bytes,2,rep,name=arguments,proto3" json:"arguments,omitempty"`
-	WorkingDir  string   `protobuf:"bytes,3,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	DestinationHost string `protobuf:"bytes,1,opt,name=destinationHost,proto3" json:"destinationHost,omitempty"`
+	DestinationPort int32  `protobuf:"varint,2,opt,name=destinationPort,proto3" json:"destinationPort,omitempty"`
+	SourcePort      string `protobuf:"bytes,3,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
 }
 
-func (x *CommandExecutionRequest) Reset() {
-	*x = CommandExecutionRequest{}
+func (x *TunnelTerminationRequest) Reset() {
+	*x = TunnelTerminationRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[12]
+		mi := &file_agent_communication_proto_msgTypes[16]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *CommandExecutionRequest) String() string {
+func (x *TunnelTerminationRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*CommandExecutionRequest) ProtoMessage() {}
+func (*TunnelTerminationRequest) ProtoMessage() {}
 
-func (x *CommandExecutionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[12]
+func (x *TunnelTerminationRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[16]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -847,60 +1067,58 @@ func (x *CommandExecutionRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use CommandExecutionRequest.ProtoReflect.Descriptor instead.
-func (*CommandExecutionRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{12}
+// Deprecated: Use TunnelTerminationRequest.ProtoReflect.Descriptor instead.
+func (*TunnelTerminationRequest) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{16}
 }
 
-func (x *CommandExecutionRequest) GetExecutionId() string {
+func (x *TunnelTerminationRequest) GetDestinationHost() string {
 	if x != nil {
-		return x.ExecutionId
+		return x.DestinationHost
 	}
 	return ""
 }
 
-func (x *CommandExecutionRequest) GetArguments() []string {
+func (x *TunnelTerminationRequest) GetDestinationPort() int32 {
 	if x != nil {
-		return x.Arguments
+		return x.DestinationPort
 	}
-	return nil
+	return 0
 }
 
-func (x *CommandExecutionRequest) GetWorkingDir() string {
+func (x *TunnelTerminationRequest) GetSourcePort() string {
 	if x != nil {
-		return x.WorkingDir
+		return x.SourcePort
 	}
 	return ""
 }
 
-type JupyterExecutionRequest struct {
+type TunnelTerminationResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
 	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	SessionId   string `protobuf:"bytes,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
-	KeepAlive   bool   `protobuf:"varint,3,opt,name=keepAlive,proto3" json:"keepAlive,omitempty"`
-	Code        string `protobuf:"bytes,4,opt,name=code,proto3" json:"code,omitempty"`
+	Status      string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 }
 
-func (x *JupyterExecutionRequest) Reset() {
-	*x = JupyterExecutionRequest{}
+func (x *TunnelTerminationResponse) Reset() {
+	*x = TunnelTerminationResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[13]
+		mi := &file_agent_communication_proto_msgTypes[17]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *JupyterExecutionRequest) String() string {
+func (x *TunnelTerminationResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*JupyterExecutionRequest) ProtoMessage() {}
+func (*TunnelTerminationResponse) ProtoMessage() {}
 
-func (x *JupyterExecutionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[13]
+func (x *TunnelTerminationResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[17]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -911,70 +1129,61 @@ func (x *JupyterExecutionRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use JupyterExecutionRequest.ProtoReflect.Descriptor instead.
-func (*JupyterExecutionRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{13}
+// Deprecated: Use TunnelTerminationResponse.ProtoReflect.Descriptor instead.
+func (*TunnelTerminationResponse) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{17}
 }
 
-func (x *JupyterExecutionRequest) GetExecutionId() string {
+func (x *TunnelTerminationResponse) GetExecutionId() string {
 	if x != nil {
 		return x.ExecutionId
 	}
 	return ""
 }
 
-func (x *JupyterExecutionRequest) GetSessionId() string {
-	if x != nil {
-		return x.SessionId
-	}
-	return ""
-}
-
-func (x *JupyterExecutionRequest) GetKeepAlive() bool {
-	if x != nil {
-		return x.KeepAlive
-	}
-	return false
-}
-
-func (x *JupyterExecutionRequest) GetCode() string {
+func (x *TunnelTerminationResponse) GetStatus() string {
 	if x != nil {
-		return x.Code
+		return x.Status
 	}
 	return ""
 }
 
-type PythonExecutionRequest struct {
+type AgentMessage struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	ExecutionId   string   `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
-	SessionId     string   `protobuf:"bytes,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
-	KeepAlive     bool     `protobuf:"varint,3,opt,name=keepAlive,proto3" json:"keepAlive,omitempty"`
-	Libraries     []string `protobuf:"bytes,4,rep,name=libraries,proto3" json:"libraries,omitempty"`
-	Code          string   `protobuf:"bytes,5,opt,name=code,proto3" json:"code,omitempty"`
-	PythonVersion string   `protobuf:"bytes,6,opt,name=pythonVersion,proto3" json:"pythonVersion,omitempty"`
-	WorkingDir    string   `protobuf:"bytes,7,opt,name=workingDir,proto3" json:"workingDir,omitempty"`
+	// Types that are assignable to Message:
+	//
+	//	*AgentMessage_AgentPing
+	//	*AgentMessage_CreateAgentResponse
+	//	*AgentMessage_TerminateAgentResponse
+	//	*AgentMessage_EnvSetupResponse
+	//	*AgentMessage_CommandExecutionResponse
+	//	*AgentMessage_PythonExecutionResponse
+	//	*AgentMessage_JupyterExecutionResponse
+	//	*AgentMessage_TunnelCreationResponse
+	//	*AgentMessage_TunnelTerminationResponse
+	Message isAgentMessage_Message `protobuf_oneof:"message"`
 }
 
-func (x *PythonExecutionRequest) Reset() {
-	*x = PythonExecutionRequest{}
+func (x *AgentMessage) Reset() {
+	*x = AgentMessage{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[14]
+		mi := &file_agent_communication_proto_msgTypes[18]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *PythonExecutionRequest) String() string {
+func (x *AgentMessage) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*PythonExecutionRequest) ProtoMessage() {}
+func (*AgentMessage) ProtoMessage() {}
 
-func (x *PythonExecutionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[14]
+func (x *AgentMessage) ProtoReflect() protoreflect.Message {
+	mi := &file_agent_communication_proto_msgTypes[18]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -985,154 +1194,139 @@ func (x *PythonExecutionRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use PythonExecutionRequest.ProtoReflect.Descriptor instead.
-func (*PythonExecutionRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{14}
+// Deprecated: Use AgentMessage.ProtoReflect.Descriptor instead.
+func (*AgentMessage) Descriptor() ([]byte, []int) {
+	return file_agent_communication_proto_rawDescGZIP(), []int{18}
 }
 
-func (x *PythonExecutionRequest) GetExecutionId() string {
-	if x != nil {
-		return x.ExecutionId
+func (m *AgentMessage) GetMessage() isAgentMessage_Message {
+	if m != nil {
+		return m.Message
 	}
-	return ""
+	return nil
 }
 
-func (x *PythonExecutionRequest) GetSessionId() string {
-	if x != nil {
-		return x.SessionId
+func (x *AgentMessage) GetAgentPing() *AgentPing {
+	if x, ok := x.GetMessage().(*AgentMessage_AgentPing); ok {
+		return x.AgentPing
 	}
-	return ""
+	return nil
 }
 
-func (x *PythonExecutionRequest) GetKeepAlive() bool {
-	if x != nil {
-		return x.KeepAlive
+func (x *AgentMessage) GetCreateAgentResponse() *CreateAgentResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_CreateAgentResponse); ok {
+		return x.CreateAgentResponse
 	}
-	return false
+	return nil
 }
 
-func (x *PythonExecutionRequest) GetLibraries() []string {
-	if x != nil {
-		return x.Libraries
+func (x *AgentMessage) GetTerminateAgentResponse() *TerminateAgentResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_TerminateAgentResponse); ok {
+		return x.TerminateAgentResponse
 	}
 	return nil
 }
 
-func (x *PythonExecutionRequest) GetCode() string {
-	if x != nil {
-		return x.Code
+func (x *AgentMessage) GetEnvSetupResponse() *EnvSetupResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_EnvSetupResponse); ok {
+		return x.EnvSetupResponse
 	}
-	return ""
+	return nil
 }
 
-func (x *PythonExecutionRequest) GetPythonVersion() string {
-	if x != nil {
-		return x.PythonVersion
+func (x *AgentMessage) GetCommandExecutionResponse() *CommandExecutionResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_CommandExecutionResponse); ok {
+		return x.CommandExecutionResponse
 	}
-	return ""
+	return nil
 }
 
-func (x *PythonExecutionRequest) GetWorkingDir() string {
-	if x != nil {
-		return x.WorkingDir
+func (x *AgentMessage) GetPythonExecutionResponse() *PythonExecutionResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_PythonExecutionResponse); ok {
+		return x.PythonExecutionResponse
 	}
-	return ""
-}
-
-type TerminateExecutionRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	ExecutionId string `protobuf:"bytes,1,opt,name=executionId,proto3" json:"executionId,omitempty"`
+	return nil
 }
 
-func (x *TerminateExecutionRequest) Reset() {
-	*x = TerminateExecutionRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[15]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
+func (x *AgentMessage) GetJupyterExecutionResponse() *JupyterExecutionResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_JupyterExecutionResponse); ok {
+		return x.JupyterExecutionResponse
 	}
+	return nil
 }
 
-func (x *TerminateExecutionRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
+func (x *AgentMessage) GetTunnelCreationResponse() *TunnelCreationResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_TunnelCreationResponse); ok {
+		return x.TunnelCreationResponse
+	}
+	return nil
 }
 
-func (*TerminateExecutionRequest) ProtoMessage() {}
-
-func (x *TerminateExecutionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[15]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
+func (x *AgentMessage) GetTunnelTerminationResponse() *TunnelTerminationResponse {
+	if x, ok := x.GetMessage().(*AgentMessage_TunnelTerminationResponse); ok {
+		return x.TunnelTerminationResponse
 	}
-	return mi.MessageOf(x)
+	return nil
 }
 
-// Deprecated: Use TerminateExecutionRequest.ProtoReflect.Descriptor instead.
-func (*TerminateExecutionRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{15}
+type isAgentMessage_Message interface {
+	isAgentMessage_Message()
 }
 
-func (x *TerminateExecutionRequest) GetExecutionId() string {
-	if x != nil {
-		return x.ExecutionId
-	}
-	return ""
+type AgentMessage_AgentPing struct {
+	AgentPing *AgentPing `protobuf:"bytes,1,opt,name=agentPing,proto3,oneof"`
 }
 
-type KillAgentRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
+type AgentMessage_CreateAgentResponse struct {
+	CreateAgentResponse *CreateAgentResponse `protobuf:"bytes,2,opt,name=createAgentResponse,proto3,oneof"`
+}
 
-	Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"`
+type AgentMessage_TerminateAgentResponse struct {
+	TerminateAgentResponse *TerminateAgentResponse `protobuf:"bytes,3,opt,name=terminateAgentResponse,proto3,oneof"`
 }
 
-func (x *KillAgentRequest) Reset() {
-	*x = KillAgentRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[16]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
+type AgentMessage_EnvSetupResponse struct {
+	EnvSetupResponse *EnvSetupResponse `protobuf:"bytes,4,opt,name=envSetupResponse,proto3,oneof"`
 }
 
-func (x *KillAgentRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
+type AgentMessage_CommandExecutionResponse struct {
+	CommandExecutionResponse *CommandExecutionResponse `protobuf:"bytes,5,opt,name=commandExecutionResponse,proto3,oneof"`
 }
 
-func (*KillAgentRequest) ProtoMessage() {}
+type AgentMessage_PythonExecutionResponse struct {
+	PythonExecutionResponse *PythonExecutionResponse `protobuf:"bytes,6,opt,name=pythonExecutionResponse,proto3,oneof"`
+}
 
-func (x *KillAgentRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[16]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
+type AgentMessage_JupyterExecutionResponse struct {
+	JupyterExecutionResponse *JupyterExecutionResponse `protobuf:"bytes,7,opt,name=jupyterExecutionResponse,proto3,oneof"`
 }
 
-// Deprecated: Use KillAgentRequest.ProtoReflect.Descriptor instead.
-func (*KillAgentRequest) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{16}
+type AgentMessage_TunnelCreationResponse struct {
+	TunnelCreationResponse *TunnelCreationResponse `protobuf:"bytes,8,opt,name=tunnelCreationResponse,proto3,oneof"`
 }
 
-func (x *KillAgentRequest) GetReason() string {
-	if x != nil {
-		return x.Reason
-	}
-	return ""
+type AgentMessage_TunnelTerminationResponse struct {
+	TunnelTerminationResponse *TunnelTerminationResponse `protobuf:"bytes,9,opt,name=tunnelTerminationResponse,proto3,oneof"`
 }
 
+func (*AgentMessage_AgentPing) isAgentMessage_Message() {}
+
+func (*AgentMessage_CreateAgentResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_TerminateAgentResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_EnvSetupResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_CommandExecutionResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_PythonExecutionResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_JupyterExecutionResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_TunnelCreationResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_TunnelTerminationResponse) isAgentMessage_Message() {}
+
 type ServerMessage struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1140,20 +1334,22 @@ type ServerMessage struct {
 
 	// Types that are assignable to Message:
 	//
-	//	*ServerMessage_ContainerExecutionRequest
+	//	*ServerMessage_ShutdownRequest
+	//	*ServerMessage_CreateAgentRequest
+	//	*ServerMessage_TerminateAgentRequest
+	//	*ServerMessage_EnvSetupRequest
 	//	*ServerMessage_CommandExecutionRequest
-	//	*ServerMessage_TerminateExecutionRequest
-	//	*ServerMessage_KillAgentRequest
-	//	*ServerMessage_TunnelCreationRequest
-	//	*ServerMessage_JupyterExecutionRequest
 	//	*ServerMessage_PythonExecutionRequest
+	//	*ServerMessage_JupyterExecutionRequest
+	//	*ServerMessage_TunnelCreationRequest
+	//	*ServerMessage_TunnelTerminationRequest
 	Message isServerMessage_Message `protobuf_oneof:"message"`
 }
 
 func (x *ServerMessage) Reset() {
 	*x = ServerMessage{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_agent_communication_proto_msgTypes[17]
+		mi := &file_agent_communication_proto_msgTypes[19]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1166,7 +1362,7 @@ func (x *ServerMessage) String() string {
 func (*ServerMessage) ProtoMessage() {}
 
 func (x *ServerMessage) ProtoReflect() protoreflect.Message {
-	mi := &file_agent_communication_proto_msgTypes[17]
+	mi := &file_agent_communication_proto_msgTypes[19]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1179,7 +1375,7 @@ func (x *ServerMessage) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead.
 func (*ServerMessage) Descriptor() ([]byte, []int) {
-	return file_agent_communication_proto_rawDescGZIP(), []int{17}
+	return file_agent_communication_proto_rawDescGZIP(), []int{19}
 }
 
 func (m *ServerMessage) GetMessage() isServerMessage_Message {
@@ -1189,37 +1385,44 @@ func (m *ServerMessage) GetMessage() isServerMessage_Message {
 	return nil
 }
 
-func (x *ServerMessage) GetContainerExecutionRequest() *ContainerExecutionRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_ContainerExecutionRequest); ok {
-		return x.ContainerExecutionRequest
+func (x *ServerMessage) GetShutdownRequest() *ShutdownRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_ShutdownRequest); ok {
+		return x.ShutdownRequest
 	}
 	return nil
 }
 
-func (x *ServerMessage) GetCommandExecutionRequest() *CommandExecutionRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_CommandExecutionRequest); ok {
-		return x.CommandExecutionRequest
+func (x *ServerMessage) GetCreateAgentRequest() *CreateAgentRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_CreateAgentRequest); ok {
+		return x.CreateAgentRequest
 	}
 	return nil
 }
 
-func (x *ServerMessage) GetTerminateExecutionRequest() *TerminateExecutionRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_TerminateExecutionRequest); ok {
-		return x.TerminateExecutionRequest
+func (x *ServerMessage) GetTerminateAgentRequest() *TerminateAgentRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_TerminateAgentRequest); ok {
+		return x.TerminateAgentRequest
 	}
 	return nil
 }
 
-func (x *ServerMessage) GetKillAgentRequest() *KillAgentRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_KillAgentRequest); ok {
-		return x.KillAgentRequest
+func (x *ServerMessage) GetEnvSetupRequest() *EnvSetupRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_EnvSetupRequest); ok {
+		return x.EnvSetupRequest
 	}
 	return nil
 }
 
-func (x *ServerMessage) GetTunnelCreationRequest() *TunnelCreationRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_TunnelCreationRequest); ok {
-		return x.TunnelCreationRequest
+func (x *ServerMessage) GetCommandExecutionRequest() *CommandExecutionRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_CommandExecutionRequest); ok {
+		return x.CommandExecutionRequest
+	}
+	return nil
+}
+
+func (x *ServerMessage) GetPythonExecutionRequest() *PythonExecutionRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_PythonExecutionRequest); ok {
+		return x.PythonExecutionRequest
 	}
 	return nil
 }
@@ -1231,9 +1434,16 @@ func (x *ServerMessage) GetJupyterExecutionRequest() *JupyterExecutionRequest {
 	return nil
 }
 
-func (x *ServerMessage) GetPythonExecutionRequest() *PythonExecutionRequest {
-	if x, ok := x.GetMessage().(*ServerMessage_PythonExecutionRequest); ok {
-		return x.PythonExecutionRequest
+func (x *ServerMessage) GetTunnelCreationRequest() *TunnelCreationRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_TunnelCreationRequest); ok {
+		return x.TunnelCreationRequest
+	}
+	return nil
+}
+
+func (x *ServerMessage) GetTunnelTerminationRequest() *TunnelTerminationRequest {
+	if x, ok := x.GetMessage().(*ServerMessage_TunnelTerminationRequest); ok {
+		return x.TunnelTerminationRequest
 	}
 	return nil
 }
@@ -1242,48 +1452,60 @@ type isServerMessage_Message interface {
 	isServerMessage_Message()
 }
 
-type ServerMessage_ContainerExecutionRequest struct {
-	ContainerExecutionRequest *ContainerExecutionRequest `protobuf:"bytes,1,opt,name=containerExecutionRequest,proto3,oneof"`
+type ServerMessage_ShutdownRequest struct {
+	ShutdownRequest *ShutdownRequest `protobuf:"bytes,1,opt,name=shutdownRequest,proto3,oneof"`
 }
 
-type ServerMessage_CommandExecutionRequest struct {
-	CommandExecutionRequest *CommandExecutionRequest `protobuf:"bytes,2,opt,name=commandExecutionRequest,proto3,oneof"`
+type ServerMessage_CreateAgentRequest struct {
+	CreateAgentRequest *CreateAgentRequest `protobuf:"bytes,2,opt,name=createAgentRequest,proto3,oneof"`
 }
 
-type ServerMessage_TerminateExecutionRequest struct {
-	TerminateExecutionRequest *TerminateExecutionRequest `protobuf:"bytes,3,opt,name=terminateExecutionRequest,proto3,oneof"`
+type ServerMessage_TerminateAgentRequest struct {
+	TerminateAgentRequest *TerminateAgentRequest `protobuf:"bytes,3,opt,name=terminateAgentRequest,proto3,oneof"`
 }
 
-type ServerMessage_KillAgentRequest struct {
-	KillAgentRequest *KillAgentRequest `protobuf:"bytes,4,opt,name=killAgentRequest,proto3,oneof"`
+type ServerMessage_EnvSetupRequest struct {
+	EnvSetupRequest *EnvSetupRequest `protobuf:"bytes,4,opt,name=envSetupRequest,proto3,oneof"`
 }
 
-type ServerMessage_TunnelCreationRequest struct {
-	TunnelCreationRequest *TunnelCreationRequest `protobuf:"bytes,5,opt,name=tunnelCreationRequest,proto3,oneof"`
+type ServerMessage_CommandExecutionRequest struct {
+	CommandExecutionRequest *CommandExecutionRequest `protobuf:"bytes,5,opt,name=commandExecutionRequest,proto3,oneof"`
+}
+
+type ServerMessage_PythonExecutionRequest struct {
+	PythonExecutionRequest *PythonExecutionRequest `protobuf:"bytes,6,opt,name=pythonExecutionRequest,proto3,oneof"`
 }
 
 type ServerMessage_JupyterExecutionRequest struct {
-	JupyterExecutionRequest *JupyterExecutionRequest `protobuf:"bytes,6,opt,name=jupyterExecutionRequest,proto3,oneof"`
+	JupyterExecutionRequest *JupyterExecutionRequest `protobuf:"bytes,7,opt,name=jupyterExecutionRequest,proto3,oneof"`
 }
 
-type ServerMessage_PythonExecutionRequest struct {
-	PythonExecutionRequest *PythonExecutionRequest `protobuf:"bytes,7,opt,name=pythonExecutionRequest,proto3,oneof"`
+type ServerMessage_TunnelCreationRequest struct {
+	TunnelCreationRequest *TunnelCreationRequest `protobuf:"bytes,8,opt,name=tunnelCreationRequest,proto3,oneof"`
 }
 
-func (*ServerMessage_ContainerExecutionRequest) isServerMessage_Message() {}
+type ServerMessage_TunnelTerminationRequest struct {
+	TunnelTerminationRequest *TunnelTerminationRequest `protobuf:"bytes,9,opt,name=tunnelTerminationRequest,proto3,oneof"`
+}
 
-func (*ServerMessage_CommandExecutionRequest) isServerMessage_Message() {}
+func (*ServerMessage_ShutdownRequest) isServerMessage_Message() {}
 
-func (*ServerMessage_TerminateExecutionRequest) isServerMessage_Message() {}
+func (*ServerMessage_CreateAgentRequest) isServerMessage_Message() {}
 
-func (*ServerMessage_KillAgentRequest) isServerMessage_Message() {}
+func (*ServerMessage_TerminateAgentRequest) isServerMessage_Message() {}
 
-func (*ServerMessage_TunnelCreationRequest) isServerMessage_Message() {}
+func (*ServerMessage_EnvSetupRequest) isServerMessage_Message() {}
 
-func (*ServerMessage_JupyterExecutionRequest) isServerMessage_Message() {}
+func (*ServerMessage_CommandExecutionRequest) isServerMessage_Message() {}
 
 func (*ServerMessage_PythonExecutionRequest) isServerMessage_Message() {}
 
+func (*ServerMessage_JupyterExecutionRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_TunnelCreationRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_TunnelTerminationRequest) isServerMessage_Message() {}
+
 var File_agent_communication_proto protoreflect.FileDescriptor
 
 var file_agent_communication_proto_rawDesc = []byte{
@@ -1292,226 +1514,267 @@ var file_agent_communication_proto_rawDesc = []byte{
 	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, 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, 0x66, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	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, 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, 0x82, 0x01, 0x0a, 0x18,
-	0x4a, 0x75, 0x70, 0x79, 0x74, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+	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, 0x1c, 0x0a, 0x09, 0x73, 0x65,
-	0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73,
-	0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
-	0x22, 0x81, 0x01, 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, 0x1c,
-	0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e,
-	0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74,
-	0x72, 0x69, 0x6e, 0x67, 0x22, 0x56, 0x0a, 0x1a, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74,
-	0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
-	0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x30, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x33,
-	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, 0x16, 0x0a, 0x06, 0x73,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x22, 0xa7, 0x05, 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, 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, 0x02, 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, 0x77, 0x0a,
-	0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
-	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x35, 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,
-	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1a, 0x63, 0x6f, 0x6e, 0x74,
-	0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x1a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e,
-	0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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,
-	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x48, 0x00, 0x52, 0x1a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78,
+	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, 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,
+	0x8b, 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, 0x28, 0x0a, 0x0f, 0x64,
+	0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
+	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12,
+	0x20, 0x0a, 0x0b, 0x73, 0x73, 0x68, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x73, 0x68, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d,
+	0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72,
+	0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x18,
+	0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x74,
+	0x68, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x07, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x52, 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, 0x22, 0x8e, 0x01, 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, 0x28,
+	0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x73,
+	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74,
+	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f,
+	0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f,
+	0x72, 0x74, 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, 0xc4, 0x07, 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, 0x05, 0x20, 0x01, 0x28,
+	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, 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, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9f, 0x01,
-	0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 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, 0x24, 0x0a,
-	0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e,
-	0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-	0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74,
-	0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x61, 0x74, 0x68, 0x22,
-	0xe9, 0x01, 0x0a, 0x15, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73,
-	0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48,
-	0x6f, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65,
-	0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x20, 0x0a,
-	0x0b, 0x73, 0x73, 0x68, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0b, 0x73, 0x73, 0x68, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12,
-	0x1e, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12,
-	0x1e, 0x0a, 0x0a, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12,
-	0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x8e, 0x01, 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, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74,
-	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f,
-	0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x64, 0x65, 0x73,
-	0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x79, 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, 0x1c, 0x0a, 0x09, 0x61, 0x72, 0x67,
-	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x72,
-	0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 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, 0x22, 0x8b, 0x01, 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, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
-	0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
-	0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76,
-	0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xee, 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, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64,
-	0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x08, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x1c,
-	0x0a, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28,
-	0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04,
-	0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65,
-	0x12, 0x24, 0x0a, 0x0d, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
-	0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x56,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e,
-	0x67, 0x44, 0x69, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b,
-	0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x22, 0x3d, 0x0a, 0x19, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e,
-	0x61, 0x74, 0x65, 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, 0x22, 0x2a, 0x0a, 0x10, 0x4b, 0x69, 0x6c, 0x6c, 0x41, 0x67, 0x65,
-	0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x98, 0x06, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x12, 0x74, 0x0a, 0x19, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61,
+	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, 0x08, 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, 0x09, 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, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x22, 0xbf, 0x07, 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, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63,
-	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x19,
-	0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
-	0x6f, 0x6e, 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, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6f, 0x72, 0x67,
+	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, 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, 0x74, 0x0a, 0x19, 0x74, 0x65, 0x72,
-	0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 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, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61,
-	0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x48, 0x00, 0x52, 0x19, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x45,
-	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x59, 0x0a, 0x10, 0x6b, 0x69, 0x6c, 0x6c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 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, 0x4b, 0x69, 0x6c, 0x6c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x10, 0x6b, 0x69, 0x6c, 0x6c, 0x41, 0x67,
-	0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x15, 0x74, 0x75,
+	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, 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, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6f, 0x72, 0x67, 0x2e,
+	0x65, 0x73, 0x74, 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, 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, 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,
-	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, 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, 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, 0x07,
-	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, 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,
+	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, 0x09, 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, 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,
+	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, 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 (
@@ -1526,48 +1789,55 @@ func file_agent_communication_proto_rawDescGZIP() []byte {
 	return file_agent_communication_proto_rawDescData
 }
 
-var file_agent_communication_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_agent_communication_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
 var file_agent_communication_proto_goTypes = []any{
-	(*AgentPing)(nil),                  // 0: org.apache.airavata.agent.AgentPing
-	(*CommandExecutionResponse)(nil),   // 1: org.apache.airavata.agent.CommandExecutionResponse
-	(*ContainerExecutionResponse)(nil), // 2: org.apache.airavata.agent.ContainerExecutionResponse
-	(*JupyterExecutionResponse)(nil),   // 3: org.apache.airavata.agent.JupyterExecutionResponse
-	(*PythonExecutionResponse)(nil),    // 4: org.apache.airavata.agent.PythonExecutionResponse
-	(*TerminateExecutionResponse)(nil), // 5: org.apache.airavata.agent.TerminateExecutionResponse
-	(*TunnelCreationResponse)(nil),     // 6: org.apache.airavata.agent.TunnelCreationResponse
-	(*TunnelTerminationResponse)(nil),  // 7: org.apache.airavata.agent.TunnelTerminationResponse
-	(*AgentMessage)(nil),               // 8: org.apache.airavata.agent.AgentMessage
-	(*ContainerExecutionRequest)(nil),  // 9: org.apache.airavata.agent.ContainerExecutionRequest
-	(*TunnelCreationRequest)(nil),      // 10: org.apache.airavata.agent.TunnelCreationRequest
-	(*TunnelTerminationRequest)(nil),   // 11: org.apache.airavata.agent.TunnelTerminationRequest
-	(*CommandExecutionRequest)(nil),    // 12: org.apache.airavata.agent.CommandExecutionRequest
-	(*JupyterExecutionRequest)(nil),    // 13: org.apache.airavata.agent.JupyterExecutionRequest
-	(*PythonExecutionRequest)(nil),     // 14: org.apache.airavata.agent.PythonExecutionRequest
-	(*TerminateExecutionRequest)(nil),  // 15: org.apache.airavata.agent.TerminateExecutionRequest
-	(*KillAgentRequest)(nil),           // 16: org.apache.airavata.agent.KillAgentRequest
-	(*ServerMessage)(nil),              // 17: org.apache.airavata.agent.ServerMessage
+	(*AgentPing)(nil),                 // 0: org.apache.airavata.agent.AgentPing
+	(*ShutdownRequest)(nil),           // 1: org.apache.airavata.agent.ShutdownRequest
+	(*CreateAgentRequest)(nil),        // 2: org.apache.airavata.agent.CreateAgentRequest
+	(*CreateAgentResponse)(nil),       // 3: org.apache.airavata.agent.CreateAgentResponse
+	(*TerminateAgentRequest)(nil),     // 4: org.apache.airavata.agent.TerminateAgentRequest
+	(*TerminateAgentResponse)(nil),    // 5: org.apache.airavata.agent.TerminateAgentResponse
+	(*EnvSetupRequest)(nil),           // 6: org.apache.airavata.agent.EnvSetupRequest
+	(*EnvSetupResponse)(nil),          // 7: org.apache.airavata.agent.EnvSetupResponse
+	(*CommandExecutionRequest)(nil),   // 8: org.apache.airavata.agent.CommandExecutionRequest
+	(*CommandExecutionResponse)(nil),  // 9: org.apache.airavata.agent.CommandExecutionResponse
+	(*PythonExecutionRequest)(nil),    // 10: org.apache.airavata.agent.PythonExecutionRequest
+	(*PythonExecutionResponse)(nil),   // 11: org.apache.airavata.agent.PythonExecutionResponse
+	(*JupyterExecutionRequest)(nil),   // 12: org.apache.airavata.agent.JupyterExecutionRequest
+	(*JupyterExecutionResponse)(nil),  // 13: org.apache.airavata.agent.JupyterExecutionResponse
+	(*TunnelCreationRequest)(nil),     // 14: org.apache.airavata.agent.TunnelCreationRequest
+	(*TunnelCreationResponse)(nil),    // 15: org.apache.airavata.agent.TunnelCreationResponse
+	(*TunnelTerminationRequest)(nil),  // 16: org.apache.airavata.agent.TunnelTerminationRequest
+	(*TunnelTerminationResponse)(nil), // 17: org.apache.airavata.agent.TunnelTerminationResponse
+	(*AgentMessage)(nil),              // 18: org.apache.airavata.agent.AgentMessage
+	(*ServerMessage)(nil),             // 19: org.apache.airavata.agent.ServerMessage
 }
 var file_agent_communication_proto_depIdxs = []int32{
 	0,  // 0: org.apache.airavata.agent.AgentMessage.agentPing:type_name -> org.apache.airavata.agent.AgentPing
-	1,  // 1: org.apache.airavata.agent.AgentMessage.commandExecutionResponse:type_name -> org.apache.airavata.agent.CommandExecutionResponse
-	2,  // 2: org.apache.airavata.agent.AgentMessage.containerExecutionResponse:type_name -> org.apache.airavata.agent.ContainerExecutionResponse
-	5,  // 3: org.apache.airavata.agent.AgentMessage.terminateExecutionResponse:type_name -> org.apache.airavata.agent.TerminateExecutionResponse
-	3,  // 4: org.apache.airavata.agent.AgentMessage.jupyterExecutionResponse:type_name -> org.apache.airavata.agent.JupyterExecutionResponse
-	4,  // 5: org.apache.airavata.agent.AgentMessage.pythonExecutionResponse:type_name -> org.apache.airavata.agent.PythonExecutionResponse
-	9,  // 6: org.apache.airavata.agent.ServerMessage.containerExecutionRequest:type_name -> org.apache.airavata.agent.ContainerExecutionRequest
-	12, // 7: org.apache.airavata.agent.ServerMessage.commandExecutionRequest:type_name -> org.apache.airavata.agent.CommandExecutionRequest
-	15, // 8: org.apache.airavata.agent.ServerMessage.terminateExecutionRequest:type_name -> org.apache.airavata.agent.TerminateExecutionRequest
-	16, // 9: org.apache.airavata.agent.ServerMessage.killAgentRequest:type_name -> org.apache.airavata.agent.KillAgentRequest
-	10, // 10: org.apache.airavata.agent.ServerMessage.tunnelCreationRequest:type_name -> org.apache.airavata.agent.TunnelCreationRequest
-	13, // 11: org.apache.airavata.agent.ServerMessage.jupyterExecutionRequest:type_name -> org.apache.airavata.agent.JupyterExecutionRequest
-	14, // 12: org.apache.airavata.agent.ServerMessage.pythonExecutionRequest:type_name -> org.apache.airavata.agent.PythonExecutionRequest
-	8,  // 13: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:input_type -> org.apache.airavata.agent.AgentMessage
-	17, // 14: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:output_type -> org.apache.airavata.agent.ServerMessage
-	14, // [14:15] is the sub-list for method output_type
-	13, // [13:14] is the sub-list for method input_type
-	13, // [13:13] is the sub-list for extension type_name
-	13, // [13:13] is the sub-list for extension extendee
-	0,  // [0:13] is the sub-list for field type_name
+	3,  // 1: org.apache.airavata.agent.AgentMessage.createAgentResponse:type_name -> org.apache.airavata.agent.CreateAgentResponse
+	5,  // 2: org.apache.airavata.agent.AgentMessage.terminateAgentResponse:type_name -> org.apache.airavata.agent.TerminateAgentResponse
+	7,  // 3: org.apache.airavata.agent.AgentMessage.envSetupResponse:type_name -> org.apache.airavata.agent.EnvSetupResponse
+	9,  // 4: org.apache.airavata.agent.AgentMessage.commandExecutionResponse:type_name -> org.apache.airavata.agent.CommandExecutionResponse
+	11, // 5: org.apache.airavata.agent.AgentMessage.pythonExecutionResponse:type_name -> org.apache.airavata.agent.PythonExecutionResponse
+	13, // 6: org.apache.airavata.agent.AgentMessage.jupyterExecutionResponse:type_name -> org.apache.airavata.agent.JupyterExecutionResponse
+	15, // 7: org.apache.airavata.agent.AgentMessage.tunnelCreationResponse:type_name -> org.apache.airavata.agent.TunnelCreationResponse
+	17, // 8: org.apache.airavata.agent.AgentMessage.tunnelTerminationResponse:type_name -> org.apache.airavata.agent.TunnelTerminationResponse
+	1,  // 9: org.apache.airavata.agent.ServerMessage.shutdownRequest:type_name -> org.apache.airavata.agent.ShutdownRequest
+	2,  // 10: org.apache.airavata.agent.ServerMessage.createAgentRequest:type_name -> org.apache.airavata.agent.CreateAgentRequest
+	4,  // 11: org.apache.airavata.agent.ServerMessage.terminateAgentRequest:type_name -> org.apache.airavata.agent.TerminateAgentRequest
+	6,  // 12: org.apache.airavata.agent.ServerMessage.envSetupRequest:type_name -> org.apache.airavata.agent.EnvSetupRequest
+	8,  // 13: org.apache.airavata.agent.ServerMessage.commandExecutionRequest:type_name -> org.apache.airavata.agent.CommandExecutionRequest
+	10, // 14: org.apache.airavata.agent.ServerMessage.pythonExecutionRequest:type_name -> org.apache.airavata.agent.PythonExecutionRequest
+	12, // 15: org.apache.airavata.agent.ServerMessage.jupyterExecutionRequest:type_name -> org.apache.airavata.agent.JupyterExecutionRequest
+	14, // 16: org.apache.airavata.agent.ServerMessage.tunnelCreationRequest:type_name -> org.apache.airavata.agent.TunnelCreationRequest
+	16, // 17: org.apache.airavata.agent.ServerMessage.tunnelTerminationRequest:type_name -> org.apache.airavata.agent.TunnelTerminationRequest
+	18, // 18: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:input_type -> org.apache.airavata.agent.AgentMessage
+	19, // 19: org.apache.airavata.agent.AgentCommunicationService.createMessageBus:output_type -> org.apache.airavata.agent.ServerMessage
+	19, // [19:20] is the sub-list for method output_type
+	18, // [18:19] is the sub-list for method input_type
+	18, // [18:18] is the sub-list for extension type_name
+	18, // [18:18] is the sub-list for extension extendee
+	0,  // [0:18] is the sub-list for field type_name
 }
 
 func init() { file_agent_communication_proto_init() }
@@ -1589,7 +1859,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[1].Exporter = func(v any, i int) any {
-			switch v := v.(*CommandExecutionResponse); i {
+			switch v := v.(*ShutdownRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1601,7 +1871,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[2].Exporter = func(v any, i int) any {
-			switch v := v.(*ContainerExecutionResponse); i {
+			switch v := v.(*CreateAgentRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1613,7 +1883,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[3].Exporter = func(v any, i int) any {
-			switch v := v.(*JupyterExecutionResponse); i {
+			switch v := v.(*CreateAgentResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1625,7 +1895,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[4].Exporter = func(v any, i int) any {
-			switch v := v.(*PythonExecutionResponse); i {
+			switch v := v.(*TerminateAgentRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1637,7 +1907,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[5].Exporter = func(v any, i int) any {
-			switch v := v.(*TerminateExecutionResponse); i {
+			switch v := v.(*TerminateAgentResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1649,7 +1919,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[6].Exporter = func(v any, i int) any {
-			switch v := v.(*TunnelCreationResponse); i {
+			switch v := v.(*EnvSetupRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1661,7 +1931,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[7].Exporter = func(v any, i int) any {
-			switch v := v.(*TunnelTerminationResponse); i {
+			switch v := v.(*EnvSetupResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1673,7 +1943,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[8].Exporter = func(v any, i int) any {
-			switch v := v.(*AgentMessage); i {
+			switch v := v.(*CommandExecutionRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1685,7 +1955,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[9].Exporter = func(v any, i int) any {
-			switch v := v.(*ContainerExecutionRequest); i {
+			switch v := v.(*CommandExecutionResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1697,7 +1967,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[10].Exporter = func(v any, i int) any {
-			switch v := v.(*TunnelCreationRequest); i {
+			switch v := v.(*PythonExecutionRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1709,7 +1979,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[11].Exporter = func(v any, i int) any {
-			switch v := v.(*TunnelTerminationRequest); i {
+			switch v := v.(*PythonExecutionResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1721,7 +1991,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[12].Exporter = func(v any, i int) any {
-			switch v := v.(*CommandExecutionRequest); i {
+			switch v := v.(*JupyterExecutionRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1733,7 +2003,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[13].Exporter = func(v any, i int) any {
-			switch v := v.(*JupyterExecutionRequest); i {
+			switch v := v.(*JupyterExecutionResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1745,7 +2015,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[14].Exporter = func(v any, i int) any {
-			switch v := v.(*PythonExecutionRequest); i {
+			switch v := v.(*TunnelCreationRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1757,7 +2027,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[15].Exporter = func(v any, i int) any {
-			switch v := v.(*TerminateExecutionRequest); i {
+			switch v := v.(*TunnelCreationResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1769,7 +2039,7 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[16].Exporter = func(v any, i int) any {
-			switch v := v.(*KillAgentRequest); i {
+			switch v := v.(*TunnelTerminationRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1781,6 +2051,30 @@ func file_agent_communication_proto_init() {
 			}
 		}
 		file_agent_communication_proto_msgTypes[17].Exporter = func(v any, i int) any {
+			switch v := v.(*TunnelTerminationResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_agent_communication_proto_msgTypes[18].Exporter = func(v any, i int) any {
+			switch v := v.(*AgentMessage); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_agent_communication_proto_msgTypes[19].Exporter = func(v any, i int) any {
 			switch v := v.(*ServerMessage); i {
 			case 0:
 				return &v.state
@@ -1793,22 +2087,27 @@ func file_agent_communication_proto_init() {
 			}
 		}
 	}
-	file_agent_communication_proto_msgTypes[8].OneofWrappers = []any{
+	file_agent_communication_proto_msgTypes[18].OneofWrappers = []any{
 		(*AgentMessage_AgentPing)(nil),
+		(*AgentMessage_CreateAgentResponse)(nil),
+		(*AgentMessage_TerminateAgentResponse)(nil),
+		(*AgentMessage_EnvSetupResponse)(nil),
 		(*AgentMessage_CommandExecutionResponse)(nil),
-		(*AgentMessage_ContainerExecutionResponse)(nil),
-		(*AgentMessage_TerminateExecutionResponse)(nil),
-		(*AgentMessage_JupyterExecutionResponse)(nil),
 		(*AgentMessage_PythonExecutionResponse)(nil),
-	}
-	file_agent_communication_proto_msgTypes[17].OneofWrappers = []any{
-		(*ServerMessage_ContainerExecutionRequest)(nil),
+		(*AgentMessage_JupyterExecutionResponse)(nil),
+		(*AgentMessage_TunnelCreationResponse)(nil),
+		(*AgentMessage_TunnelTerminationResponse)(nil),
+	}
+	file_agent_communication_proto_msgTypes[19].OneofWrappers = []any{
+		(*ServerMessage_ShutdownRequest)(nil),
+		(*ServerMessage_CreateAgentRequest)(nil),
+		(*ServerMessage_TerminateAgentRequest)(nil),
+		(*ServerMessage_EnvSetupRequest)(nil),
 		(*ServerMessage_CommandExecutionRequest)(nil),
-		(*ServerMessage_TerminateExecutionRequest)(nil),
-		(*ServerMessage_KillAgentRequest)(nil),
-		(*ServerMessage_TunnelCreationRequest)(nil),
-		(*ServerMessage_JupyterExecutionRequest)(nil),
 		(*ServerMessage_PythonExecutionRequest)(nil),
+		(*ServerMessage_JupyterExecutionRequest)(nil),
+		(*ServerMessage_TunnelCreationRequest)(nil),
+		(*ServerMessage_TunnelTerminationRequest)(nil),
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -1816,7 +2115,7 @@ func file_agent_communication_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_agent_communication_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   18,
+			NumMessages:   20,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
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 d32e4d18eb..758309c621 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,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
-// - protoc-gen-go-grpc v1.4.0
-// - protoc             v4.24.4
+// - protoc-gen-go-grpc v1.5.1
+// - protoc             v5.29.3
 // source: agent-communication.proto
 
 package protos
@@ -15,8 +15,8 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.62.0 or later.
-const _ = grpc.SupportPackageIsVersion8
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
 
 const (
 	AgentCommunicationService_CreateMessageBus_FullMethodName = "/org.apache.airavata.agent.AgentCommunicationService/createMessageBus"
@@ -26,7 +26,7 @@ const (
 //
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
 type AgentCommunicationServiceClient interface {
-	CreateMessageBus(ctx context.Context, opts ...grpc.CallOption) (AgentCommunicationService_CreateMessageBusClient, error)
+	CreateMessageBus(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[AgentMessage, ServerMessage], error)
 }
 
 type agentCommunicationServiceClient struct {
@@ -37,55 +37,40 @@ func NewAgentCommunicationServiceClient(cc grpc.ClientConnInterface) AgentCommun
 	return &agentCommunicationServiceClient{cc}
 }
 
-func (c *agentCommunicationServiceClient) CreateMessageBus(ctx context.Context, opts ...grpc.CallOption) (AgentCommunicationService_CreateMessageBusClient, error) {
+func (c *agentCommunicationServiceClient) CreateMessageBus(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[AgentMessage, ServerMessage], error) {
 	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	stream, err := c.cc.NewStream(ctx, &AgentCommunicationService_ServiceDesc.Streams[0], AgentCommunicationService_CreateMessageBus_FullMethodName, cOpts...)
 	if err != nil {
 		return nil, err
 	}
-	x := &agentCommunicationServiceCreateMessageBusClient{ClientStream: stream}
+	x := &grpc.GenericClientStream[AgentMessage, ServerMessage]{ClientStream: stream}
 	return x, nil
 }
 
-type AgentCommunicationService_CreateMessageBusClient interface {
-	Send(*AgentMessage) error
-	Recv() (*ServerMessage, error)
-	grpc.ClientStream
-}
-
-type agentCommunicationServiceCreateMessageBusClient struct {
-	grpc.ClientStream
-}
-
-func (x *agentCommunicationServiceCreateMessageBusClient) Send(m *AgentMessage) error {
-	return x.ClientStream.SendMsg(m)
-}
-
-func (x *agentCommunicationServiceCreateMessageBusClient) Recv() (*ServerMessage, error) {
-	m := new(ServerMessage)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
+// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
+type AgentCommunicationService_CreateMessageBusClient = grpc.BidiStreamingClient[AgentMessage, ServerMessage]
 
 // AgentCommunicationServiceServer is the server API for AgentCommunicationService service.
 // All implementations must embed UnimplementedAgentCommunicationServiceServer
-// for forward compatibility
+// for forward compatibility.
 type AgentCommunicationServiceServer interface {
-	CreateMessageBus(AgentCommunicationService_CreateMessageBusServer) error
+	CreateMessageBus(grpc.BidiStreamingServer[AgentMessage, ServerMessage]) error
 	mustEmbedUnimplementedAgentCommunicationServiceServer()
 }
 
-// UnimplementedAgentCommunicationServiceServer must be embedded to have forward compatible implementations.
-type UnimplementedAgentCommunicationServiceServer struct {
-}
+// UnimplementedAgentCommunicationServiceServer must be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedAgentCommunicationServiceServer struct{}
 
-func (UnimplementedAgentCommunicationServiceServer) CreateMessageBus(AgentCommunicationService_CreateMessageBusServer) error {
+func (UnimplementedAgentCommunicationServiceServer) CreateMessageBus(grpc.BidiStreamingServer[AgentMessage, ServerMessage]) error {
 	return status.Errorf(codes.Unimplemented, "method CreateMessageBus not implemented")
 }
 func (UnimplementedAgentCommunicationServiceServer) mustEmbedUnimplementedAgentCommunicationServiceServer() {
 }
+func (UnimplementedAgentCommunicationServiceServer) testEmbeddedByValue() {}
 
 // UnsafeAgentCommunicationServiceServer may be embedded to opt out of forward compatibility for this service.
 // Use of this interface is not recommended, as added methods to AgentCommunicationServiceServer will
@@ -95,34 +80,22 @@ type UnsafeAgentCommunicationServiceServer interface {
 }
 
 func RegisterAgentCommunicationServiceServer(s grpc.ServiceRegistrar, srv AgentCommunicationServiceServer) {
+	// If the following call pancis, it indicates UnimplementedAgentCommunicationServiceServer was
+	// embedded by pointer and is nil.  This will cause panics if an
+	// unimplemented method is ever invoked, so we test this at initialization
+	// time to prevent it from happening at runtime later due to I/O.
+	if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+		t.testEmbeddedByValue()
+	}
 	s.RegisterService(&AgentCommunicationService_ServiceDesc, srv)
 }
 
 func _AgentCommunicationService_CreateMessageBus_Handler(srv interface{}, stream grpc.ServerStream) error {
-	return srv.(AgentCommunicationServiceServer).CreateMessageBus(&agentCommunicationServiceCreateMessageBusServer{ServerStream: stream})
-}
-
-type AgentCommunicationService_CreateMessageBusServer interface {
-	Send(*ServerMessage) error
-	Recv() (*AgentMessage, error)
-	grpc.ServerStream
-}
-
-type agentCommunicationServiceCreateMessageBusServer struct {
-	grpc.ServerStream
+	return srv.(AgentCommunicationServiceServer).CreateMessageBus(&grpc.GenericServerStream[AgentMessage, ServerMessage]{ServerStream: stream})
 }
 
-func (x *agentCommunicationServiceCreateMessageBusServer) Send(m *ServerMessage) error {
-	return x.ServerStream.SendMsg(m)
-}
-
-func (x *agentCommunicationServiceCreateMessageBusServer) Recv() (*AgentMessage, error) {
-	m := new(AgentMessage)
-	if err := x.ServerStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
+// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
+type AgentCommunicationService_CreateMessageBusServer = grpc.BidiStreamingServer[AgentMessage, ServerMessage]
 
 // AgentCommunicationService_ServiceDesc is the grpc.ServiceDesc for AgentCommunicationService service.
 // It's only intended for direct use with grpc.RegisterService,
diff --git a/modules/agent-framework/proto/agent-communication.proto b/modules/agent-framework/proto/agent-communication.proto
index 62dd4db5be..9bf6d3d7f3 100644
--- a/modules/agent-framework/proto/agent-communication.proto
+++ b/modules/agent-framework/proto/agent-communication.proto
@@ -11,117 +11,138 @@ service AgentCommunicationService {
   rpc createMessageBus(stream AgentMessage) returns (stream ServerMessage);
 }
 
+// agent pinging the server
 message AgentPing {
   string agentId = 1;
 }
 
-message CommandExecutionResponse {
-  string executionId = 1;
-  string responseString = 2;
+// server requesting the agent to shutdown
+message ShutdownRequest {
+  string agentId = 1;
 }
 
-message ContainerExecutionResponse {
+// server requesting the agent to create a new agent subprocess
+message CreateAgentRequest {
   string executionId = 1;
-  string responseString = 2;
+  string agentId = 2;
+  string containerId = 3;
+  string workingDir = 4;
+  repeated string mounts = 5;
 }
-
-message JupyterExecutionResponse {
+message CreateAgentResponse {
   string executionId = 1;
-  string sessionId = 2;
-  string responseString = 3;
+  string agentId = 2;
+  string status = 3;
 }
 
-message PythonExecutionResponse {
+// server requesting the agent to terminate an agent subprocess
+message TerminateAgentRequest {
   string executionId = 1;
-  string sessionId = 2;
-  string responseString = 3;
+  string agentId = 2;
 }
-
-message TerminateExecutionResponse {
-  string status = 1;
-  string description = 2;
-}
-
-message TunnelCreationResponse {
-  string status = 1;
-}
-
-message TunnelTerminationResponse {
-  string status = 1;
+message TerminateAgentResponse {
+  string executionId = 1;
+  string agentId = 2;
+  string status = 3;
 }
 
-message AgentMessage {
-  oneof message {
-    AgentPing agentPing = 1;
-    CommandExecutionResponse commandExecutionResponse = 2;
-    ContainerExecutionResponse containerExecutionResponse = 3;
-    TerminateExecutionResponse terminateExecutionResponse = 4;
-    JupyterExecutionResponse jupyterExecutionResponse = 5;
-    PythonExecutionResponse pythonExecutionResponse = 6;
-  }
+// server requesting the agent to setup an environment
+message EnvSetupRequest {
+  string executionId = 1;
+  string envName = 2;
+  repeated string libraries = 3;
+  repeated string pip = 4;
 }
-
-message ContainerExecutionRequest {
+message EnvSetupResponse {
   string executionId = 1;
-  string containerName = 2;
-  repeated string arguments = 3;
-  string mountPath = 4;
+  string status = 2;
 }
 
-message TunnelCreationRequest {
-  string destinationHost = 1;
-  string destinationPort = 2;
-  string sshUserName = 3;
-  string sourcePort = 4;
-  string sshKeyPath = 5;
-  string password = 6;
+// server requesting the agent to execute a shell command in the environment
+message CommandExecutionRequest {
+  string executionId = 1;
+  string envName = 2;
+  string workingDir = 3;
+  repeated string arguments = 4;
 }
-
-message TunnelTerminationRequest {
-  string destinationHost = 1;
-  int32 destinationPort = 2;
-  string sourcePort = 3;
+message CommandExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
 }
 
-message CommandExecutionRequest {
+// server requesting the agent to execute a python script in the environment
+message PythonExecutionRequest {
   string executionId = 1;
-  repeated string arguments = 2;
+  string envName = 2;
   string workingDir = 3;
+  string code = 4;
+}
+message PythonExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
 }
 
+// server requesting the agent to execute a jupyter notebook cell in the environment
 message JupyterExecutionRequest {
   string executionId = 1;
-  string sessionId = 2;
-  bool keepAlive = 3;
-  string code = 4;
+  string envName = 2;
+  string code = 3;
+}
+message JupyterExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
 }
 
-message PythonExecutionRequest {
+// server requesting the agent to create a ssh tunnel
+message TunnelCreationRequest {
+  string executionId = 1;
+  string destinationHost = 2;
+  string destinationPort = 3;
+  string sshUserName = 4;
+  string sourcePort = 5;
+  string sshKeyPath = 6;
+  string password = 7;
+}
+message TunnelCreationResponse {
   string executionId = 1;
-  string sessionId = 2;
-  bool keepAlive = 3;
-  repeated string libraries = 4;
-  string code = 5;
-  string pythonVersion = 6;
-  string workingDir = 7;
+  string status = 2;
 }
 
-message TerminateExecutionRequest {
+// server requesting the agent to terminate a ssh tunnel
+message TunnelTerminationRequest {
+  string destinationHost = 1;
+  int32 destinationPort = 2;
+  string sourcePort = 3;
+}
+message TunnelTerminationResponse {
   string executionId = 1;
+  string status = 2;
 }
 
-message KillAgentRequest {
-  string reason = 1;
+message AgentMessage {
+  oneof message {
+    AgentPing agentPing = 1;
+    CreateAgentResponse createAgentResponse = 2;
+    TerminateAgentResponse terminateAgentResponse = 3;
+    EnvSetupResponse envSetupResponse = 4;
+    CommandExecutionResponse commandExecutionResponse = 5;
+    PythonExecutionResponse pythonExecutionResponse = 6;
+    JupyterExecutionResponse jupyterExecutionResponse = 7;
+    TunnelCreationResponse tunnelCreationResponse = 8;
+    TunnelTerminationResponse tunnelTerminationResponse = 9;
+  }
 }
 
 message ServerMessage {
   oneof message {
-    ContainerExecutionRequest containerExecutionRequest = 1;
-    CommandExecutionRequest commandExecutionRequest = 2;
-    TerminateExecutionRequest terminateExecutionRequest = 3;
-    KillAgentRequest killAgentRequest = 4;
-    TunnelCreationRequest tunnelCreationRequest = 5;
-    JupyterExecutionRequest jupyterExecutionRequest = 6;
-    PythonExecutionRequest pythonExecutionRequest = 7;
+    ShutdownRequest shutdownRequest = 1;
+    CreateAgentRequest createAgentRequest = 2;
+    TerminateAgentRequest terminateAgentRequest = 3;
+    EnvSetupRequest envSetupRequest = 4;
+    CommandExecutionRequest commandExecutionRequest = 5;
+    PythonExecutionRequest pythonExecutionRequest = 6;
+    JupyterExecutionRequest jupyterExecutionRequest = 7;
+    TunnelCreationRequest tunnelCreationRequest = 8;
+    TunnelTerminationRequest tunnelTerminationRequest = 9;
   }
 }
\ No newline at end of file