syntax = "proto3"; package hostagent.v1; // HostAgentService manages sandbox VMs on a single physical host. // The control plane calls these RPCs to orchestrate sandbox lifecycle. service HostAgentService { // CreateSandbox boots a new microVM with the given configuration. rpc CreateSandbox(CreateSandboxRequest) returns (CreateSandboxResponse); // DestroySandbox stops and cleans up a sandbox (VM, network, rootfs). rpc DestroySandbox(DestroySandboxRequest) returns (DestroySandboxResponse); // PauseSandbox pauses a running sandbox's VM. rpc PauseSandbox(PauseSandboxRequest) returns (PauseSandboxResponse); // ResumeSandbox resumes a paused sandbox's VM. rpc ResumeSandbox(ResumeSandboxRequest) returns (ResumeSandboxResponse); // Exec runs a command inside a sandbox and returns the collected output. rpc Exec(ExecRequest) returns (ExecResponse); // ListSandboxes returns all sandboxes managed by this host agent. rpc ListSandboxes(ListSandboxesRequest) returns (ListSandboxesResponse); // WriteFile writes content to a file inside a sandbox. rpc WriteFile(WriteFileRequest) returns (WriteFileResponse); // ReadFile reads a file from inside a sandbox. rpc ReadFile(ReadFileRequest) returns (ReadFileResponse); // ListDir lists directory contents inside a sandbox. rpc ListDir(ListDirRequest) returns (ListDirResponse); // MakeDir creates a directory inside a sandbox. rpc MakeDir(MakeDirRequest) returns (MakeDirResponse); // RemovePath removes a file or directory inside a sandbox. rpc RemovePath(RemovePathRequest) returns (RemovePathResponse); // CreateSnapshot pauses a sandbox, takes a snapshot, stores it as a reusable // template, and destroys the sandbox. rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse); // DeleteSnapshot removes a snapshot template from disk. rpc DeleteSnapshot(DeleteSnapshotRequest) returns (DeleteSnapshotResponse); // ExecStream runs a command inside a sandbox and streams output events as they arrive. rpc ExecStream(ExecStreamRequest) returns (stream ExecStreamResponse); // WriteFileStream writes a file to a sandbox using chunked streaming. // First message must contain metadata (sandbox_id, path). Subsequent messages contain data chunks. rpc WriteFileStream(stream WriteFileStreamRequest) returns (WriteFileStreamResponse); // ReadFileStream reads a file from a sandbox and streams it back in chunks. rpc ReadFileStream(ReadFileStreamRequest) returns (stream ReadFileStreamResponse); // PingSandbox resets the inactivity timer for a running sandbox. rpc PingSandbox(PingSandboxRequest) returns (PingSandboxResponse); // Terminate instructs the host agent to destroy all sandboxes and exit. // Called by the control plane immediately when a host is deleted so the // agent shuts down without waiting for the next heartbeat cycle. rpc Terminate(TerminateRequest) returns (TerminateResponse); // GetSandboxMetrics returns ring buffer metrics for a running sandbox. rpc GetSandboxMetrics(GetSandboxMetricsRequest) returns (GetSandboxMetricsResponse); // FlushSandboxMetrics returns all ring buffer tiers and clears them. // Called by the control plane before pause/destroy to persist metrics to DB. rpc FlushSandboxMetrics(FlushSandboxMetricsRequest) returns (FlushSandboxMetricsResponse); // FlattenRootfs stops the sandbox VM, flattens the device-mapper CoW // snapshot into a standalone rootfs.ext4 in the images directory, then // cleans up all sandbox resources. Used by the template build system to // produce image-only templates (no memory/CPU state). rpc FlattenRootfs(FlattenRootfsRequest) returns (FlattenRootfsResponse); // PtyAttach starts a new PTY process or reconnects to an existing one. // If cmd is non-empty, starts a new process with the given PTY dimensions. // If tag is set and cmd is empty, reconnects to the existing process with that tag. // Returns a stream of output events (started, output data, exit). rpc PtyAttach(PtyAttachRequest) returns (stream PtyAttachResponse); // PtySendInput sends raw bytes to a PTY process identified by tag. rpc PtySendInput(PtySendInputRequest) returns (PtySendInputResponse); // PtyResize updates the terminal dimensions for a PTY process. rpc PtyResize(PtyResizeRequest) returns (PtyResizeResponse); // PtyKill sends a signal to a PTY process. rpc PtyKill(PtyKillRequest) returns (PtyKillResponse); // StartBackground starts a process in the background and returns immediately // with the PID and tag. The process survives RPC disconnection. rpc StartBackground(StartBackgroundRequest) returns (StartBackgroundResponse); // ListProcesses returns all running processes inside a sandbox. rpc ListProcesses(ListProcessesRequest) returns (ListProcessesResponse); // KillProcess sends a signal to a process identified by PID or tag. rpc KillProcess(KillProcessRequest) returns (KillProcessResponse); // ConnectProcess re-attaches to a running process and streams its output. rpc ConnectProcess(ConnectProcessRequest) returns (stream ConnectProcessResponse); } message CreateSandboxRequest { // Sandbox ID assigned by the control plane. If empty, the host agent generates one. string sandbox_id = 5; // Deprecated: use team_id + template_id instead. string template = 1; // Number of virtual CPUs (default: 1). int32 vcpus = 2; // Memory in MB (default: 512). int32 memory_mb = 3; // TTL in seconds. Sandbox is auto-paused after this duration of // inactivity. 0 means no auto-pause. int32 timeout_sec = 4; // Disk size in MB for the rootfs. Base images are expanded to this size // at host agent startup. Default: 5120 (5 GB). int32 disk_size_mb = 6; // Team UUID that owns the template (hex string). All-zeros = platform. string team_id = 7; // Template UUID (hex string). Both zeros + team zeros = "minimal" sentinel. string template_id = 8; // Default unix user for the sandbox (set in envd via PostInit). string default_user = 9; // Default environment variables (set in envd via PostInit). map default_env = 10; } message CreateSandboxResponse { string sandbox_id = 1; string status = 2; string host_ip = 3; // Runtime metadata collected during sandbox creation (e.g. envd_version, // kernel_version, firecracker_version, agent_version). map metadata = 4; } message DestroySandboxRequest { string sandbox_id = 1; } message DestroySandboxResponse {} message PauseSandboxRequest { string sandbox_id = 1; } message PauseSandboxResponse {} message ResumeSandboxRequest { string sandbox_id = 1; // TTL in seconds restored from the DB so the reaper can auto-pause // the sandbox again after inactivity. 0 means no auto-pause. int32 timeout_sec = 2; // Default unix user for the sandbox (set in envd via PostInit on resume). string default_user = 3; // Default environment variables (set in envd via PostInit on resume). map default_env = 4; // Kernel version hint from the DB — the agent tries to use the exact version, // falling back to latest if not found on disk. string kernel_version = 5; } message ResumeSandboxResponse { string sandbox_id = 1; string status = 2; string host_ip = 3; // Actual runtime metadata after resume (versions may differ from hint if // the exact kernel was not available). map metadata = 4; } message CreateSnapshotRequest { string sandbox_id = 1; // Deprecated: use team_id + template_id instead. string name = 2; // Team UUID that will own the new template. string team_id = 3; // Template UUID for the new snapshot template. string template_id = 4; } message CreateSnapshotResponse { string name = 1; int64 size_bytes = 2; } message DeleteSnapshotRequest { // Deprecated: use team_id + template_id instead. string name = 1; // Team UUID that owns the template. string team_id = 2; // Template UUID to delete. string template_id = 3; } message DeleteSnapshotResponse {} message ExecRequest { string sandbox_id = 1; string cmd = 2; repeated string args = 3; // Timeout for the command in seconds (default: 30). int32 timeout_sec = 4; map envs = 5; string cwd = 6; } message ExecResponse { bytes stdout = 1; bytes stderr = 2; int32 exit_code = 3; } message ListSandboxesRequest {} message ListSandboxesResponse { repeated SandboxInfo sandboxes = 1; // IDs of sandboxes that were automatically paused by the TTL reaper // since the last call. Drained on read. repeated string auto_paused_sandbox_ids = 2; } message SandboxInfo { string sandbox_id = 1; string status = 2; // Deprecated: use team_id + template_id instead. string template = 3; int32 vcpus = 4; int32 memory_mb = 5; string host_ip = 6; int64 created_at_unix = 7; int64 last_active_at_unix = 8; int32 timeout_sec = 9; string team_id = 10; string template_id = 11; // Runtime metadata (envd_version, kernel_version, etc.). map metadata = 12; } message WriteFileRequest { string sandbox_id = 1; string path = 2; bytes content = 3; } message WriteFileResponse {} message ReadFileRequest { string sandbox_id = 1; string path = 2; } message ReadFileResponse { bytes content = 1; } // ── Streaming Exec ────────────────────────────────────────────────── message ExecStreamRequest { string sandbox_id = 1; string cmd = 2; repeated string args = 3; int32 timeout_sec = 4; map envs = 5; string cwd = 6; } message ExecStreamResponse { oneof event { ExecStreamStart start = 1; ExecStreamData data = 2; ExecStreamEnd end = 3; } } message ExecStreamStart { uint32 pid = 1; } message ExecStreamData { oneof output { bytes stdout = 1; bytes stderr = 2; } } message ExecStreamEnd { int32 exit_code = 1; string error = 2; } // ── Streaming File Transfer ───────────────────────────────────────── message WriteFileStreamRequest { oneof content { WriteFileStreamMeta meta = 1; bytes chunk = 2; } } message WriteFileStreamMeta { string sandbox_id = 1; string path = 2; } message WriteFileStreamResponse {} message ReadFileStreamRequest { string sandbox_id = 1; string path = 2; } message ReadFileStreamResponse { bytes chunk = 1; } // ── Filesystem Operations ────────────────────────────────────────── message ListDirRequest { string sandbox_id = 1; string path = 2; uint32 depth = 3; } message ListDirResponse { repeated FileEntry entries = 1; } message FileEntry { string name = 1; string path = 2; // "file", "directory", or "symlink". string type = 3; int64 size = 4; uint32 mode = 5; // Human-readable permissions string, e.g. "-rwxr-xr-x". string permissions = 6; string owner = 7; string group = 8; // Last modification time as Unix timestamp (seconds). int64 modified_at = 9; optional string symlink_target = 10; } message MakeDirRequest { string sandbox_id = 1; string path = 2; } message MakeDirResponse { FileEntry entry = 1; } message RemovePathRequest { string sandbox_id = 1; string path = 2; } message RemovePathResponse {} // ── Ping ──────────────────────────────────────────────────────────── message PingSandboxRequest { string sandbox_id = 1; } message PingSandboxResponse {} // ── Terminate ──────────────────────────────────────────────────────── message TerminateRequest {} message TerminateResponse {} // ── Metrics ────────────────────────────────────────────────────────── message MetricPoint { int64 timestamp_unix = 1; double cpu_pct = 2; int64 mem_bytes = 3; int64 disk_bytes = 4; } message GetSandboxMetricsRequest { string sandbox_id = 1; // Range tier: "10m", "2h", or "24h". string range = 2; } message GetSandboxMetricsResponse { repeated MetricPoint points = 1; } message FlushSandboxMetricsRequest { string sandbox_id = 1; } message FlushSandboxMetricsResponse { repeated MetricPoint points_10m = 1; repeated MetricPoint points_2h = 2; repeated MetricPoint points_24h = 3; } // ── FlattenRootfs ──────────────────────────────────────────────────── message FlattenRootfsRequest { string sandbox_id = 1; // Deprecated: use team_id + template_id instead. string name = 2; // Team UUID that will own the resulting template. string team_id = 3; // Template UUID for the output. string template_id = 4; } message FlattenRootfsResponse { int64 size_bytes = 1; } // ── PTY ───────────────────────────────────────────────────────────── message PtyAttachRequest { string sandbox_id = 1; // Tag is the stable identifier for this PTY session (e.g. "pty-abc123de"). // Chosen by the caller and used to reconnect later. string tag = 2; // If cmd is non-empty, a new process is started. If empty, reconnects to // the existing process identified by tag. string cmd = 3; repeated string args = 4; uint32 cols = 5; uint32 rows = 6; // Environment variables for the process. map envs = 7; // Working directory. Empty means default. string cwd = 8; // User to run as. Empty means default (root). string user = 9; } message PtyAttachResponse { oneof event { PtyStarted started = 1; PtyOutput output = 2; PtyExited exited = 3; } } message PtyStarted { uint32 pid = 1; string tag = 2; } message PtyOutput { bytes data = 1; } message PtyExited { int32 exit_code = 1; string error = 2; } message PtySendInputRequest { string sandbox_id = 1; string tag = 2; bytes data = 3; } message PtySendInputResponse {} message PtyResizeRequest { string sandbox_id = 1; string tag = 2; uint32 cols = 3; uint32 rows = 4; } message PtyResizeResponse {} message PtyKillRequest { string sandbox_id = 1; string tag = 2; } message PtyKillResponse {} // ── Background Processes ─────────────────────────────────────────── message StartBackgroundRequest { string sandbox_id = 1; string cmd = 2; repeated string args = 3; // User-chosen tag for the process. If empty, the host agent generates one. string tag = 4; map envs = 5; string cwd = 6; } message StartBackgroundResponse { uint32 pid = 1; string tag = 2; } message ListProcessesRequest { string sandbox_id = 1; } message ProcessEntry { uint32 pid = 1; string tag = 2; string cmd = 3; repeated string args = 4; } message ListProcessesResponse { repeated ProcessEntry processes = 1; } message KillProcessRequest { string sandbox_id = 1; oneof selector { uint32 pid = 2; string tag = 3; } // Signal to send: "SIGTERM" or "SIGKILL" (default: "SIGKILL"). string signal = 4; } message KillProcessResponse {} message ConnectProcessRequest { string sandbox_id = 1; oneof selector { uint32 pid = 2; string tag = 3; } } // Reuses ExecStream event types for symmetry. message ConnectProcessResponse { oneof event { ExecStreamStart start = 1; ExecStreamData data = 2; ExecStreamEnd end = 3; } }