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

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


The following commit(s) were added to refs/heads/master by this push:
     new 25bfaa29ca Agent framework initial commit
25bfaa29ca is described below

commit 25bfaa29ca05dbfd12e9fc310c72eee377a5c1a4
Author: Dimuthu Wannipurage <[email protected]>
AuthorDate: Wed Jul 17 13:45:23 2024 -0400

    Agent framework initial commit
---
 modules/agent-framework/airavata-agent/.gitignore  |    2 +
 modules/agent-framework/airavata-agent/README.md   |   58 +
 .../airavata-agent/agent-communication.proto       |   94 ++
 modules/agent-framework/airavata-agent/agent.go    |  184 +++
 modules/agent-framework/airavata-agent/go.mod      |   16 +
 .../protos/agent-communication.pb.go               | 1355 ++++++++++++++++++++
 .../protos/agent-communication_grpc.pb.go          |  143 +++
 modules/agent-framework/connection-service/pom.xml |  118 ++
 .../service/ConnectionServiceApplication.java      |   11 +
 .../service/controllers/AgentController.java       |   47 +
 .../connection/service/handlers/AgentHandler.java  |  159 +++
 .../connection/service/models/AgentCommandAck.java |   22 +
 .../service/models/AgentCommandRequest.java        |   34 +
 .../service/models/AgentInfoResponse.java          |   27 +
 .../connection/service/models/AgentTunnelAck.java  |   22 +
 .../service/models/AgentTunnelCreationRequest.java |   67 +
 .../src/main/proto/agent-communication.proto       |   94 ++
 .../src/main/resources/application.yml             |    6 +
 modules/agent-framework/pom.xml                    |   25 +
 pom.xml                                            |    8 +-
 20 files changed, 2489 insertions(+), 3 deletions(-)

