← ALL POSTS

Engineering · Oct 21, 2026 · 8 min read

How to Give AI Agents Memory That Survives Restarts

IR
Isabella Reed
COO & Growth, camelAI
How to Give AI Agents Memory That Survives Restarts

An agent that forgets after a deploy may have kept its conversation only in the process that served the request. When that process exits, the next request starts without that history.

"AI agent memory" covers several different things, and many forgetting bugs come from mixing them up. This guide separates them, shows a common way agents lose state, and walks through keeping a conversation across sessions, restarts, and users.

What counts as memory for an AI agent

AI agent memory is information an application stores and makes available to an agent across model calls or sessions. Short-term memory usually means working context; long-term memory persists beyond a session. You may also see episodic memory for past interactions, semantic memory for facts, and procedural memory for instructions or skills.

An ordinary model request does not automatically inherit your application's previous conversation. Your app, framework, or provider must retain that state and make the relevant parts available to the next request.

What an agent memory system needs to store

The table below is a practical breakdown of implementation responsibilities, not five mutually exclusive scientific categories.

KindWhat it isHow long it lastsTypical failure
Context windowThe text sent to the model on this callOne model callThe request exceeds the limit, or the application truncates or summarizes it
Conversation historyThe stored record of messages and tool resultsAs long as you store itKept in process memory, lost on restart
FilesDocuments, notes, and outputs the agent reads and writes. Can hold learned facts or instructions tooUntil deletedWritten to local disk on a server that gets replaced
Retrieval indexA searchable index over a corpus, often using embeddingsAs long as the index existsMistaken for conversation history
Learned memoryFacts the agent or application chooses to keep about a user or taskUntil edited or removedStale facts nobody can inspect or correct

These are separate problems. A vector database does not stop your agent forgetting the last message. Durable history does not let it search ten thousand documents.

Why agents forget

A common version looks like this:

# The conversation lives in this list, in this process.
messages = []

def chat(text):
    messages.append({"role": "user", "content": text})
    reply = model.generate(messages)
    messages.append({"role": "assistant", "content": reply})
    return reply

It works on a laptop. In production it can break in four ways:

  • Restarts and deploys. The list is gone.
  • More than one server. The second request lands on a server that never saw the first.
  • More than one user. Without a key per conversation, users share or overwrite each other's history.
  • Long conversations. The list outgrows the context window.

The first three have the same fix: give the conversation a stable identity and a home outside the process that handles requests.

Give each conversation a stable identity

Pick an identifier you already have, such as a user id, a ticket id, or a thread id, and store history under it. You can do this yourself with a database table keyed by that id and code that loads and saves on every turn. Frameworks call this a session or a checkpointer.

A hosted agent runtime does the storing for you. The example below uses camelRun, our hosted AI agent runtime, where the identifier is the agent's key.

About this example. The code is adapted from the camelRun documentation, and its names and options were checked against the Python SDK source (camelai-run 0.18.1) on October 21, 2026. The scripts were syntax-checked; the restart test has not been exercised against a live account. Run it against your own account to confirm the behavior.

You need Python 3.11 or later and an API key from the quickstart.

pip install camelai-run
export CAMELAI_API_KEY=art_...

Save this as remember.py:

import asyncio
from camelai_run import Agents

async def main():
    async with Agents() as agents:  # reads CAMELAI_API_KEY
        agent = await agents.upsert(
            "memory-demo-4412",
            instructions="You are a concise assistant.",
        )
        run = await agent.run("My order number is 4412. Remember it.")
        print(run.text)

asyncio.run(main())
python remember.py

upsert creates the agent the first time. After that, the same key returns the same agent and applies any configuration you pass, such as changed instructions. Its history is kept by the runtime, not by this script. See Concepts for how keys work.

Test it: restart, then ask

Do not take persistence on trust. Test it with two separate processes.

Let remember.py exit. Then save this as recall.py:

import asyncio
from camelai_run import Agents

async def main():
    async with Agents() as agents:
        agent = await agents.upsert(
            "memory-demo-4412",
            instructions="You are a concise assistant.",
        )
        run = await agent.run("What is my order number?")
        print(run.text)
        print(await agent.history())  # the stored record

asyncio.run(main())
python recall.py

The second process shares nothing with the first except the key and the account. Both must use an API key for the same camelRun account; the same key is simplest.

Check two things. The reply should mention 4412. More importantly, the printed history should contain the first script's message. A model's answer alone is not a reliable persistence test, since models can guess or decline. The stored record is.

Whatever you build on, this is the test that matters: stop the process, start a new one, and confirm the earlier messages are still there.

Keep users apart

Run recall.py again with the key changed to memory-demo-9999. That agent should have no record of the order number.

Treat this as a smoke test, not proof of security. Separate keys prevent accidental conversation mixing. They do not authorize access: your backend must authenticate the caller, check that they own the requested conversation, and derive the key from trusted records. Never build a key from a value the client submits unchecked.

In a real application, namespace keys by what you need to separate, such as tenant, user, and thread. camelRun keys are 1 to 80 letters, digits, underscores, and hyphens.

const agent = await agents.upsert(`thread-${thread.id}`, {
  subject: thread.ownerId,         // whom the agent acts for
  context: { org: thread.orgId },  // claims your tools authorize against
});

subject and context are fixed when the agent is created and must come from your backend. The docs add one caution: an agent shared by several people shares its whole conversation with all of them, so keep private data in single-person agents. See Agents for many users.

Long conversations and compaction

History that keeps growing eventually exceeds the context window. A common answer is compaction: older turns are replaced, for the model's purposes, by a summary, while recent turns stay verbatim.

In camelRun, history is compacted when it gets long, and the stored history still keeps every message. That distinction matters:

  • What you can read back is the full record.
  • What the model sees in a long conversation is a summary of the early part plus the recent part.

So durable history is not perfect recall. A detail from two hundred turns ago may survive only as a line in a summary.

Files are a second kind of memory

Each camelRun agent has a workspace at /workspace by default, with read, write, edit, ls, glob and grep file tools. Files persist with the agent, so notes written in one run are there in the next. A volume can also be mounted into several agents, read-only or read-write, which is one way to share a handbook across every user's agent. See Files.

Files keep facts outside the compacted transcript, provided the agent or your application retrieves them when needed. For authoritative account IDs or financial decisions, keep the source of truth in your application database and expose scoped access through tools.

Stored facts go stale. Decide who can correct them, and store only what the feature needs.

What durable history does not give you

  • No semantic search. camelRun has no built-in vector retrieval, and its migration guide lists that as a gap. If you need retrieval over a large corpus, run a search service and expose it as a tool.
  • No automatic fact learning. History records what was said. It does not decide what is worth remembering about a user.
  • Storage is billed. On camelRun, history and files cost $0.10 per GB-month as of October 21, 2026, including while an agent is asleep. Check the live pricing.

A checklist for agent memory

  1. Name each kind of memory your agent needs.
  2. Key every conversation by an id from your own trusted records.
  3. Store history outside the process that handles requests.
  4. Run the two-process restart test and inspect the stored history.
  5. Authorize access to each conversation in your backend.
  6. Decide where must-keep facts live, and do not rely on summaries for them.
  7. Plan how stale facts get corrected.
  8. Delete an agent's data when the user or thread is deleted.

Next steps

To run the example, start with the camelRun quickstart. When you are ready to ship, How to Deploy AI Agents with Persistent State covers tools, workers, approvals, and spend limits. camelRun is open source if you would rather run it yourself.

CAMELRUN · HOSTED AGENT RUNTIME

Run your AI agents on camelRun.