Cordium documentation · Latest

Sharing Data with Volumes

Volumes are persistent storage devices of a Space that live independently of the Workspaces that mount them (read more here). This example shows four common ways to use them in the payments Space: a build cache shared by ephemeral CI Workspaces, a read-only dataset shared by many Workspaces, handing artifacts off from one Workspace to another, and persisting the state of ephemeral AI agent Workspaces across runs.

First, a Space admin creates the Volumes. SHARED Volumes can be mounted by several running Workspaces at the same time and require a multi-writer storage backend, while EXCLUSIVE Volumes (the default) are mounted by one running Workspace at a time (read more here):

cordium create volume go-cache.payments.cordium --size 30000 --shared cordium create volume fixtures.payments.cordium --size 50000 --shared cordium create volume release-artifacts.payments.cordium --size 10000 cordium create volume triage-agent-state.payments.cordium --size 2000

A Shared Build Cache

Ephemeral Workspaces start from a clean storage on every run, which is great for reproducibility but means that every run downloads the Go modules and rebuilds everything from scratch. Pointing the Go caches to a SHARED Volume makes every run, including concurrent ones, reuse the work of the previous ones. Go's caches are safe to share between concurrent processes:

spec: image: registry: url: golang:1.26-bookworm repository: url: https://github.com/acme-corp/payments-api cloneOptions: depth: 1 disableLazyUnshallow: true runtime: autoStop: true volumeMounts: - volumeRef: name: go-cache mountPath: /cache envVars: - key: GOMODCACHE value: /cache/mod - key: GOCACHE value: /cache/build tasks: - name: test type: ON_CREATE workingDir: /workspace/repo onFailure: ON_FAILURE_ABORT run: go test -race ./...
cordium create template ci.payments.cordium --file ci.yaml cordium create ws --template ci.payments.cordium --ephemeral --start

The same approach works for npm (npm_config_cache), pip (PIP_CACHE_DIR), Cargo (CARGO_HOME), Gradle (GRADLE_USER_HOME) and Bazel (--disk_cache).

A Read-Only Dataset

Large fixtures, datasets and model weights should be downloaded once rather than by every Workspace. A Space admin populates the fixtures Volume once, for example by uploading a local directory to a Workspace that mounts it read-write:

cordium create ws --template api-dev.payments.cordium --volume fixtures:/fixtures --start cordium cp -r ./fixtures/ <WORKSPACE>:/fixtures/

Every other Workspace mounts it read-only, which guarantees that no test or agent can modify the shared data:

spec: runtime: volumeMounts: - volumeRef: name: fixtures mountPath: /fixtures readOnly: true

Handing Off Artifacts

A release pipeline can build its artifacts in one Workspace and verify them in another, with a different image or in a locked-down network environment, by passing them through a Volume. Since the two Workspaces run one after the other, an EXCLUSIVE Volume is enough. Here is the build step, which uses a release Template similar to the ci Template above:

cordium create ws --template release.payments.cordium --ephemeral --start \ --volume release-artifacts:/artifacts

with the following task:

spec: runtime: tasks: - name: build type: ON_CREATE workingDir: /workspace/repo onFailure: ON_FAILURE_ABORT run: | VERSION="$(git describe --tags --always)" mkdir -p "/artifacts/$VERSION" GOOS=linux GOARCH=amd64 go build -trimpath -o "/artifacts/$VERSION/payments-api-linux-amd64" ./cmd/server GOOS=linux GOARCH=arm64 go build -trimpath -o "/artifacts/$VERSION/payments-api-linux-arm64" ./cmd/server (cd "/artifacts/$VERSION" && sha256sum payments-api-* > SHA256SUMS) ln -sfn "$VERSION" /artifacts/latest

And the verification step, once the build Workspace has stopped, in a fresh Workspace that mounts the same Volume read-only:

cordium run --space payments.cordium --image debian:13-slim --ephemeral --rm \ --volume release-artifacts:/artifacts:ro
cd /artifacts/latest && sha256sum -c SHA256SUMS
note

Starting a Workspace that mounts an EXCLUSIVE Volume fails while another running Workspace mounts it. When you orchestrate such steps from a script, wait for the previous Workspace to stop first, for example via the SDKs' WaitUntilStopped/wait_until_stopped() helpers.

Persisting the State of Ephemeral Agents

Ephemeral Workspaces are the right default for AI agents, but some agents benefit from a memory that survives across runs, such as a triage agent that keeps notes about recurring issues, or a job that keeps checkpoints. An EXCLUSIVE Volume mounted under the home directory gives exactly that, while the rest of the Workspace is still discarded after each run. Here is the relevant part of such an agent Workspace's spec:

spec: isEphemeral: true runtime: autoStop: true volumeMounts: - volumeRef: name: triage-agent-state mountPath: /home/octelium/.agent-state

Since an EXCLUSIVE Volume cannot be mounted by two running Workspaces at once, this also guarantees that two runs of the agent never write to its state concurrently.