diff --git a/modules/agent-framework/airavata-agent/.gitignore 
b/modules/agent-framework/airavata-agent/.gitignore
new file mode 100644
index 0000000000..ea32156bf5
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/.gitignore
@@ -0,0 +1,2 @@
+airavata-agent
+go.sum
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-agent/README.md 
b/modules/agent-framework/airavata-agent/README.md
new file mode 100644
index 0000000000..53ca7f6809
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/README.md
@@ -0,0 +1,58 @@
+## The Agent for orchestrating Airavata job workloads
+
+## Set up the go environment
+```
+go mod tidy
+```
+
+## Building proto files
+
+```
+go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
+go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
+export PATH=$PATH:$HOME/go/bin
+protoc --go_out=. --go-grpc_out=. agent-communication.proto
+```
+
+## Running the agent
+```
+go install
+go run agent.go <connection_server_url> <agent_id>
+```
+
+## Build the agent
+
+### Build for the current platform
+```
+go build
+```
+
+### Build for a specific platform
+```
+env GOOS=linux GOARCH=amd64 go build
+```
+
+## Sample Requests
+
+
+```
+POST http://localhost:18880/api/v1/agent/execute
+
+{
+    "agentId": "agent1",
+    "workingDir": "",
+    "arguments": ["docker", "ps", "-a"]
+} 
+```
+```
+POST http://localhost:18880/api/v1/agent/tunnel
+
+{
+    "destinationHost": "32.241.33.22",
+    "destinationPort": "9999",
+    "sshUserName": "sshuser",
+    "sourcePort": "9001",
+    "sshKeyPath": "/Users/dwannipu/.ssh/id_rsa_unencrypted",
+    "processId": "process1"
+}
+```
diff --git a/modules/agent-framework/airavata-agent/agent-communication.proto 
b/modules/agent-framework/airavata-agent/agent-communication.proto
new file mode 100644
index 0000000000..0e54285ebd
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/agent-communication.proto
@@ -0,0 +1,94 @@
+syntax = "proto3";
+
+package org.apache.airavata.agent;
+
+option java_multiple_files = true;
+option java_package = "org.apache.airavata.agent";
+option java_outer_classname = "AgentCommunicationProto";
+option go_package = "protos/";
+
+service AgentCommunicationService {
+  rpc createMessageBus(stream AgentMessage) returns (stream ServerMessage);
+}
+
+message AgentPing {
+  string agentId = 1;
+}
+
+message CommandExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
+}
+
+message ContainerExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
+}
+
+message TerminateExecutionResponse {
+  string status = 1;
+  string description = 2;
+}
+
+message TunnelCreationResponse {
+  string status = 1;
+}
+
+message TunnelTerminationResponse {
+  string status = 1;
+}
+
+message AgentMessage {
+  oneof message {
+    AgentPing agentPing = 1;
+    CommandExecutionResponse commandExecutionResponse = 2;
+    ContainerExecutionResponse containerExecutionResponse = 3;
+    TerminateExecutionResponse terminateExecutionResponse = 4;
+  }
+}
+
+message ContainerExecutionRequest {
+  string executionId = 1;
+  string containerName = 2;
+  repeated string arguments = 3;
+  string mountPath = 4;
+}
+
+message TunnelCreationRequest {
+  string destinationHost = 1;
+  string destinationPort = 2;
+  string sshUserName = 3;
+  string sourcePort = 4;
+  string sshKeyPath = 5;
+  string password = 6;
+}
+
+message TunnelTerminationRequest {
+  string destinationHost = 1;
+  int32 destinationPort = 2;
+  string sourcePort = 3;
+}
+
+message CommandExecutionRequest {
+  string executionId = 1;
+  repeated string arguments = 2;
+  string workingDir = 3;
+}
+
+message TerminateExecutionRequest {
+  string executionId = 1;
+}
+
+message KillAgentRequest {
+  string reason = 1;
+}
+
+message ServerMessage {
+  oneof message {
+    ContainerExecutionRequest containerExecutionRequest = 1;
+    CommandExecutionRequest commandExecutionRequest = 2;
+    TerminateExecutionRequest terminateExecutionRequest = 3;
+    KillAgentRequest killAgentRequest = 4;
+    TunnelCreationRequest tunnelCreationRequest = 5;
+  }
+}
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-agent/agent.go 
b/modules/agent-framework/airavata-agent/agent.go
new file mode 100644
index 0000000000..bdefd0bf79
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/agent.go
@@ -0,0 +1,184 @@
+package main
+
+import (
+       "context"
+       "fmt"
+       "io"
+       "log"
+       "net"
+       "os"
+       "os/exec"
+
+       protos "airavata-agent/protos"
+
+       "golang.org/x/crypto/ssh"
+       "google.golang.org/grpc"
+)
+
+func main() {
+
+       args := os.Args[1:]
+       serverUrl := args[0]
+       agentId := args[1]
+       grpcStreamChannel := make(chan struct{})
+
+       conn, err := grpc.Dial(serverUrl, grpc.WithInsecure(), grpc.WithBlock())
+       if err != nil {
+               log.Fatalf("did not connect: %v", err)
+       }
+       defer conn.Close()
+
+       c := protos.NewAgentCommunicationServiceClient(conn)
+
+       stream, err := c.CreateMessageBus(context.Background())
+
+       if err != nil {
+               log.Fatalf("Error creating stream: %v", err)
+       }
+
+       log.Printf("Trying to connect to %s with agent id %s", serverUrl, 
agentId)
+
+       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...")
+       }
+
+       go func() {
+               for {
+                       in, err := stream.Recv()
+                       if err == io.EOF {
+                               close(grpcStreamChannel)
+                               return
+                       }
+                       if err != nil {
+                               log.Fatalf("Failed to receive a message : %v", 
err)
+                       }
+                       log.Printf("Received message %s", in.Message)
+                       switch x := in.GetMessage().(type) {
+                       case *protos.ServerMessage_CommandExecutionRequest:
+                               log.Printf("Recived a command execution 
request")
+                               executionId := 
x.CommandExecutionRequest.ExecutionId
+                               execArgs := x.CommandExecutionRequest.Arguments
+                               log.Printf("Execution id %s", executionId)
+                               cmd := exec.Command(execArgs[0], 
execArgs[1:]...)
+                               stdout, err := cmd.Output()
+                               if err != nil {
+                                       log.Fatalf(err.Error())
+                                       return
+                               }
+                               log.Printf("Execution output is %s", 
string(stdout))
+
+                       case *protos.ServerMessage_TunnelCreationRequest:
+                               log.Printf("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
+                               openRemoteTunnel(host, destPort, srcPort, 
sshUser, keyPath)
+                       }
+
+               }
+       }()
+
+       <-grpcStreamChannel
+
+       if err := stream.CloseSend(); err != nil {
+               log.Fatalf("failed to close the stream: %v", err)
+       }
+
+}
+
+func openRemoteTunnel(remoteHost string, remotePort string, localPort string, 
sshUser string, sshKeyFile string) {
+       // SSH server details
+       sshHost := remoteHost + ":22"
+       //sshPassword := "your_ssh_password"
+
+       // Remote and local ports
+       localHost := "localhost"
+
+       key, err := os.ReadFile(sshKeyFile)
+       if err != nil {
+               log.Fatalf("unable to read private key: %v", err)
+       }
+
+       // Create the Signer for this private key.
+       signer, err := ssh.ParsePrivateKey(key)
+       if err != nil {
+               log.Fatalf("unable to parse private key: %v", err)
+       }
+
+       // 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
+       }
+
+       // Connect to the SSH server
+       sshConn, err := ssh.Dial("tcp", sshHost, sshConfig)
+       if err != nil {
+               log.Fatalf("Failed to dial SSH: %s", err)
+       }
+       defer sshConn.Close()
+
+       // Listen on the remote port
+       remoteListener, err := sshConn.Listen("tcp", fmt.Sprintf("0.0.0.0:%s", 
remotePort))
+       if err != nil {
+               log.Fatalf("Failed to listen on remote port %s: %s", 
remotePort, err)
+       }
+       defer remoteListener.Close()
+
+       log.Printf("Reverse SSH tunnel established. Listening on remote port 
%s", remotePort)
+
+       for {
+               remoteConn, err := remoteListener.Accept()
+               if err != nil {
+                       log.Printf("Failed to accept remote connection: %s", 
err)
+                       continue
+               }
+
+               go handleConnection(remoteConn, localHost, localPort)
+       }
+}
+
+func handleConnection(remoteConn net.Conn, localHost, localPort string) {
+       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)
+               return
+       }
+       defer localConn.Close()
+
+       // Create channels to signal when copying is done
+       done := make(chan struct{})
+
+       // Start copying data between remote and local connections
+       go copyConn(remoteConn, localConn, done)
+       go copyConn(localConn, remoteConn, done)
+
+       // Wait for both copy operations to complete
+       <-done
+       <-done
+}
+
+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)
+               }
+       }
+}
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-agent/go.mod 
b/modules/agent-framework/airavata-agent/go.mod
new file mode 100644
index 0000000000..cf79988e72
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/go.mod
@@ -0,0 +1,16 @@
+module airavata-agent
+
+go 1.22.3
+
+require (
+       golang.org/x/crypto v0.24.0
+       google.golang.org/grpc v1.64.0
+)
+
+require (
+       golang.org/x/net v0.24.0 // indirect
+       golang.org/x/sys v0.21.0 // indirect
+       golang.org/x/text v0.16.0 // indirect
+       google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // 
indirect
+       google.golang.org/protobuf v1.34.2 // indirect
+)
diff --git 
a/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go 
b/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
new file mode 100644
index 0000000000..9212c8eb77
--- /dev/null
+++ b/modules/agent-framework/airavata-agent/protos/agent-communication.pb.go
@@ -0,0 +1,1355 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.34.2
+//     protoc        v4.24.4
+// source: agent-communication.proto
+
+package protos
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+       reflect "reflect"
+       sync "sync"
+)
+
+const (
+       // Verify that this generated code is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+       // Verify that runtime/protoimpl is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type AgentPing struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       AgentId string `protobuf:"bytes,1,opt,name=agentId,proto3" 
json:"agentId,omitempty"`
+}
+
+func (x *AgentPing) Reset() {
+       *x = AgentPing{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[0]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *AgentPing) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AgentPing) ProtoMessage() {}
+
+func (x *AgentPing) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[0]
+       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 AgentPing.ProtoReflect.Descriptor instead.
+func (*AgentPing) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *AgentPing) GetAgentId() string {
+       if x != nil {
+               return x.AgentId
+       }
+       return ""
+}
+
+type CommandExecutionResponse 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 *CommandExecutionResponse) Reset() {
+       *x = CommandExecutionResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[1]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *CommandExecutionResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandExecutionResponse) ProtoMessage() {}
+
+func (x *CommandExecutionResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[1]
+       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 CommandExecutionResponse.ProtoReflect.Descriptor instead.
+func (*CommandExecutionResponse) 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 {
+       if x != nil {
+               return x.ResponseString
+       }
+       return ""
+}
+
+type ContainerExecutionResponse 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 *ContainerExecutionResponse) Reset() {
+       *x = ContainerExecutionResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[2]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ContainerExecutionResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ContainerExecutionResponse) ProtoMessage() {}
+
+func (x *ContainerExecutionResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[2]
+       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 ContainerExecutionResponse.ProtoReflect.Descriptor instead.
+func (*ContainerExecutionResponse) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ContainerExecutionResponse) GetExecutionId() string {
+       if x != nil {
+               return x.ExecutionId
+       }
+       return ""
+}
+
+func (x *ContainerExecutionResponse) GetResponseString() string {
+       if x != nil {
+               return x.ResponseString
+       }
+       return ""
+}
+
+type TerminateExecutionResponse 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"`
+}
+
+func (x *TerminateExecutionResponse) Reset() {
+       *x = TerminateExecutionResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[3]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TerminateExecutionResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TerminateExecutionResponse) ProtoMessage() {}
+
+func (x *TerminateExecutionResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[3]
+       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 TerminateExecutionResponse.ProtoReflect.Descriptor instead.
+func (*TerminateExecutionResponse) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *TerminateExecutionResponse) GetStatus() string {
+       if x != nil {
+               return x.Status
+       }
+       return ""
+}
+
+func (x *TerminateExecutionResponse) GetDescription() string {
+       if x != nil {
+               return x.Description
+       }
+       return ""
+}
+
+type TunnelCreationResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Status string `protobuf:"bytes,1,opt,name=status,proto3" 
json:"status,omitempty"`
+}
+
+func (x *TunnelCreationResponse) Reset() {
+       *x = TunnelCreationResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[4]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TunnelCreationResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TunnelCreationResponse) ProtoMessage() {}
+
+func (x *TunnelCreationResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[4]
+       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 TunnelCreationResponse.ProtoReflect.Descriptor instead.
+func (*TunnelCreationResponse) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *TunnelCreationResponse) GetStatus() string {
+       if x != nil {
+               return x.Status
+       }
+       return ""
+}
+
+type TunnelTerminationResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Status string `protobuf:"bytes,1,opt,name=status,proto3" 
json:"status,omitempty"`
+}
+
+func (x *TunnelTerminationResponse) Reset() {
+       *x = TunnelTerminationResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[5]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TunnelTerminationResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TunnelTerminationResponse) ProtoMessage() {}
+
+func (x *TunnelTerminationResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[5]
+       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 TunnelTerminationResponse.ProtoReflect.Descriptor instead.
+func (*TunnelTerminationResponse) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *TunnelTerminationResponse) GetStatus() string {
+       if x != nil {
+               return x.Status
+       }
+       return ""
+}
+
+type AgentMessage struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Types that are assignable to Message:
+       //
+       //      *AgentMessage_AgentPing
+       //      *AgentMessage_CommandExecutionResponse
+       //      *AgentMessage_ContainerExecutionResponse
+       //      *AgentMessage_TerminateExecutionResponse
+       Message isAgentMessage_Message `protobuf_oneof:"message"`
+}
+
+func (x *AgentMessage) Reset() {
+       *x = AgentMessage{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[6]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *AgentMessage) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AgentMessage) ProtoMessage() {}
+
+func (x *AgentMessage) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[6]
+       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 AgentMessage.ProtoReflect.Descriptor instead.
+func (*AgentMessage) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{6}
+}
+
+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
+       }
+       return nil
+}
+
+func (x *AgentMessage) GetTerminateExecutionResponse() 
*TerminateExecutionResponse {
+       if x, ok := x.GetMessage().(*AgentMessage_TerminateExecutionResponse); 
ok {
+               return x.TerminateExecutionResponse
+       }
+       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"`
+}
+
+func (*AgentMessage_AgentPing) isAgentMessage_Message() {}
+
+func (*AgentMessage_CommandExecutionResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_ContainerExecutionResponse) isAgentMessage_Message() {}
+
+func (*AgentMessage_TerminateExecutionResponse) isAgentMessage_Message() {}
+
+type ContainerExecutionRequest 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"`
+}
+
+func (x *ContainerExecutionRequest) Reset() {
+       *x = ContainerExecutionRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[7]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ContainerExecutionRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ContainerExecutionRequest) ProtoMessage() {}
+
+func (x *ContainerExecutionRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[7]
+       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 ContainerExecutionRequest.ProtoReflect.Descriptor instead.
+func (*ContainerExecutionRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ContainerExecutionRequest) 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 {
+       if x != nil {
+               return x.MountPath
+       }
+       return ""
+}
+
+type TunnelCreationRequest 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"`
+}
+
+func (x *TunnelCreationRequest) Reset() {
+       *x = TunnelCreationRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[8]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TunnelCreationRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TunnelCreationRequest) ProtoMessage() {}
+
+func (x *TunnelCreationRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[8]
+       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 TunnelCreationRequest.ProtoReflect.Descriptor instead.
+func (*TunnelCreationRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *TunnelCreationRequest) GetDestinationHost() string {
+       if x != nil {
+               return x.DestinationHost
+       }
+       return ""
+}
+
+func (x *TunnelCreationRequest) GetDestinationPort() string {
+       if x != nil {
+               return x.DestinationPort
+       }
+       return ""
+}
+
+func (x *TunnelCreationRequest) GetSshUserName() string {
+       if x != nil {
+               return x.SshUserName
+       }
+       return ""
+}
+
+func (x *TunnelCreationRequest) GetSourcePort() string {
+       if x != nil {
+               return x.SourcePort
+       }
+       return ""
+}
+
+func (x *TunnelCreationRequest) GetSshKeyPath() string {
+       if x != nil {
+               return x.SshKeyPath
+       }
+       return ""
+}
+
+func (x *TunnelCreationRequest) GetPassword() string {
+       if x != nil {
+               return x.Password
+       }
+       return ""
+}
+
+type TunnelTerminationRequest 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"`
+}
+
+func (x *TunnelTerminationRequest) Reset() {
+       *x = TunnelTerminationRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[9]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TunnelTerminationRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TunnelTerminationRequest) ProtoMessage() {}
+
+func (x *TunnelTerminationRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_agent_communication_proto_msgTypes[9]
+       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 TunnelTerminationRequest.ProtoReflect.Descriptor instead.
+func (*TunnelTerminationRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *TunnelTerminationRequest) GetDestinationHost() string {
+       if x != nil {
+               return x.DestinationHost
+       }
+       return ""
+}
+
+func (x *TunnelTerminationRequest) GetDestinationPort() int32 {
+       if x != nil {
+               return x.DestinationPort
+       }
+       return 0
+}
+
+func (x *TunnelTerminationRequest) GetSourcePort() string {
+       if x != nil {
+               return x.SourcePort
+       }
+       return ""
+}
+
+type CommandExecutionRequest 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"`
+}
+
+func (x *CommandExecutionRequest) Reset() {
+       *x = CommandExecutionRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[10]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *CommandExecutionRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandExecutionRequest) ProtoMessage() {}
+
+func (x *CommandExecutionRequest) 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 CommandExecutionRequest.ProtoReflect.Descriptor instead.
+func (*CommandExecutionRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *CommandExecutionRequest) GetExecutionId() string {
+       if x != nil {
+               return x.ExecutionId
+       }
+       return ""
+}
+
+func (x *CommandExecutionRequest) GetArguments() []string {
+       if x != nil {
+               return x.Arguments
+       }
+       return nil
+}
+
+func (x *CommandExecutionRequest) GetWorkingDir() string {
+       if x != nil {
+               return x.WorkingDir
+       }
+       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"`
+}
+
+func (x *TerminateExecutionRequest) Reset() {
+       *x = TerminateExecutionRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[11]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *TerminateExecutionRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TerminateExecutionRequest) ProtoMessage() {}
+
+func (x *TerminateExecutionRequest) 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 TerminateExecutionRequest.ProtoReflect.Descriptor instead.
+func (*TerminateExecutionRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *TerminateExecutionRequest) GetExecutionId() string {
+       if x != nil {
+               return x.ExecutionId
+       }
+       return ""
+}
+
+type KillAgentRequest struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Reason string `protobuf:"bytes,1,opt,name=reason,proto3" 
json:"reason,omitempty"`
+}
+
+func (x *KillAgentRequest) Reset() {
+       *x = KillAgentRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[12]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *KillAgentRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KillAgentRequest) ProtoMessage() {}
+
+func (x *KillAgentRequest) 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 KillAgentRequest.ProtoReflect.Descriptor instead.
+func (*KillAgentRequest) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *KillAgentRequest) GetReason() string {
+       if x != nil {
+               return x.Reason
+       }
+       return ""
+}
+
+type ServerMessage struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Types that are assignable to Message:
+       //
+       //      *ServerMessage_ContainerExecutionRequest
+       //      *ServerMessage_CommandExecutionRequest
+       //      *ServerMessage_TerminateExecutionRequest
+       //      *ServerMessage_KillAgentRequest
+       //      *ServerMessage_TunnelCreationRequest
+       Message isServerMessage_Message `protobuf_oneof:"message"`
+}
+
+func (x *ServerMessage) Reset() {
+       *x = ServerMessage{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_agent_communication_proto_msgTypes[13]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ServerMessage) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerMessage) ProtoMessage() {}
+
+func (x *ServerMessage) 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 ServerMessage.ProtoReflect.Descriptor instead.
+func (*ServerMessage) Descriptor() ([]byte, []int) {
+       return file_agent_communication_proto_rawDescGZIP(), []int{13}
+}
+
+func (m *ServerMessage) GetMessage() isServerMessage_Message {
+       if m != nil {
+               return m.Message
+       }
+       return nil
+}
+
+func (x *ServerMessage) GetContainerExecutionRequest() 
*ContainerExecutionRequest {
+       if x, ok := x.GetMessage().(*ServerMessage_ContainerExecutionRequest); 
ok {
+               return x.ContainerExecutionRequest
+       }
+       return nil
+}
+
+func (x *ServerMessage) GetCommandExecutionRequest() *CommandExecutionRequest {
+       if x, ok := x.GetMessage().(*ServerMessage_CommandExecutionRequest); ok 
{
+               return x.CommandExecutionRequest
+       }
+       return nil
+}
+
+func (x *ServerMessage) GetTerminateExecutionRequest() 
*TerminateExecutionRequest {
+       if x, ok := x.GetMessage().(*ServerMessage_TerminateExecutionRequest); 
ok {
+               return x.TerminateExecutionRequest
+       }
+       return nil
+}
+
+func (x *ServerMessage) GetKillAgentRequest() *KillAgentRequest {
+       if x, ok := x.GetMessage().(*ServerMessage_KillAgentRequest); ok {
+               return x.KillAgentRequest
+       }
+       return nil
+}
+
+func (x *ServerMessage) GetTunnelCreationRequest() *TunnelCreationRequest {
+       if x, ok := x.GetMessage().(*ServerMessage_TunnelCreationRequest); ok {
+               return x.TunnelCreationRequest
+       }
+       return nil
+}
+
+type isServerMessage_Message interface {
+       isServerMessage_Message()
+}
+
+type ServerMessage_ContainerExecutionRequest struct {
+       ContainerExecutionRequest *ContainerExecutionRequest 
`protobuf:"bytes,1,opt,name=containerExecutionRequest,proto3,oneof"`
+}
+
+type ServerMessage_CommandExecutionRequest struct {
+       CommandExecutionRequest *CommandExecutionRequest 
`protobuf:"bytes,2,opt,name=commandExecutionRequest,proto3,oneof"`
+}
+
+type ServerMessage_TerminateExecutionRequest struct {
+       TerminateExecutionRequest *TerminateExecutionRequest 
`protobuf:"bytes,3,opt,name=terminateExecutionRequest,proto3,oneof"`
+}
+
+type ServerMessage_KillAgentRequest struct {
+       KillAgentRequest *KillAgentRequest 
`protobuf:"bytes,4,opt,name=killAgentRequest,proto3,oneof"`
+}
+
+type ServerMessage_TunnelCreationRequest struct {
+       TunnelCreationRequest *TunnelCreationRequest 
`protobuf:"bytes,5,opt,name=tunnelCreationRequest,proto3,oneof"`
+}
+
+func (*ServerMessage_ContainerExecutionRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_CommandExecutionRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_TerminateExecutionRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_KillAgentRequest) isServerMessage_Message() {}
+
+func (*ServerMessage_TunnelCreationRequest) isServerMessage_Message() {}
+
+var File_agent_communication_proto protoreflect.FileDescriptor
+
+var file_agent_communication_proto_rawDesc = []byte{
+       0x0a, 0x19, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 
0x75, 0x6e, 0x69, 0x63,
+       0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 
0x19, 0x6f, 0x72, 0x67,
+       0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 
0x76, 0x61, 0x74, 0x61,
+       0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x22, 0x25, 0x0a, 0x09, 0x41, 0x67, 
0x65, 0x6e, 0x74, 0x50,
+       0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 
0x49, 0x64, 0x18, 0x01,
+       0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 
0x64, 0x22, 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,
+       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, 
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, 0xc4, 
0x03, 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, 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, 
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, 0xbb, 0x04, 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, 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, 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, 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, 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, 0x42, 0x09, 0x0a, 
0x07, 0x6d, 0x65, 0x73,
+       0x73, 0x61, 0x67, 0x65, 0x32, 0x86, 0x01, 0x0a, 0x19, 0x41, 0x67, 0x65, 
0x6e, 0x74, 0x43, 0x6f,
+       0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 
0x65, 0x72, 0x76, 0x69,
+       0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 
0x4d, 0x65, 0x73, 0x73,
+       0x61, 0x67, 0x65, 0x42, 0x75, 0x73, 0x12, 0x27, 0x2e, 0x6f, 0x72, 0x67, 
0x2e, 0x61, 0x70, 0x61,
+       0x63, 0x68, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x61, 0x76, 0x61, 0x74, 0x61, 
0x2e, 0x61, 0x67, 0x65,
+       0x6e, 0x74, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 
0x61, 0x67, 0x65, 0x1a,
+       0x28, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 
0x2e, 0x61, 0x69, 0x72,
+       0x61, 0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 
0x53, 0x65, 0x72, 0x76,
+       0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 
0x01, 0x42, 0x3f, 0x0a,
+       0x19, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 
0x61, 0x69, 0x72, 0x61,
+       0x76, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x42, 0x17, 
0x41, 0x67, 0x65, 0x6e,
+       0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 
0x6f, 0x6e, 0x50, 0x72,
+       0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x07, 0x70, 0x72, 0x6f, 0x74, 0x6f, 
0x73, 0x2f, 0x62, 0x06,
+       0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+       file_agent_communication_proto_rawDescOnce sync.Once
+       file_agent_communication_proto_rawDescData = 
file_agent_communication_proto_rawDesc
+)
+
+func file_agent_communication_proto_rawDescGZIP() []byte {
+       file_agent_communication_proto_rawDescOnce.Do(func() {
+               file_agent_communication_proto_rawDescData = 
protoimpl.X.CompressGZIP(file_agent_communication_proto_rawDescData)
+       })
+       return file_agent_communication_proto_rawDescData
+}
+
+var file_agent_communication_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
+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
+       (*TerminateExecutionResponse)(nil), // 3: 
org.apache.airavata.agent.TerminateExecutionResponse
+       (*TunnelCreationResponse)(nil),     // 4: 
org.apache.airavata.agent.TunnelCreationResponse
+       (*TunnelTerminationResponse)(nil),  // 5: 
org.apache.airavata.agent.TunnelTerminationResponse
+       (*AgentMessage)(nil),               // 6: 
org.apache.airavata.agent.AgentMessage
+       (*ContainerExecutionRequest)(nil),  // 7: 
org.apache.airavata.agent.ContainerExecutionRequest
+       (*TunnelCreationRequest)(nil),      // 8: 
org.apache.airavata.agent.TunnelCreationRequest
+       (*TunnelTerminationRequest)(nil),   // 9: 
org.apache.airavata.agent.TunnelTerminationRequest
+       (*CommandExecutionRequest)(nil),    // 10: 
org.apache.airavata.agent.CommandExecutionRequest
+       (*TerminateExecutionRequest)(nil),  // 11: 
org.apache.airavata.agent.TerminateExecutionRequest
+       (*KillAgentRequest)(nil),           // 12: 
org.apache.airavata.agent.KillAgentRequest
+       (*ServerMessage)(nil),              // 13: 
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
+       3,  // 3: 
org.apache.airavata.agent.AgentMessage.terminateExecutionResponse:type_name -> 
org.apache.airavata.agent.TerminateExecutionResponse
+       7,  // 4: 
org.apache.airavata.agent.ServerMessage.containerExecutionRequest:type_name -> 
org.apache.airavata.agent.ContainerExecutionRequest
+       10, // 5: 
org.apache.airavata.agent.ServerMessage.commandExecutionRequest:type_name -> 
org.apache.airavata.agent.CommandExecutionRequest
+       11, // 6: 
org.apache.airavata.agent.ServerMessage.terminateExecutionRequest:type_name -> 
org.apache.airavata.agent.TerminateExecutionRequest
+       12, // 7: 
org.apache.airavata.agent.ServerMessage.killAgentRequest:type_name -> 
org.apache.airavata.agent.KillAgentRequest
+       8,  // 8: 
org.apache.airavata.agent.ServerMessage.tunnelCreationRequest:type_name -> 
org.apache.airavata.agent.TunnelCreationRequest
+       6,  // 9: 
org.apache.airavata.agent.AgentCommunicationService.createMessageBus:input_type 
-> org.apache.airavata.agent.AgentMessage
+       13, // 10: 
org.apache.airavata.agent.AgentCommunicationService.createMessageBus:output_type
 -> org.apache.airavata.agent.ServerMessage
