Runtime

How to give an AI agent memory that persists between sessions

Keep each user's agent in a named sandbox that pauses between sessions, and put memory that must outlive it on a volume.

On Runtime a paused agent keeps everything it had in RAM, its running processes and its files, for 1 to 365 days, and pays only storage while it sleeps: $0.08 per GB per 30-day month for the blocks it alone owns, at the rates in force on 25 September 2026. The next request wakes it, usually in about half a second, with its variables, open files and background servers exactly where they were.

Three kinds of agent memory

Kind Where it lives on Runtime Lasts Costs while idle
Working memory The paused sandbox's RAM and processes 1 to 365 days per pause (30 by default, paid) $0.08 per GB-month of owned blocks
Workspace files The sandbox's own disk While the sandbox exists Included in the paused size
Long-term memory A volume attached at a path Until you delete it, across any sandboxes About $0.11 per GiB-month
Checkpoints Snapshots of the whole machine 1 to 365 days (7 by default) $0.08 per GB-month of stored bytes

Most agents need the first two. Add a volume when a user's memory must survive the sandbox itself, and a snapshot when you want to go back to a known point.

The short answer: one sandbox per user, paused between visits

Name the sandbox after the user or the thread. getOrCreate answers the same sandbox every time, waking it if it paused:

TypeScriptimport { Sandbox } from "withruntime";export async function agentFor(userId: string) {  return Sandbox.getOrCreate(`agent-${userId}`, {    idlePauseSeconds: 600, // pause after ten quiet minutes    labels: { kind: "assistant", user: userId },  });}// Monday: the agent loads the user's data and takes a note.const monday = await agentFor("u-42");await monday.interpreter.run("import pandas as pd\nnotes = ['prefers weekly summaries']");// Thursday, from another server: the same interpreter, the same variables.const thursday = await agentFor("u-42");const recall = await thursday.interpreter.run("notes");console.log(thursday.info.reused, recall.results[0]?.data["text/plain"]);
Pythonfrom withruntime import Sandboxdef agent_for(user_id: str):    return Sandbox.get_or_create(        f"agent-{user_id}",        idle_pause_seconds=600,  # pause after ten quiet minutes        labels={"kind": "assistant", "user": user_id},    )monday = agent_for("u-42")monday.interpreter.run("import pandas as pd\nnotes = ['prefers weekly summaries']")thursday = agent_for("u-42")recall = thursday.interpreter.run("notes")print(thursday.info.get("reused"), recall["results"][0]["data"]["text/plain"])

The interpreter is a process in the sandbox, so a pause keeps its variables. A data frame that took a minute to load is still loaded next week. Write the agent's own notes to a file too, such as /workspace/memory.md, so they are readable with files.readText and survive a restart.

A paid pause is kept 30 days unless you set 1 to 365 with POST /v1/sandboxes/{id}:retention, and each pause replaces the saved state before it (pricing). Trial pauses are kept seven days, free.

Memory that outlives any sandbox

A volume is a disk with its own lifetime. Create one per user, attach it to whichever sandbox is serving them, and keep the agent's long-term store there:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const memory = await runtime.volumes.create({ sizeMiB: 1024, name: "memory-u-42" });await using sbx = await runtime.sandboxes.create({  volumes: [{ volumeId: memory.id, path: "/memory" }],  labels: { user: "u-42" },});await sbx.exec("sudo chown runtime /memory");await sbx.exec("echo '- prefers weekly summaries' >> /memory/facts.md && sync");
Pythonfrom withruntime import Runtimeruntime = Runtime()memory = runtime.volumes.create(size_mib=1024, name="memory-u-42")with runtime.sandboxes.create(volumes=[{"volume_id": memory["id"], "path": "/memory"}],                              labels={"user": "u-42"}) as sbx:    sbx.exec("sudo chown runtime /memory")    sbx.exec("echo '- prefers weekly summaries' >> /memory/facts.md && sync")

A volume attaches read-write to one sandbox at a time, which suits one user's memory, or read-only to any number. Run sync after writes that must be kept: a sandbox whose lease runs out stops at once (storage). A volume is charged on its full size from creation, 153 microdollars per GiB-hour.

For a structured store, start the memory server from Runtime's MCP catalog inside the sandbox with sbx.mcp.start([{ id: "memory" }]) and give the agent its URL (MCP servers in a sandbox).

Checkpoints you can go back to

A snapshot saves the whole machine as it is, memory and processes included. Take one before a risky step, and start a new sandbox from it if the step goes wrong:

TypeScriptimport { Runtime, Sandbox } from "withruntime";const runtime = new Runtime();const agent = await Sandbox.getOrCreate("agent-u-42", { idlePauseSeconds: 600 });const before = await agent.snapshot({ name: "u-42-before-import", retentionDays: 30 });// ... the agent runs a migration that goes badly ...const restored = await runtime.sandboxes.create({ snapshot: before.id });console.log(restored.id);

A snapshot is copied off its server as soon as it is taken, so it survives the loss of that server. A sandbox with volumes cannot be snapshotted, so keep the two designs apart: pause and snapshot the agent's machine, or keep its memory on a volume.

What persistent agent memory needs

Need How Runtime covers it
The same agent for the same user Names unique per account; getOrCreate finds, wakes or makes it
RAM state kept between sessions Pause keeps memory and running processes
Fast return Wake on request, usually about half a second
Memory apart from the machine Volumes, attached at any path, kept until deleted
Undo Snapshots with 1 to 365 days of retention; fork for live copies
One user's memory kept from another A Firecracker microVM with its own kernel per sandbox
Low cost at rest No compute while paused; storage by the GB

What it costs

Take 1,000 users. Each one's 2 vCPU, 4 GiB agent runs 10 hours in a month, using on average 0.1 of a vCPU, and is paused the other 710 hours of a 30-day month with 0.5 GB of its own disk and memory stored:

TextCPU:     1,000 × 10 h × 0.1 vCPU × $0.025         = $25.00Memory:  1,000 × 10 h × 4 GiB × $0.0075           = $300.00Paused:  1,000 × 0.5 GB × $0.08 × 710 h / 720 h   = $39.44Total:                                              $364.44

About 36 cents a user a month. A 1 GiB memory volume per user would add 153 microdollars × 720 hours, about $0.11 each (pricing).

Start

Terminalnpx withruntime sandbox create --trial --name agent-demo --get-or-create --idle-pause 600

Approve the browser link the first command prints. Run the same line tomorrow and it prints the same sandbox's id.

Related: pause and resume a sandbox, sandbox snapshots, long-running agents, per-user dev environments.

Facts on this page were checked on 25 September 2026.