Skip to content
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. Put any memory that must outlive the sandbox on a volume.

On Runtime, a paused agent keeps everything it had in RAM, its running processes and its files, while you have credit. A paused agent pays only for storage while it sleeps: $0.08 per GB per 30-day month for the blocks it alone owns, at the rates in force on 26 October 2026. Its variables, open files and background servers are 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 While you have credit (7 days without credit) $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 while you have credit, up to a year (7 days without credit) $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. Add a snapshot when you want to return to a known point.

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

Name the sandbox after the user or the thread. getOrCreate returns the same sandbox every time. If the sandbox is paused, it wakes the sandbox first:

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. Also write the agent's own notes to a file, such as /workspace/memory.md. You can then read them with files.readText, and they survive a restart.

A paid pause is kept while your account has credit. Or it is kept for the 1 to 365 days you set with POST /v1/sandboxes/{id}:retention. Each pause replaces the saved state before it (pricing). Pauses without credit 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 that user, 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. That suits one user's memory. It can also attach read-only to any number of sandboxes. Run sync after any write that must be kept. A sandbox whose time limit or credit runs out with "stop" stops immediately (storage). A volume is charged on its full size from creation, at 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" }]). Then 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, including its memory and processes. Take a snapshot before a risky step. If the step goes wrong, start a new sandbox from it:

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 survives the loss of its server once its off-server copy has been checked. Then backedUp is true. A sandbox with volumes cannot be snapshotted. Keep the two designs separate. Either 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 The next request wakes it, with memory and processes
Memory apart from the machine Volumes, attached at any path, kept until deleted
Undo Snapshots kept while you have credit; 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. The agent is paused the other 710 hours of a 30-day month, with 0.5 GB of its own disk and memory stored:

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

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

Start

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

Approve the browser link that 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 26 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card