+       10, // [10:11] is the sub-list for method output_type
+       9,  // [9:10] is the sub-list for method input_type
+       9,  // [9:9] is the sub-list for extension type_name
+       9,  // [9:9] is the sub-list for extension extendee
+       0,  // [0:9] is the sub-list for field type_name
+}
+
+func init() { file_agent_communication_proto_init() }
+func file_agent_communication_proto_init() {
+       if File_agent_communication_proto != nil {
+               return
+       }
+       if !protoimpl.UnsafeEnabled {
+               file_agent_communication_proto_msgTypes[0].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*AgentPing); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[1].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*CommandExecutionResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[2].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*ContainerExecutionResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[3].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*TerminateExecutionResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[4].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*TunnelCreationResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[5].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[6].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[7].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*ContainerExecutionRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[8].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*TunnelCreationRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[9].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*TunnelTerminationRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[10].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*CommandExecutionRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[11].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*TerminateExecutionRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[12].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*KillAgentRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_agent_communication_proto_msgTypes[13].Exporter = func(v 
any, i int) any {
+                       switch v := v.(*ServerMessage); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+       }
+       file_agent_communication_proto_msgTypes[6].OneofWrappers = []any{
+               (*AgentMessage_AgentPing)(nil),
+               (*AgentMessage_CommandExecutionResponse)(nil),
+               (*AgentMessage_ContainerExecutionResponse)(nil),
+               (*AgentMessage_TerminateExecutionResponse)(nil),
+       }
+       file_agent_communication_proto_msgTypes[13].OneofWrappers = []any{
+               (*ServerMessage_ContainerExecutionRequest)(nil),
+               (*ServerMessage_CommandExecutionRequest)(nil),
+               (*ServerMessage_TerminateExecutionRequest)(nil),
+               (*ServerMessage_KillAgentRequest)(nil),
+               (*ServerMessage_TunnelCreationRequest)(nil),
+       }
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: file_agent_communication_proto_rawDesc,
+                       NumEnums:      0,
+                       NumMessages:   14,
+                       NumExtensions: 0,
+                       NumServices:   1,
+               },
+               GoTypes:           file_agent_communication_proto_goTypes,
+               DependencyIndexes: file_agent_communication_proto_depIdxs,
+               MessageInfos:      file_agent_communication_proto_msgTypes,
+       }.Build()
+       File_agent_communication_proto = out.File
+       file_agent_communication_proto_rawDesc = nil
+       file_agent_communication_proto_goTypes = nil
+       file_agent_communication_proto_depIdxs = nil
+}
diff --git 
a/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go 
b/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go
new file mode 100644
index 0000000000..d32e4d18eb
--- /dev/null
+++ 
b/modules/agent-framework/airavata-agent/protos/agent-communication_grpc.pb.go
@@ -0,0 +1,143 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.4.0
+// - protoc             v4.24.4
+// source: agent-communication.proto
+
+package protos
+
+import (
+       context "context"
+       grpc "google.golang.org/grpc"
+       codes "google.golang.org/grpc/codes"
+       status "google.golang.org/grpc/status"
+)
+
+// 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
+
+const (
+       AgentCommunicationService_CreateMessageBus_FullMethodName = 
"/org.apache.airavata.agent.AgentCommunicationService/createMessageBus"
+)
+
+// AgentCommunicationServiceClient is the client API for 
AgentCommunicationService service.
+//
+// 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)
+}
+
+type agentCommunicationServiceClient struct {
+       cc grpc.ClientConnInterface
+}
+
+func NewAgentCommunicationServiceClient(cc grpc.ClientConnInterface) 
AgentCommunicationServiceClient {
+       return &agentCommunicationServiceClient{cc}
+}
+
+func (c *agentCommunicationServiceClient) CreateMessageBus(ctx 
context.Context, opts ...grpc.CallOption) 
(AgentCommunicationService_CreateMessageBusClient, 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}
+       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
+}
+
+// AgentCommunicationServiceServer is the server API for 
AgentCommunicationService service.
+// All implementations must embed UnimplementedAgentCommunicationServiceServer
+// for forward compatibility
+type AgentCommunicationServiceServer interface {
+       CreateMessageBus(AgentCommunicationService_CreateMessageBusServer) error
+       mustEmbedUnimplementedAgentCommunicationServiceServer()
+}
+
+// UnimplementedAgentCommunicationServiceServer must be embedded to have 
forward compatible implementations.
+type UnimplementedAgentCommunicationServiceServer struct {
+}
+
+func (UnimplementedAgentCommunicationServiceServer) 
CreateMessageBus(AgentCommunicationService_CreateMessageBusServer) error {
+       return status.Errorf(codes.Unimplemented, "method CreateMessageBus not 
implemented")
+}
+func (UnimplementedAgentCommunicationServiceServer) 
mustEmbedUnimplementedAgentCommunicationServiceServer() {
+}
+
+// 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
+// result in compilation errors.
+type UnsafeAgentCommunicationServiceServer interface {
+       mustEmbedUnimplementedAgentCommunicationServiceServer()
+}
+
+func RegisterAgentCommunicationServiceServer(s grpc.ServiceRegistrar, srv 
AgentCommunicationServiceServer) {
+       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
+}
+
+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
+}
+
+// AgentCommunicationService_ServiceDesc is the grpc.ServiceDesc for 
AgentCommunicationService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var AgentCommunicationService_ServiceDesc = grpc.ServiceDesc{
+       ServiceName: "org.apache.airavata.agent.AgentCommunicationService",
+       HandlerType: (*AgentCommunicationServiceServer)(nil),
+       Methods:     []grpc.MethodDesc{},
+       Streams: []grpc.StreamDesc{
+               {
+                       StreamName:    "createMessageBus",
+                       Handler:       
_AgentCommunicationService_CreateMessageBus_Handler,
+                       ServerStreams: true,
+                       ClientStreams: true,
+               },
+       },
+       Metadata: "agent-communication.proto",
+}
diff --git a/modules/agent-framework/connection-service/pom.xml 
b/modules/agent-framework/connection-service/pom.xml
new file mode 100644
index 0000000000..25ece1a8e2
--- /dev/null
+++ b/modules/agent-framework/connection-service/pom.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.airavata</groupId>
+        <artifactId>agent-framework</artifactId>
+        <version>0.21-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>connection-service</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <spring.boot.version>3.2.4</spring.boot.version>
+        <jul-to-slf4j.version>1.7.0</jul-to-slf4j.version>
+        <json.version>20240303</json.version>
+        <javax.version>2.0.1.Final</javax.version>
+        <apache.commons.lang3.version>3.14.0</apache.commons.lang3.version>
+        <mysql.connector.java>8.0.31</mysql.connector.java>
+        <protobuf.version>3.23.4</protobuf.version>
+        <protobuf-plugin.version>0.6.1</protobuf-plugin.version>
+        <grpc.version>1.63.0</grpc.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring.boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-to-slf4j</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-stub</artifactId>
+            <version>${grpc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-protobuf</artifactId>
+            <version>${grpc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>net.devh</groupId>
+            <artifactId>grpc-server-spring-boot-starter</artifactId>
+            <version>3.0.0.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+            <version>${javax.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <extensions>
+            <extension>
+                <groupId>kr.motd.maven</groupId>
+                <artifactId>os-maven-plugin</artifactId>
+                <version>1.7.0</version>
+            </extension>
+        </extensions>
+
+        <plugins>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>${protobuf-plugin.version}</version>
+                <configuration>
+                    
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
+                    <pluginId>grpc-java</pluginId>
+                    
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>compile-custom</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>14</source>
+                    <target>14</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/ConnectionServiceApplication.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/ConnectionServiceApplication.java
new file mode 100644
index 0000000000..b76217a554
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/ConnectionServiceApplication.java
@@ -0,0 +1,11 @@
+package org.apache.airavata.agent.connection.service;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ConnectionServiceApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(ConnectionServiceApplication.class, args);
+    }
+}
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
new file mode 100644
index 0000000000..61ef791a60
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/AgentController.java
@@ -0,0 +1,47 @@
+package org.apache.airavata.agent.connection.service.controllers;
+
+import org.apache.airavata.agent.connection.service.handlers.AgentHandler;
+import org.apache.airavata.agent.connection.service.models.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+
+@RestController
+@RequestMapping("/api/v1/agent")
+public class AgentController {
+
+    private final static Logger logger = 
LoggerFactory.getLogger(AgentController.class);
+
+    private AgentHandler agentHandler;
+
+    public AgentController(AgentHandler agentHandler) {
+        this.agentHandler = agentHandler;
+    }
+
+    @GetMapping("/{agentId}")
+    public ResponseEntity<AgentInfoResponse> 
getAgentInfo(@PathVariable("agentId") String agentId) {
+        return ResponseEntity.accepted().body(agentHandler.isAgentUp(agentId));
+    }
+
+    @PostMapping("/tunnel")
+    public ResponseEntity<AgentTunnelAck> runTunnelCreationOnAgent(@Valid 
@RequestBody AgentTunnelCreationRequest tunnelRequest) {
+        return 
ResponseEntity.accepted().body(agentHandler.runTunnelOnAgent(tunnelRequest));
+    }
+    @PostMapping("/execute")
+    public ResponseEntity<AgentCommandAck> runCommandOnAgent(@Valid 
@RequestBody AgentCommandRequest commandRequest) {
+        logger.info("Received command request to run on agent {}", 
commandRequest.getAgentId());
+        if (agentHandler.isAgentUp(commandRequest.getAgentId()).isAgentUp()) {
+            return 
ResponseEntity.accepted().body(agentHandler.runCommandOnAgent(commandRequest));
+        } else {
+            logger.warn("No agent is available to run on agent {}", 
commandRequest.getAgentId());
+            AgentCommandAck ack = new AgentCommandAck();
+            ack.setError("Agent not found");
+            return ResponseEntity.accepted().body(ack);
+        }
+    }
+
+}
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentHandler.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentHandler.java
new file mode 100644
index 0000000000..7c34dff2fa
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentHandler.java
@@ -0,0 +1,159 @@
+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.connection.service.models.*;
+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;
+
+
+@GrpcService
+public class AgentHandler extends 
AgentCommunicationServiceGrpc.AgentCommunicationServiceImplBase {
+
+    private final static Logger logger = 
LoggerFactory.getLogger(AgentHandler.class);
+
+    // <streamId, StreamObserver>
+    private final Map<String, StreamObserver<ServerMessage>> ACTIVE_STREAMS = 
new ConcurrentHashMap<>();
+
+    // <agentId, streamId>
+    private final Map<String, String> AGENT_STREAM_MAPPING = new 
ConcurrentHashMap<>();
+
+    public AgentInfoResponse isAgentUp(String 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 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 AgentCommandAck runCommandOnAgent(AgentCommandRequest 
commandRequest) {
+
+        String executionId = UUID.randomUUID().toString();
+        AgentCommandAck ack = new AgentCommandAck();
+        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);
+
+            try {
+                logger.info("Running a command on agent {}", 
commandRequest.getAgentId());
+                
streamObserver.onNext(ServerMessage.newBuilder().setCommandExecutionRequest(
+                        CommandExecutionRequest.newBuilder()
+                                .setExecutionId(executionId)
+                                .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 {
+            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;
+    }
+
+    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) {
+
+    }
+
+    private void handleContainerExecutionResponse (ContainerExecutionResponse 
containerExecutionResponse) {
+
+    }
+
+    private void handleAgentTerminationResponse (TerminateExecutionResponse 
terminateExecutionResponse) {
+
+    }
+
+    private String generateStreamId() {
+        // Generate a unique ID for each stream
+        return java.util.UUID.randomUUID().toString();
+    }
+    @Override
+    public StreamObserver<AgentMessage> 
createMessageBus(StreamObserver<ServerMessage> responseObserver) {
+
+        String streamId = generateStreamId();
+        ACTIVE_STREAMS.put(streamId, responseObserver);
+
+        return new StreamObserver<AgentMessage>() {
+            @Override
+            public void onNext(AgentMessage request) {
+
+                switch (request.getMessageCase()) {
+                    case AGENTPING -> {
+                        handleAgentPing(request.getAgentPing(), streamId);
+                    }
+                    case COMMANDEXECUTIONRESPONSE -> {
+                        
handleCommandExecutionResponse(request.getCommandExecutionResponse());
+                    }
+                    case CONTAINEREXECUTIONRESPONSE -> {
+                        
handleContainerExecutionResponse(request.getContainerExecutionResponse());
+                    }
+                    case TERMINATEEXECUTIONRESPONSE -> {
+                        
handleAgentTerminationResponse(request.getTerminateExecutionResponse());
+                    }
+                }
+            }
+
+            @Override
+            public void onError(Throwable t) {
+                logger.warn("Error in processing stream {}. Removing the 
stream tracking from cache", streamId, t);
+                ACTIVE_STREAMS.remove(streamId);
+            }
+
+            @Override
+            public void onCompleted() {
+                logger.info("Stream {} is completed", streamId);
+                responseObserver.onCompleted();
+                ACTIVE_STREAMS.remove(streamId);
+            }
+        };
+    }
+}
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
new file mode 100644
index 0000000000..ad1e2843db
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandAck.java
@@ -0,0 +1,22 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentCommandAck {
+    private String executionId;
+    private String error;
+
+    public String getExecutionId() {
+        return executionId;
+    }
+
+    public void setExecutionId(String executionId) {
+        this.executionId = executionId;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+}
\ No newline at end of file
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java
new file mode 100644
index 0000000000..4e90e5f0f0
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentCommandRequest.java
@@ -0,0 +1,34 @@
+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;
+    private String agentId;
+
+    public List<String> getArguments() {
+        return arguments;
+    }
+
+    public void setArguments(List<String> arguments) {
+        this.arguments = arguments;
+    }
+
+    public String getWorkingDir() {
+        return workingDir;
+    }
+
+    public void setWorkingDir(String workingDir) {
+        this.workingDir = workingDir;
+    }
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+}
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentInfoResponse.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentInfoResponse.java
new file mode 100644
index 0000000000..e367ef8a18
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentInfoResponse.java
@@ -0,0 +1,27 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentInfoResponse {
+    private String agentId;
+    private boolean isAgentUp;
+
+    public AgentInfoResponse(String agentId, boolean isAgentUp) {
+        this.agentId = agentId;
+        this.isAgentUp = isAgentUp;
+    }
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+    public boolean isAgentUp() {
+        return isAgentUp;
+    }
+
+    public void setAgentUp(boolean agentUp) {
+        isAgentUp = agentUp;
+    }
+}
\ No newline at end of file
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelAck.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelAck.java
new file mode 100644
index 0000000000..8641512ba9
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelAck.java
@@ -0,0 +1,22 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentTunnelAck {
+    private int status;
+    private String error;
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+}
diff --git 
a/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java
 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java
new file mode 100644
index 0000000000..71c954fc00
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/java/org/apache/airavata/agent/connection/service/models/AgentTunnelCreationRequest.java
@@ -0,0 +1,67 @@
+package org.apache.airavata.agent.connection.service.models;
+
+public class AgentTunnelCreationRequest {
+    private String agentId;
+    private String destinationHost;
+    private String destinationPort;
+    private String sshUserName;
+    private String sourcePort;
+    private String sshKeyPath;
+    private String password;
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+    public String getDestinationHost() {
+        return destinationHost;
+    }
+
+    public void setDestinationHost(String destinationHost) {
+        this.destinationHost = destinationHost;
+    }
+
+    public String getDestinationPort() {
+        return destinationPort;
+    }
+
+    public void setDestinationPort(String destinationPort) {
+        this.destinationPort = destinationPort;
+    }
+
+    public String getSshUserName() {
+        return sshUserName;
+    }
+
+    public void setSshUserName(String sshUserName) {
+        this.sshUserName = sshUserName;
+    }
+
+    public String getSourcePort() {
+        return sourcePort;
+    }
+
+    public void setSourcePort(String sourcePort) {
+        this.sourcePort = sourcePort;
+    }
+
+    public String getSshKeyPath() {
+        return sshKeyPath;
+    }
+
+    public void setSshKeyPath(String sshKeyPath) {
+        this.sshKeyPath = sshKeyPath;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}
\ No newline at end of file
diff --git 
a/modules/agent-framework/connection-service/src/main/proto/agent-communication.proto
 
b/modules/agent-framework/connection-service/src/main/proto/agent-communication.proto
new file mode 100644
index 0000000000..0e54285ebd
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/proto/agent-communication.proto
@@ -0,0 +1,94 @@
+syntax = "proto3";
+
+package org.apache.airavata.agent;
+
+option java_multiple_files = true;
+option java_package = "org.apache.airavata.agent";
+option java_outer_classname = "AgentCommunicationProto";
+option go_package = "protos/";
+
+service AgentCommunicationService {
+  rpc createMessageBus(stream AgentMessage) returns (stream ServerMessage);
+}
+
+message AgentPing {
+  string agentId = 1;
+}
+
+message CommandExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
+}
+
+message ContainerExecutionResponse {
+  string executionId = 1;
+  string responseString = 2;
+}
+
+message TerminateExecutionResponse {
+  string status = 1;
+  string description = 2;
+}
+
+message TunnelCreationResponse {
+  string status = 1;
+}
+
+message TunnelTerminationResponse {
+  string status = 1;
+}
+
+message AgentMessage {
+  oneof message {
+    AgentPing agentPing = 1;
+    CommandExecutionResponse commandExecutionResponse = 2;
+    ContainerExecutionResponse containerExecutionResponse = 3;
+    TerminateExecutionResponse terminateExecutionResponse = 4;
+  }
+}
+
+message ContainerExecutionRequest {
+  string executionId = 1;
+  string containerName = 2;
+  repeated string arguments = 3;
+  string mountPath = 4;
+}
+
+message TunnelCreationRequest {
+  string destinationHost = 1;
+  string destinationPort = 2;
+  string sshUserName = 3;
+  string sourcePort = 4;
+  string sshKeyPath = 5;
+  string password = 6;
+}
+
+message TunnelTerminationRequest {
+  string destinationHost = 1;
+  int32 destinationPort = 2;
+  string sourcePort = 3;
+}
+
+message CommandExecutionRequest {
+  string executionId = 1;
+  repeated string arguments = 2;
+  string workingDir = 3;
+}
+
+message TerminateExecutionRequest {
+  string executionId = 1;
+}
+
+message KillAgentRequest {
+  string reason = 1;
+}
+
+message ServerMessage {
+  oneof message {
+    ContainerExecutionRequest containerExecutionRequest = 1;
+    CommandExecutionRequest commandExecutionRequest = 2;
+    TerminateExecutionRequest terminateExecutionRequest = 3;
+    KillAgentRequest killAgentRequest = 4;
+    TunnelCreationRequest tunnelCreationRequest = 5;
+  }
+}
\ No newline at end of file
diff --git 
a/modules/agent-framework/connection-service/src/main/resources/application.yml 
b/modules/agent-framework/connection-service/src/main/resources/application.yml
new file mode 100644
index 0000000000..c05154f1fc
--- /dev/null
+++ 
b/modules/agent-framework/connection-service/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+grpc:
+  server:
+    port: 19900
+
+server:
+  port: 18880
\ No newline at end of file
diff --git a/modules/agent-framework/pom.xml b/modules/agent-framework/pom.xml
new file mode 100644
index 0000000000..d07570f03b
--- /dev/null
+++ b/modules/agent-framework/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.airavata</groupId>
+        <artifactId>airavata</artifactId>
+        <version>0.21-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>agent-framework</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>connection-service</module>
+    </modules>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 16d80cb802..c19f5558aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,8 @@
         <module>modules/airavata-metascheduler/process-scheduler</module>
         <module>modules/computer-resource-monitoring-service</module>
         <module>modules/airavata-metascheduler/metadata-analyzer</module>
+        <module>modules/agent-framework</module>
+        <module>modules/agent-framework/connection-service</module>
     </modules>
 
     <parent>
@@ -86,8 +88,8 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <derby.version>10.13.1.1</derby.version>
-        <org.slf4j.version>1.7.25</org.slf4j.version>
-        <log4j2.version>2.17.2</log4j2.version>
+        <org.slf4j.version>2.0.13</org.slf4j.version>
+        <log4j2.version>2.23.1</log4j2.version>
         <surefire.version>3.0.0-M4</surefire.version>
         <junit.version>4.12</junit.version>
         <curator.version>2.8.0</curator.version>
@@ -108,7 +110,7 @@
         <thrift.version>0.18.1</thrift.version>
         <mysql.connector.version>5.1.34</mysql.connector.version>
         <skipTests>false</skipTests>
-        <google.gson.version>2.3</google.gson.version>
+        <google.gson.version>2.10.1</google.gson.version>
         <zk.version>3.4.0</zk.version>
         <amqp.client.version>3.5.1</amqp.client.version>
         <snakeyaml.version>1.15</snakeyaml.version>


Reply via email to