SokkoSokko
← Back to blog

Persistent State for AI Agents: Surviving Crashes and Restarts

Sokko Team10 min read

What state means for an AI agent

Here's the short version of how to give an ai agent persistent state across restarts: move the parts of the agent's memory that matter off RAM and onto durable storage, so a crash, a redeploy, or a nightly reboot doesn't erase what it learned. That's the whole job. The tricky part is knowing which pieces of state actually need to survive, and choosing the right home for each one.

"State" isn't a single blob. A running agent usually juggles several kinds at once, and they don't all live in the same place:

  • Conversation memory. The message history and any summarized context it uses to stay coherent across turns.

  • Working files. Scratch files, downloaded data, generated artifacts, a cloned repo it's editing. Often the largest chunk, and the most painful to lose.

  • Vector stores and embeddings. Retrieval indexes it built from documents, so it doesn't re-embed everything on every boot.

  • Task queues and job state. What it's supposed to do next, what's in flight, and what already failed.

  • Checkpoints. Mid-task progress markers so a long job can resume instead of starting from scratch.

  • Config and credentials. API keys and settings. These are usually injected at boot from a secret store, not something you write to disk yourself.

Not all of it deserves durable storage. A half-formed prompt sitting in a variable can vanish safely. A three-hour research run that just finished cannot. Separating the two is your first real decision, and it saves you from over-engineering.

Why in-process state dies on restart

By default, everything your agent holds in memory lives inside one process. When that process exits, for any reason, the memory goes with it. This surprises people because it "worked on my laptop" for days: the process just never stopped, so nothing was ever lost.

Production is different. Processes stop constantly, and not always because you asked:

  • A crash from an unhandled exception or an out-of-memory kill.

  • A deploy that replaces the old version with a new one.

  • A host reboot for a kernel patch.

  • A container getting rescheduled onto another node.

  • A cloud instance being recycled.

If the only copy of "what the agent has done so far" lived in RAM, all of it is gone after any of those events. The same applies to files written inside a container's own filesystem. Container filesystems are ephemeral by design: rebuild or reschedule the container and that scratch data disappears with it.

This is not a bug you fix, it's a property you design around. The twelve-factor app principles put it plainly: treat processes as stateless and disposable, and push anything that must last into a backing service. An agent is just a long-running process, so the same rule holds. Assume the process can die at any instant, then make sure the important state is somewhere the death can't touch.

So, How to Give an AI Agent Persistent State Across Restarts?

The pattern is always the same three moves, whatever storage you pick:

  1. Choose a durable store that outlives the process (a volume, a database, object storage, or an external service).

  2. Write state there as you go, at sensible checkpoints rather than only at the very end. After each completed step, each finished tool call, or on a timer.

  3. Read it back on boot. On startup, the agent checks the store, finds any prior state, and resumes instead of starting cold.

That third step is the one people forget. Persisting state is useless if the agent never loads it again. A durable agent's first action on boot should be "do I have unfinished work or existing memory?" before it does anything else.

There are five common places to put durable state, and most real agents use two or three of them together rather than picking one.

A mounted volume

A disk that lives outside the process and gets attached to it at runtime. The agent writes files to a path like /workspace, and that path survives restarts because the disk isn't part of the container. This is the simplest option for working files, checkpoints, and small local databases like SQLite. It's the closest thing to "just save a file and trust it'll be there next time."

A database

Postgres, MySQL, Redis, or a managed equivalent. Best for structured state: conversation history, task queues, job status, per-user memory. You get queries, transactions, and concurrent access, which a flat file can't give you. The cost is running (or paying for) the database.

Object storage

S3, Cloudflare R2, Google Cloud Storage, or a MinIO instance you host. Best for large or infrequently touched artifacts: generated files, backups of a vector index, big downloads. Cheap per gigabyte, effectively unlimited, but higher latency than a local disk, so it's a poor fit for state you touch every second.

A checkpoint file

A single serialized snapshot of the agent's progress, written to a volume or object store. For long multi-step jobs, you write a checkpoint after each step. If the agent dies at step 7 of 10, it reloads the checkpoint and resumes at step 8. Cheap to add, and it turns a catastrophic restart into a minor hiccup.

An external memory service

A managed vector database (Pinecone, Weaviate, Qdrant) or a dedicated memory layer. Best for semantic long-term memory and retrieval at scale. It's durable by definition because it's a separate service, but it's another dependency and another bill.

The durable options compared

Here's how the five stack up. Treat "latency" as rough and relative, not a benchmark.

OptionBest forLatencySurvives restart?Honest tradeoff
Mounted volumeWorking files, SQLite, checkpointsVery lowYesTied to one machine unless you use networked storage
DatabaseConversation history, queues, structured memoryLowYesYou have to run or pay for it
Object storageLarge artifacts, backups, big downloadsHigherYesToo slow for hot, per-step state
Checkpoint fileResumable long tasksLowYesYou must write resume logic yourself
External memory serviceSemantic long-term memory at scaleMediumYesExtra dependency and cost

