Skip to main content

GCP Sandbox Provider

@smithers-orchestrator/gcp is a first-class Smithers SandboxProvider for Google Cloud. It executes a <Sandbox> child workflow’s request on Cloud Run Jobs and ships the request/result bundle through a Cloud Storage bucket, because Cloud Run Jobs give no shared filesystem back to the caller. The shared provider-kit owns the request/result protocol, egress, secret scrubbing, and cleanup; this package supplies the GCS transport plus the Cloud Run runner. The provider id is gcp-sandbox (exported as GCP_SANDBOX_PROVIDER_ID).
import {
  createGcpSandboxProvider,
  registerGcpSandboxProvider,
  GCP_SANDBOX_PROVIDER_ID,
} from "smithers-orchestrator/gcp";

Credentials

Authentication is Application Default Credentials: GOOGLE_APPLICATION_CREDENTIALS (a service-account key file) or workload identity, plus GOOGLE_CLOUD_PROJECT. Local credentials are never forwarded into the container. The container env is options.env plus the Smithers, egress, and GCS-transport variables. @google-cloud/run and @google-cloud/storage are optional dependencies, imported lazily inside the session, so the package loads without them. Install both to use the real provider:
npm install @google-cloud/run @google-cloud/storage

Prerequisites

The provider does not create the bucket. Set these up first:
  • A Cloud Storage bucket that already exists (the transport). Set a short lifecycle TTL on the smithers/sandbox/ prefix to reap crash leftovers.
  • A Cloud Run jobName to run, or set createJob to have a per-run Job created and torn down. When createJob is set you must also pass a container image (Cloud Run requires one to create the Job). The job’s service account needs read/write on the bucket prefix.

Required options

createGcpSandboxProvider({ projectId, location, bucket, jobName }): all four are required and missing ones throw INVALID_INPUT. projectId falls back to GOOGLE_CLOUD_PROJECT.
optionmeaning
projectIdGCP project id
locationCloud Run region, e.g. us-central1
bucketa pre-existing Cloud Storage bucket (transport)
jobNameCloud Run Job to run (or created per-run when createJob)
Other knobs: prefix (default smithers/sandbox), command, workdir (default /workspace), env, cleanup ("destroy" or "keep"), timeoutSec, createJob, sandboxId(request), and client/clients/clientOptions for SDK injection.

Usage

import { Sandbox } from "smithers-orchestrator";
import { createGcpSandboxProvider } from "smithers-orchestrator/gcp";

const provider = createGcpSandboxProvider({
  projectId: "my-project",
  location: "us-central1",
  bucket: "my-smithers-sandbox",
  jobName: "smithers-sandbox-runner",
});

// <Sandbox provider={provider} workflow={child} output={outputs.result} />
Or register it once and reference it by id with registerGcpSandboxProvider(...) then <Sandbox provider="gcp-sandbox" />.

Request/result contract

The kit writes .smithers/sandbox-request.json and expects .smithers/sandbox-result.json back, handing the container SMITHERS_SANDBOX_REQUEST_PATH and SMITHERS_SANDBOX_RESULT_PATH. Because there is no shared filesystem, the container round-trips those files through GCS. The runner injects four extra vars:
  • SMITHERS_SANDBOX_GCS_BUCKET: the transport bucket.
  • SMITHERS_SANDBOX_GCS_PREFIX: object-name prefix.
  • SMITHERS_SANDBOX_REQUEST_GCS_OBJECT: object holding the request JSON.
  • SMITHERS_SANDBOX_RESULT_GCS_OBJECT: object the entry must write result JSON to.
Every workdir-relative path maps to <prefix>/<runId>/<sandboxId>/<percent-encoded workdir-relative path> (the full path, not just the basename, so same-named files never collide). Cloud Run reports task counts and conditions, not a numeric exit code: a succeeded task is exit 0 and a failed task is exit 1. An infra failure (execution failed, no result written) throws. A run that writes status: "failed" result JSON is a normal failed bundle the kit materializes.

Cleanup and cost

cleanup: "destroy" (default) deletes the transient GCS objects and, when createJob made a per-run job, deletes that job. cleanup: "keep" leaves everything. The bucket itself is never created or deleted. You pay for Cloud Run Job execution time plus GCS storage of the small transient objects. Compute Engine execution is documented future work. createMockGcpSandboxEnvironment(handler, config?) provides in-memory Cloud Storage and Cloud Run doubles for tests. It needs zero real GCP credentials or bucket, so unit tests run in CI without touching GCP.