temperDocs
Menu

Concepts

Data and upgrades

What lives on each end user's data disk, what survives suspend, power-off and VM replacement, and how to roll out new agent versions.

Each environment has its own encrypted data disk. The VM around it can be replaced at any time: when it powers off after being idle, when Temper replaces an unhealthy VM, or when you upgrade the agent. The disk is what stays. This page covers what is kept where, and how to ship a new version of your agent to environments that already exist.

The data disk

The data disk is mounted in the VM at /workspace. Your agent runs as the agent user, whose home directory (and the default working directory for exec calls) is /workspace/agent. Anything your agent writes under /workspace is on the disk: its memory, conversation history, files it downloaded or produced, and its configuration.

  • Every end user gets a separate disk. No other environment can read it.
  • Each disk is encrypted with its own key. The disk is unlocked on the host and handed to the VM, so your agent sees ordinary files.
  • The size is resources.disk_gib (10 GiB by default, up to 200 GiB). You can only set it when you create the environment. Storage is metered on the space actually written, not on the size you set.

Everything outside /workspace is rebuilt every time the VM starts. The root file system comes from a read-only image with a scratch layer on top, and that layer is cleared when the VM is replaced. Don't keep anything you need outside /workspace.

Logged-in browser sessions are not on the disk. Temper stores them, encrypted, as browser profiles (see Browser).

What survives what

EventFiles in /workspaceFiles outside /workspaceRunning processes and memory
Suspend and wake (memory snapshot)KeptKeptKept
Power off and wakeKeptLostLost
VM replaced (agent upgrade, unhealthy VM)KeptLostLost
Environment destroyedDeletedDeletedDeleted

If a memory snapshot cannot be restored, Temper boots a fresh VM on the same disk instead of failing the wake. Your files are kept, running processes are not. The running event for that wake has "restore_failed": true in its detail.

Write your agent so it can restart from what is on disk at any time: save progress to /workspace as it goes, rather than keeping it only in memory.

Backups and deletion

Temper backs up data disks incrementally. Backups contain only the encrypted blocks of the disk, so neither the storage provider nor Temper's operators can read your users' files from them.

Destroying an environment deletes its VM, its data disk and all of its backups. Deletion can't be undone. Don't destroy an environment to "restart" it; use suspend and resume, or simply leave it to the idle ladder.

Agent packages

Your agent ships as a package: a squashfs image that Temper mounts read-only inside every VM. Upload each version once with uploadPackage (Python upload_package, Go UploadPackage), naming it with a version string of up to 64 letters, digits, ., _ and -. The body must be a squashfs file.

A version can't be changed once it is uploaded. Uploading the same content again returns 200. Uploading different content under an existing version returns 409 version_exists, so bump the version instead.

import { readFile } from "node:fs/promises";

const pkg = await temper.agent.uploadPackage("1.5.0", await readFile("agent-1.5.0.squashfs"));
console.log(pkg.version, pkg.sha256, pkg.size_bytes);
uploaded = temper.agent.upload_package("1.5.0", "agent-1.5.0.squashfs")  # path, bytes or a binary file
print(uploaded.package.version, uploaded.package.sha256, uploaded.created)
f, err := os.Open("agent-1.5.0.squashfs")
if err != nil {
	log.Fatal(err)
}
defer f.Close()
pkg, created, err := client.Agent.UploadPackage(ctx, "1.5.0", f)

listPackages returns every version you have uploaded and your current default. See the agent API.

The default version

Your default version is the one new environments get when they are created without agent_version. Set it with setDefaultVersion (Python set_default_version, Go SetDefaultVersion). Setting a version you have not uploaded returns 400.

Changing the default does not touch existing environments. To move existing environments to a new version, start a rollout. A rollout that completes at 100% also makes its version your default.

agent_version on create is not checked against your uploaded packages, so make sure you pass a version that exists.

Rollouts

A rollout moves a percentage of your environments to a new version, a few at a time, and stops on its own if they fail.

const rollout = await temper.agent.startRollout({ version: "1.5.0", percent: 10, batch_size: 5, max_failures: 2 });
// Later, once you are happy with it:
await temper.agent.widenRollout(rollout.id, 100);
rollout = temper.agent.start_rollout(version="1.5.0", percent=10, batch_size=5, max_failures=2)
# Later, once you are happy with it:
temper.agent.widen_rollout(rollout.id, 100)
rollout, err := client.Agent.StartRollout(ctx, temper.StartRolloutParams{
	Version: "1.5.0", Percent: 10, BatchSize: 5, MaxFailures: 2,
})
if err != nil {
	log.Fatal(err)
}
// Later, once you are happy with it:
_, err = client.Agent.WidenRollout(ctx, rollout.ID, 100)

How it works:

  • Which environments. Temper picks percent% of your environments by a hash of the rollout id and the environment id. The choice is stable: widening the percentage only adds environments, it never swaps one set for another.
  • Batches. Up to batch_size environments (default 1) are upgraded at the same time. The next batch starts only once the current one is healthy. Upgrading replaces the VM and reattaches the same data disk, so files in /workspace are kept and running processes are not (see What survives what).
  • Environments that aren't running get the new version recorded but are not woken up. They start on it the next time they wake. In the rollout's detail they show deferred: true.
  • Automatic rollback. If more than max_failures environments (default 0) fail to come up healthy, the rollout rolls itself back and reason says which environment failed and why.
  • Completion. At 100% with every environment done, the rollout becomes completed and its version becomes your default.

You can have one active or paused rollout at a time; starting another returns 409 rollout_in_progress. Starting a rollout with a version you have not uploaded returns 400.

Pause, resume, widen, roll back

CallAllowed whenNotes
pauseRolloutactiveStops starting new batches. Any other state returns 409 invalid_state_transition, including paused.
resumeRolloutpausedPicks up where it stopped. Any other state returns 409 invalid_state_transition.
widenRolloutactive or pausedRaises percent. It can't go down: a smaller value returns 400. To undo part of a rollout, roll it back.
rollbackRolloutYour most recent rolloutMoves every upgraded environment back to the version it had before. Rolling back a completed rollout also restores your previous default version. Rolling back an older rollout returns 409 not_latest_rollout. Rolling back one that is already rolled_back returns it unchanged.

getRollout (Python get_rollout, Go GetRollout) returns the rollout and every environment it touched, with from_version, upgraded_at, healthy_at, failed_at, error and rolled_back_at. listRollouts returns your most recent rollouts, newest first. Each upgrade is also recorded as an agent_upgrade event on the environment.

The Python and Go method names follow the same pattern: pause_rollout / PauseRollout, resume_rollout / ResumeRollout, rollback_rollout / RollbackRollout.

Per-environment agent settings

PATCH /v1/environments/{id}/agent (updateAgentSettings) controls what the agent inside one environment may schedule and how long it may keep the VM awake. It does not change the agent's version. Versions are set when the environment is created and changed by rollouts. See Limits on what the agent can do and Update agent settings.