"Persistent" is doing too much work
If you read the marketing pages for any AI coding tool released in the past year, "persistent agent" is in the headline. What it actually means varies wildly:
- Chat history persistence. The conversation thread is saved. The agent re-reads the last N messages on each call. Most tools mean this.
- Workspace persistence. The code files survive across sessions. Less common than you'd think: some tools wipe the filesystem each session.
- Agent-side note persistence. The agent itself can leave notes for its future self, scoped to the project. Few tools have this.
- Cross-device persistence. The same agent state is available whether you're on web or iOS. A tool that runs only on your laptop, with nothing syncing it, can't have this.
VibeKit's agent has all four. They're not the same thing, they live in different storage backends, and they fail in different ways. Calling all of them "memory" is what makes the category confusing.
The four layers, what's in each
Here's the actual taxonomy I've ended up with after running this in production for a few months.
1. Chat history (durable, in Postgres)
Every user message, every agent response, every system event tied to an app gets a row in agent_messages. Indexed by app_id, ordered by created_at. This is the "did you say this two weeks ago" memory.
The user sees this in the chat UI on every device. Open the iOS app, scroll up, and the conversation from your laptop is there. Same app on the web, same history.
The agent itself works from its own session: one ongoing conversation per app, kept by the agent runtime (OpenClaw), with no timer that expires it. Postgres is the backstop. If a very long session gets trimmed, the agent's next turn is seeded with a recap of the recent chat from these rows, so it picks up mid-conversation instead of starting cold.
What this is good for: continuity, "as I mentioned earlier", referring back to user-stated preferences.
What this is not: semantic search over your entire codebase. Chat history is linear and not semantically indexed.
2. The workspace (durable, on EFS)
Each app's code lives in /mnt/efs/workspaces/app-<id>/, a real filesystem the agent reads, writes, and runs builds against. The app's container mounts it. The agent's editor tools read and write here. git operates on this directory.
This is "the codebase" in the literal sense. Files persist until the user deletes the app. The agent can cat, grep, and ls like a normal Unix process.
What this is good for: "what did this file say yesterday?", line-level edits, multi-file refactors with awareness of the whole tree.
What this is not: automatic summarization. The agent has to actually look at the files to know what's in them.
3. Agent-side notes (semi-durable, in workspace files)
The agent keeps notes for its future self in plain files in the workspace, next to a few files the platform writes for it. The one that sets the rules is AGENTS.md, a per-app contract that scopes behavior. The full set:
AGENTS.md: the contract. What kind of app this is, how to build and deploy it, what never to touch. The platform writes it and keeps it read-only to the agent, so a chat message can't talk the agent into rewriting its own rules.MEMORY.md(plus dated logs inmemory/): the agent's long-term notes. Architecture decisions, known issues, what the user prefers. The agent reads and searches it for real work and updates it when it learns something durable.STATUS.md: live infrastructure facts (container state, recent logs, scheduled tasks), refreshed by the platform when you message the agent, at most every five minutes.TOOLS.md: what tools and APIs the agent can use. Platform-written and read-only.SOUL.md/IDENTITY.md/USER.md: the agent's persona and the user's preferences for this app (a different agent per app). These belong to the user, and the agent edits them on request.
These are real files in the workspace. They survive deploys, they survive container restarts, they survive the user logging out and back in months later. They're the agent's memory of itself.
What this is good for: "remember not to use yarn, the user prefers pnpm", "remember the auth flow you set up last week".
What this is not: infallible. The agent can lie to itself in these files, or write notes that age poorly. We treat them as advisory, not authoritative.
4. The model's context window (ephemeral, per-call)
This is the only memory that's actually scoped to a single API call. The model gets a fixed context window on each call: hundreds of thousands of tokens or more on current frontier models, though we trim a session well before that, at about 110K. Inside that window, the agent has everything it needs for the current turn:
- System prompt (instructions + persona)
- The session so far (the ongoing conversation, with old tool results pruned)
- Read files (the workspace files the agent decided to look at)
- Tool results from this turn
That window resets on every call. There's no "memory" inside it, just whatever we put there.
This is the layer that's most often confused with "persistent memory." It isn't. The other three layers are what make persistence possible by reconstructing the window on each call.
What we deliberately let the agent forget
Persistence is a knife with two edges. Some things should not persist:
- Half-formed reasoning. If the agent went down a wrong path and the user redirected it ("no, don't do that"), we don't want the wrong path to keep showing up in future prompts. Chat history captures the redirect; the bad reasoning gets diluted by everything that comes after.
- One-off tool output. Tool results (the actual JSON from a
fetch, the output of anls -la) live in the context window while they matter, then get pruned from the session. Anything worth keeping belongs inMEMORY.mdas a note. Keeping every result verbatim would bury the conversation. - Secrets. API keys, tokens, credentials. App environment variables are stored encrypted per user, and the agent's own platform credentials live outside the workspace, injected as environment variables the agent can use but can't rewrite. The read-only
AGENTS.mdtells the agent never to expose a key. - User regret. If the user says "actually delete that file" or "undo that commit", we let them. Persistence shouldn't be a roach motel.
The principle: persist what helps the agent be coherent across time, forget what wastes context window or creates risk.
How this fails
A few honest ways persistence breaks in practice:
- Workspace ownership drift. EFS / NFSv4 + container UID mismatches caused some files to become
nobody:nobody-owned, which the agent then couldn't overwrite. We solved this with an EFS Access Point that forces UID 989, but it was a real bug. - Note rot. Agent-side notes (
MEMORY.mdespecially) go stale when the code changes underneath them, and nothing rewrites them for the agent.STATUS.mdis the exception that proves the point: the platform keeps rewriting it in the background when you message the agent (no more often than every five minutes), so infrastructure facts there can't rot for long. When a note and the code disagree, the code is right. - Chat history bloat. A long-running app can collect thousands of messages, far more than any context window holds. Old tool results get pruned as the session grows, and past about 110K tokens of context we trim it, seed the next turn with a short recap of the recent chat, and tell the user it happened. The workspace and
MEMORY.mdcarry everything older.
What this enables
When all four layers are working, the agent behavior you get is:
- Open the iOS app a week later → "where did we leave off?" → agent has the answer
- Push a commit to the app's main branch from Cursor on your Mac → the app redeploys from it and the workspace catches up → next iPhone agent session knows about it
- Tell the agent on Monday "we're using pnpm for this project" → on Friday it's still using pnpm
- Crash a container → restart from the same EFS workspace, no loss
That's what "persistent agent" should mean. Not just "longer chat window."
If you want to see the layered model in action, start a project and come back to it a week later. Watch the agent re-orient itself. The persistence isn't a feature; it's the substrate the agent stands on.