Skip to content

Compute service

The compute service is the gVisor-backed sandbox data plane for paperboard. It provisions isolated execution environments for every agent tool call, streams exec output to the caller, and emits resource-usage telemetry that feeds the Phase 5 billing engine.

Agent tool calls run arbitrary code on behalf of tenants. Keeping that code inside the agents process would make it impossible to enforce per-tenant CPU, memory, and disk limits, or to restart a crashed sandbox without losing an in-flight LLM session. A dedicated data-plane service lets us:

  • Enforce runtimeClassName: gvisor on sandbox pods without touching the agents deployment.
  • Run the gVisor DaemonSet on a dedicated node pool (Phase 6) with independent scaling.
  • Expose workspace I/O RPCs (ReadFile, WriteFile, ListFiles) as first-class operations without adding K8s API client dependencies to agents.
  1. Creates an isolated gVisor pod + 5 GiB PVC workspace per session on first tool call (lazy provisioning — sessions that never invoke a tool pay nothing).
  2. Streams exec output (stdout, stderr) and a final ExecCompleted event carrying UsageMetrics back to the agents caller.
  3. Exposes workspace I/O RPCs so agents can read/write files across tool-call turns.
  4. Garbage-collects PVCs after a 24-hour soft-delete grace period.
CallerProtocolWhat it asks for
agentsgRPCCreateSandbox, ExecCommand, DestroySandbox, file I/O
runtimeRoutes requests; does not call compute directly (Phase 3)

No public HTTP API. All traffic is internal gRPC (ClusterIP, port 50051).

stateDiagram-v2
[*] --> STARTING : CreateSandbox\n(first tool_use in session)
STARTING --> READY : pod Running\n(WaitForRunning)
STARTING --> FAILED : pod CrashLoopBackOff\nor deadline exceeded
READY --> READY : ExecCommand\n(each tool call)
READY --> DESTROYED : DestroySandbox\n(session end or idle timeout)
FAILED --> DESTROYED : DestroySandbox
DESTROYED --> [*] : PVC soft-deleted\n(24h grace → GC CronJob)

A sandbox is lazily created on the first tool_use block from the LLM. Sessions that complete without invoking any tool have sessions.sandbox_id IS NULL and incur no compute cost. Subsequent tool calls within the same session re-use the existing sandbox.

Each sandbox gets a dedicated PVC mounted at /workspace:

ParameterDefaultOverride
Storage classstandardPVC_STORAGE_CLASS env var
Size5GiPVC_WORKSPACE_SIZE env var
Mount path/workspaceWorkspaceSpec.mount_path in CreateSandboxRequest

On DestroySandbox the PVC is annotated with compute.paper-board.io/delete-after set to now + 24h. An hourly GC CronJob (cmd/gc) deletes annotated PVCs past their grace window. This pattern preserves workspace data for post-mortem inspection after unexpected session ends.

Every ExecCommand response carries a UsageMetrics message:

cpu_ms wall-clock CPU time consumed by the process
memory_peak_bytes peak RSS during the exec
memory_avg_bytes average RSS
disk_read_bytes bytes read from the workspace PVC
disk_write_bytes bytes written to the workspace PVC
network_egress_bytes bytes sent to external destinations
network_ingress_bytes bytes received from external destinations

The agents service writes these into agents.usage_events (Phase 3 outbox) so the platform service can aggregate quota and billing data in Phase 4.

gVisor self-install. The Helm chart ships a DaemonSet that installs runsc on every node and registers RuntimeClass: gvisor. No GKE Sandbox dependency — the chart is cloud-agnostic (kind, GCP standard-rwo, AWS gp3).

Lazy sandbox provisioning (D14). Sandboxes are created on first tool_use, not at session start. This avoids paying for a pod + PVC on every LLM turn that has no tool call, which is the common case for conversational agents.

PVC soft-delete grace (D5). A 24-hour window between DestroySandbox and physical PVC deletion avoids data loss on unexpected session restarts. The CronJob enforces the upper bound.

No Postgres schema (ADR-0002). Compute is stateless — sandbox state lives in K8s pod annotations and labels. The migrator job is a no-op stub present only to satisfy the Helm pre-install/pre-upgrade hook contract.