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
| Event | Files in /workspace | Files outside /workspace | Running processes and memory |
|---|---|---|---|
| Suspend and wake (memory snapshot) | Kept | Kept | Kept |
| Power off and wake | Kept | Lost | Lost |
| VM replaced (agent upgrade, unhealthy VM) | Kept | Lost | Lost |
| Environment destroyed | Deleted | Deleted | Deleted |
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_sizeenvironments (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/workspaceare 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_failuresenvironments (default 0) fail to come up healthy, the rollout rolls itself back andreasonsays which environment failed and why. - Completion. At 100% with every environment done, the rollout becomes
completedand 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
| Call | Allowed when | Notes |
|---|---|---|
pauseRollout | active | Stops starting new batches. Any other state returns 409 invalid_state_transition, including paused. |
resumeRollout | paused | Picks up where it stopped. Any other state returns 409 invalid_state_transition. |
widenRollout | active or paused | Raises percent. It can't go down: a smaller value returns 400. To undo part of a rollout, roll it back. |
rollbackRollout | Your most recent rollout | Moves 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.