Skip to content

Pre-warm a Service in a Template

A regular template can preinstall an operating system and dependencies, but an application may still perform expensive initialization after every sandbox starts—for example, loading an SDK, creating an agent session, scanning a workspace, or building a local cache. CubeSandbox can wait for that work to finish before taking the template snapshot, allowing new sandboxes to restore an already initialized process and memory state.

This guide uses examples/pi-agent-integration to demonstrate the pattern. Read Templates Overview first if you are unfamiliar with how a probe determines when the snapshot is taken.

How It Works

The key to a pre-warmed template is an accurate readiness endpoint:

  1. The image starts a resident service.
  2. The service performs the initialization that should be pre-warmed.
  3. Its readiness endpoint returns HTTP 2xx only after initialization completes.
  4. CubeSandbox observes the successful probe and saves the filesystem, memory, and process state.
  5. Sandboxes created from the template restore the resident service ready to accept work.

The readiness endpoint should not succeed merely because the HTTP server has started listening. Return 503 until every state that must be preserved in the snapshot is ready.

Pi Agent Warmup Example

The regular Pi Agent workflow starts a new process for every task. The example warmup adapter instead runs as the image's resident process and creates a Pi SDK AgentSession during startup. GET /readyz returns 200 only after that session is initialized.

1. Prepare the Resident Service

The implementation is in pi_warmup_adapter.mjs. Its core pattern is:

javascript
let ready = false;

const server = http.createServer((request, response) => {
  if (request.method === "GET" && request.url === "/readyz") {
    response.writeHead(ready ? 200 : 503);
    return response.end();
  }

  // Handle application requests after restore.
});

session = await createAgentSession(/* ... */);
ready = true;
server.listen(8080, "0.0.0.0");

The complete adapter also exposes POST /prompt to send work to the restored resident AgentSession.

2. Make the Service the Image Command

Dockerfile.warmup builds on the Pi Agent image, copies the adapter, and sets it as the image CMD:

dockerfile
ARG PI_AGENT_IMAGE=pi-agent-cube:latest
FROM ${PI_AGENT_IMAGE}

COPY pi_warmup_adapter.mjs /tmp/pi_warmup_adapter.mjs
RUN PI_PACKAGE_DIR="$(npm root -g)/@earendil-works/pi-coding-agent" \
    && install -m 0755 /tmp/pi_warmup_adapter.mjs \
       "${PI_PACKAGE_DIR}/pi_warmup_adapter.mjs" \
    && rm /tmp/pi_warmup_adapter.mjs

ENV PI_WARMUP_HOST=0.0.0.0 \
    PI_WARMUP_PORT=8080

EXPOSE 49983 8080

CMD ["sh", "-c", "exec node \"$(npm root -g)/@earendil-works/pi-coding-agent/pi_warmup_adapter.mjs\""]

Port 8080 serves application readiness and task requests. Port 49983 is used by envd from the base image to retain SDK command, file, and terminal capabilities.

3. Build and Push the Image

From the repository root, build the base image followed by the warmup image:

bash
docker build --platform linux/amd64 \
  -t localhost:5000/pi-agent-cube:latest \
  examples/pi-agent-integration

docker build --platform linux/amd64 \
  -f examples/pi-agent-integration/Dockerfile.warmup \
  --build-arg PI_AGENT_IMAGE=localhost:5000/pi-agent-cube:latest \
  -t localhost:5000/pi-agent-warmup-cube:latest \
  examples/pi-agent-integration

docker push localhost:5000/pi-agent-cube:latest
docker push localhost:5000/pi-agent-warmup-cube:latest

Replace the example address with an image registry reachable by the CubeSandbox cluster.

4. Build the Template Using the Application Probe

Expose both envd and the warmup adapter, but point the probe at /readyz, which represents completion of Pi session initialization:

bash
cubemastercli tpl create-from-image \
  --image localhost:5000/pi-agent-warmup-cube:latest \
  --alias pi-warmup \
  --writable-layer-size 4G \
  --expose-port 49983 \
  --expose-port 8080 \
  --probe 8080 \
  --probe-path /readyz

Do not use 49983/health as the warmup-complete signal in this example. It only proves that envd is ready, not that the Pi AgentSession has been created.

Run cubemastercli tpl watch --job-id <job-id> until the job reaches READY. Sandboxes created from the resulting template restore the initialized Node process and Pi session.

Designing Your Own Pre-warmed Service

Follow these principles when applying the same pattern to another service:

  • Probe the real warmup state. Return 2xx only after model loading, runtime initialization, or cache construction has completed.
  • Keep the process resident. The initialized process must remain running to be restored with the memory snapshot.
  • Do not bake secrets into the template. Do not supply API keys, tokens, or user data during the build. Provide them after restore through a request, secret vault, or another runtime mechanism.
  • Treat external connections carefully. Database connections, long-lived sockets, and temporary credentials may be invalid after restore. Detect and recreate them instead of assuming snapshotted connections remain usable.
  • Define the concurrency model. One adapter in the Pi example owns one session and returns HTTP 409 for concurrent work. Implement a pool or assign one task per sandbox when concurrency is required.
  • Keep readiness checks lightweight. A probe should read local state without repeating expensive initialization or producing external side effects.

Troubleshooting

SymptomWhat to check
Template build keeps waiting for the probeConfirm that the service listens on 0.0.0.0, the port and path match, and initialization logs show success.
Template is READY, but the first request still initializes the appThe readiness endpoint succeeds too early; set the ready state only after full initialization.
SDK command or file APIs are unavailableConfirm the image contains envd and exposes it with --expose-port 49983.
External requests fail after restoreCheck whether connections or credentials created before the snapshot expired, and recreate them after restore.

For the complete Pi Agent build, invocation, and network-policy example, see examples/pi-agent-integration/README.md.