A practical default for a single agent: put working files and checkpoints on a mounted volume, put conversation and task state in a small database, and reach for object storage or a vector service only when volume or scale forces it. Start simple, add layers when you feel the pain.

If you plan to run several agents on the same box, read running multiple AI agents on one server first, because shared state is where those setups quietly break. Two agents writing to the same volume path or the same database rows without isolation will corrupt each other's memory in ways that are miserable to debug.

A worked example: mounting a persisted volume

The most common durable pattern is a volume mounted at /workspace. Here's a Kubernetes persistent volume claim that requests 5 GiB of durable disk:

# pvc.yaml: a persistent volume claim for the agent workspace
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: agent-workspace
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Then you mount that claim into the agent's container at /workspace, so anything written there lands on the durable disk instead of the throwaway container filesystem:

# deployment.yaml (excerpt)
spec:
  containers:
    - name: agent
      image: my-agent:latest
      volumeMounts:
        - name: workspace
          mountPath: /workspace
  volumes:
    - name: workspace
      persistentVolumeClaim:
        claimName: agent-workspace

The same idea in plain Docker is a named volume, which persists even when the container is removed and recreated:

docker volume create agent-workspace

docker run -d --name my-agent \
  --restart unless-stopped \
  -v agent-workspace:/workspace \
  my-agent:latest

On the agent side, the code just treats /workspace as the durable home and checks it on boot:

import json, os

STATE_PATH = "/workspace/state.json"

def load_state():
    if os.path.exists(STATE_PATH):
        with open(STATE_PATH) as f:
            return json.load(f)
    return {"step": 0, "history": []}

def save_state(state):
    tmp = STATE_PATH + ".tmp"
    with open(tmp, "w") as f:
        json.dump(state, f)
    os.replace(tmp, STATE_PATH)  # atomic write, avoids half-written files

Two details worth copying. First, the write goes to a temp file and then does an atomic rename, so a crash mid-write can't leave you with a corrupt state.json. Second, load_state returns a sane default when there's no file yet, so the very first boot doesn't crash. Small habits, big payoff.

If your agent runs tools that generate or execute code, the same volume is where those artifacts should land, and it pairs closely with how you isolate execution. See AI agent sandbox and code execution for keeping that side safe while still persisting the useful output. For getting an agent deployed in the first place, deploying your first agent walks the earlier steps.

For the storage layer itself, the Kubernetes persistent volumes docs are the reference for how claims, access modes, and reclaim policies actually behave.

Common mistakes that lose state anyway

Even with durable storage wired up, a few habits quietly defeat it:

  • Only saving at the end. If you write state once, when a task finishes, a crash at 95% loses everything. Save incrementally.

  • Trusting the container filesystem. Writing to /tmp or the app directory feels persistent because it works until the first reschedule. Write to the mounted path, always.

  • Non-atomic writes. A crash halfway through a write can corrupt the file. Write to a temp file and rename.

  • Never testing recovery. If you've never killed the process and watched it resume, you don't actually know your resume path works. Test it on purpose.

  • Sharing one store between agents without isolation. Give each agent its own namespace, prefix, or volume so they can't overwrite each other.

How Sokko fits

If you'd rather not set up storage by hand for every agent, this is exactly what Sokko handles. It's managed hosting for AI agents. Every agent runs in its own private, isolated space, walled off from every other customer's, and anything it writes to its workspace is saved automatically on storage we manage. That state survives restarts, redeploys, and reboots, with no setup on your side. Your API keys are kept in secure storage and loaded in at boot, so credentials never sit on the agent's disk or leak into its files. There's also an optional org-wide shared-memory add-on for when several agents genuinely need to remember the same things.

You still control the important choices. Pick one of the four runtimes (OpenClaw, Hermes, Paperclip, or OpenSRE), bring your own model keys (Claude, GPT, or Gemini), and the agent boots in under a minute. If you want to try the persistence model without building the plumbing, Sokko starts from about $12/month per agent, and there are $100 in trial credits to kick the tires. The point is simple: your agent's storage is durable, so you can treat the agent process as disposable and stop fearing restarts.

Key takeaways

  • Agent "state" is several things (conversation, working files, vector stores, task queues, checkpoints), and only some of it needs to be durable.

  • In-process and container-filesystem state dies on every crash, deploy, or reboot. Design for it instead of hoping it won't happen.

  • The durable pattern is always: pick a store that outlives the process, write to it during the work, and read it back on boot.

  • Volumes, databases, object storage, checkpoint files, and external memory services each fit different jobs. Most agents combine two or three.

  • Write atomically, save incrementally, and actually test that your agent resumes after you kill it.