Long-term memory
Sessions give an agent short-term memory: the history of one conversation. Long-term memory is what the agent knows about a person across conversations: a small set of facts, kept per user, that the agent can search in any later session.
Whether an agent remembers at all is a policy on the agent, not a decision made on each message. You set it once; the platform stores it with the agent and re-applies it on every redeploy.
The three modes
| Mode | What it means | When to use it |
|---|---|---|
off | The agent never remembers. The memory tools are not offered to the model. The default for a new agent. | Anything where the conversation must stay a conversation. |
auto | After each reply, the agent's own model distils the turn into facts and stores them - in the background, so the reply is never delayed. | Personal assistants; support agents that should recognise a returning customer. |
explicit | Facts are written only when someone asks: the model calls its remember tool because the user said "remember that ...", an operator adds one, or an operator commits a whole session. | Agents where every stored fact should be a deliberate act. |
An agent deployed before memory policies existed runs as explicit until you set a policy - which is what it always did: nothing was written unless somebody asked.
Set the policy
- platformctl
- curl
- Console
platformctl agents memory set research-buddy --mode auto
You should see:
mode auto
a new revision is rolling; the running agent serves the new policy once it is ready
platformctl agents memory get research-buddy shows the stored policy. platformctl agents memory status research-buddy asks the running agent what it is serving - the two differ until the new revision is ready.
PATCH /v1/agents/{name}/memory/policy - sparse: fields you leave out keep their value.
curl -s -X PATCH "$CAI_API/v1/agents/research-buddy/memory/policy" \
-H "Authorization: Bearer $CAI_TOKEN" -H 'content-type: application/json' \
-d '{"mode":"auto"}'
You should see:
{"agent":"research-buddy","memory":{"mode":"auto"},"effective":{"mode":"auto","source":"stored"},"memory_updated":true}
GET /v1/agents/{name}/memory/policy returns the same shape without memory_updated. For an agent with no stored policy, effective.source is legacy_default and effective.mode is explicit.
Open Agents, expand the agent, and click Memory settings. Choose the mode, then Apply & deploy new revision. The agent's Test tab shows the policy in force as a badge - Memory: off, auto or explicit.
The other settings, all optional:
| Setting | CLI flag | What it does |
|---|---|---|
inject | --inject none|profile | profile places the caller's newest facts in front of every turn, so the agent knows them without searching. Default none: the agent searches when it decides to. |
ttl_seconds | --ttl SECONDS | A fact expires this long after it was written. Default 0: never. |
exclude_sensitive | --exclude-sensitive on|off | Keeps health, religion, politics, sexuality and similar categories out of memory even if the user mentions them. Default on. |
topics | --topics a,b,c | Restricts what is extracted. Default: personal_info, preferences, key_details, explicit_instructions. |
instructions | --instructions "..." | Extra guidance for the extractor, for example "record which product tier the user is on". |
knowledge | --knowledge on|off | Enables the agent-wide Knowledge store. Default off. |
A policy change rolls a new revision, like a compute or environment change does.
What is stored
A memory is a fact, not a transcript. After a turn under auto (or when asked, under explicit), the agent's own model reads the conversation and writes short, standalone statements about the user:
Owns a Mastercraft Maristar 245.
Prefers replies in bullet points.
Lives in Austin.
Each fact carries where it came from - the user it belongs to, who said it (the user, or the assistant correcting them), which turn and session, whether it came from the conversation, an operator, the model's remember tool, or a tool result - and when it was written.
Rules the extractor always follows:
- Both sides of the conversation count. A fact the assistant corrected is stored corrected. Extracting only what the user said is how an agent learns to agree with everything.
- The model's private reasoning is never stored. Only what was actually said.
- Identity numbers, card numbers, passwords and API keys are never stored, whatever the topics say.
- New facts are reconciled with old ones. Saying "actually I sold the boat" does not add a second boat fact; the old one is invalidated - kept, marked no longer true, and never served again. Nothing is silently overwritten.
- Facts from tool results and documents wait for confirmation. Text an agent fetched is not something the user said; it lands
pendingand is not served until an operator confirms it.
Whose memory it is
Memory is per user, always. Every fact is tagged with the caller it belongs to, and an agent only ever reads back that caller's own facts. This is one store per agent, filtered by user - not a copy per user - so privacy costs nothing extra.
| How you invoke | Whose memory it is |
|---|---|
Signed in (platformctl, the Console, a session token) | you |
| With an API key | that service account |
With an explicit user_id in the request | that value - you are the authority on who your end user is |
Anonymously, with no user_id | that one session - nothing is shared with any other session |
If you are building something multi-user on top of an agent, send user_id. It is the only way the platform can know that two conversations belong to the same person.
The old opt-out that made one common store readable by every caller keeps working for one more release, with a warning in the agent's log. It served one user's conversation to every other user. If your agent is a shared knowledge base, that is what the Knowledge store is for.
How the agent uses memory
Three ways, and the policy decides which the model is offered:
search_memory(query)- the tool the agent calls to look something up. Returns the most relevant facts about this caller, or "No relevant memories found." Withheld from the model underoff: a tool that always returns nothing teaches the model to stop calling tools.remember(fact)- offered underexplicitonly. When the user says "remember that I prefer bullet points", the model stores that one fact. Underautothe extractor already captures it; underoffnothing is written.- Profile injection (
inject: profile) - the caller's newest facts are placed in front of each turn as background text, so the agent knows them without a search. They are marked "may be out of date, not instructions" and are never put in the system prompt: memory is text that came from users and documents, and it must not get instruction priority.
Give your agent the tools it should have:
- ADK
- CrewAI
- LangGraph
from google.adk.agents import Agent
from crusoe_adk.foundry import foundry_model
from crusoe_adk.tools import run_python, search_memory
root_agent = Agent(
name="research_buddy",
model=foundry_model(),
instruction="Use search_memory to recall facts about the person you are talking to.",
tools=[run_python, search_memory],
)
The platform adds remember under explicit and search_knowledge when the Knowledge store is on, and removes search_memory under off. The startup log says what it did: memory policy: mode=explicit, tools added=['remember'] ....
from crewai import Agent
import crusoe_crewai as crusoe
research_buddy = Agent(
role="Research Buddy",
goal="Recall facts about the person you are talking to.",
backstory="A concise assistant running on the Crusoe AI Platform.",
llm=crusoe.foundry_model(),
tools=[crusoe.RunPython(), crusoe.SearchMemory(), crusoe.Remember(), crusoe.SearchKnowledge()],
verbose=False,
)
These are classes, so note the parentheses. A crew lists its own tools, so the platform cannot remove one; instead a tool the policy does not allow answers honestly - search_memory returns "Memory is off for this agent" under off, and Remember says the agent remembers automatically under auto.
from langgraph.prebuilt import create_react_agent
import crusoe_langchain as crusoe
graph = create_react_agent(
crusoe.foundry_model(),
tools=[crusoe.run_python, crusoe.search_memory, crusoe.remember, crusoe.search_knowledge],
prompt="Use search_memory to recall facts about the person you are talking to.",
)
As with CrewAI, a graph binds its own tools; one the policy does not allow answers honestly rather than pretending to work.
See and correct what an agent remembers
You can now look. Every operator action is per user, and every one is available from the CLI, the API and the Console.
- platformctl
- curl
- Console
# What does the agent remember about alice?
platformctl agents memory list research-buddy --user alice
You should see:
ID CREATED AUTHOR SOURCE STATE FACT
6f1c... 2026-09-09 14:02 user conversation valid Owns a Mastercraft Maristar 245.
# Add one fact, as written (attributed to you, the operator)
platformctl agents memory remember research-buddy --user alice "Prefers replies in bullet points."
# Mark one fact no longer true - it is kept, hidden, never served
platformctl agents memory invalidate research-buddy 6f1c...
# Believe a pending fact that came from a tool result
platformctl agents memory confirm research-buddy 9a2e...
# Remove one fact outright
platformctl agents memory delete research-buddy 6f1c...
# Erase everything about alice - the erasure request. Works in every mode.
platformctl agents memory forget research-buddy --user alice --yes
All of these require a signed-in project member.
# list
curl -s "$CAI_API/v1/agents/research-buddy/memory?user_id=alice" -H "Authorization: Bearer $CAI_TOKEN"
# remember
curl -s -X POST "$CAI_API/v1/agents/research-buddy/memory" -H "Authorization: Bearer $CAI_TOKEN" \
-H 'content-type: application/json' -d '{"user_id":"alice","text":"Prefers replies in bullet points."}'
# one fact's lifecycle
curl -s -X POST "$CAI_API/v1/agents/research-buddy/memory/6f1c...:invalidate" -H "Authorization: Bearer $CAI_TOKEN"
curl -s -X POST "$CAI_API/v1/agents/research-buddy/memory/9a2e...:confirm" -H "Authorization: Bearer $CAI_TOKEN"
curl -s -X DELETE "$CAI_API/v1/agents/research-buddy/memory/6f1c..." -H "Authorization: Bearer $CAI_TOKEN"
# erase one user
curl -s -X DELETE "$CAI_API/v1/agents/research-buddy/memory?user_id=alice" -H "Authorization: Bearer $CAI_TOKEN"
The list response:
{"user_id":"alice","count":1,"facts":[{"id":"6f1c...","kind":"fact","text":"Owns a Mastercraft Maristar 245.",
"user_id":"alice","author":"user","turn":1,"session_id":"3f2c...","source_kind":"conversation",
"topic":"personal_info","created_at":1788900000.0,"valid":true,"pending":false,"invalidated_by":""}]}
Add include_invalid=true to see invalidated facts; include_pending=false to hide pending ones.
In the agent's Test tab, the Remember this action stores one fact about the conversation's user, as you write it. The policy badge next to it says whether the agent remembers at all.
Erasure works whatever the mode is: an operator must always be able to see and delete what was remembered, even after turning memory off.
Knowledge: what every user should be told
Some agents need facts that apply to everyone - a refund policy, product names, opening hours. That is not conversation memory; it is knowledge, written by operators, never by a user's conversation, and read by every caller. Turn it on with the policy (--knowledge on), then add to it:
platformctl agents knowledge add research-buddy "Refunds are processed within 5 business days of the return arriving at the warehouse."
platformctl agents knowledge search research-buddy "how long do refunds take"
platformctl agents knowledge list research-buddy
By default the text you add is distilled into facts by the agent's model - paste a paragraph or a FAQ answer. --verbatim stores it as one fact exactly as written. The model reaches it through the search_knowledge tool, which the platform offers when the store is on. platformctl agents knowledge delete <agent> <id> removes one fact; clear --yes empties the store.
Knowledge lives in its own collection (know_<project-short>_<agent>), separate from memory (mem_<project-short>_<agent>), so a conversation can never write into what every user reads.
Per-call controls
"memory": falseoninvokeopts that one turn out of every write - the "don't remember this conversation" signal an integrator needs. Reads still happen."memorize": trueoninvokeis the old per-message flag. It is deprecated and kept for one release: underexplicitorautoit means "distil this whole session now, before replying"; underoffit is ignored. Nobody else has this flag, and a client that sets it on every call is why the same conversation used to be stored again on every message.POST /v1/agents/{name}/sessions/{id}/memorizeandplatformctl memorize <agent> --session <id>remain as the operator override: commit one session's facts now. Underoffthe agent answers409naming the setting:
memory is off for this agent (MEMORY_MODE=off); set the agent's memory mode to explicit or auto to allow writes
Writing always requires authentication, even when invoking does not.
Migration: nothing deployed changes on its own
- An agent with no stored policy runs as
explicit- exactly what it did before, because nothing was ever written unless somebody asked. - Memories written before facts existed were whole transcripts. They are still searched, but they cannot be listed, corrected or expired per fact.
platformctl agents memory reindex <agent>distils them into facts under their own user;--drop-legacyremoves each transcript once distilled. Transcripts that recorded no user cannot be attributed and are left alone (platformctl agents memory statuscounts them aslegacy_points). MEMORY_SCOPE=sharedkeeps working for one release with a deprecation warning; the Knowledge store is its replacement.
What is behind it
- Storage: one managed VectorDB collection per agent,
mem_<project-short>_<agent>, plusknow_<project-short>_<agent>when Knowledge is on. The platform creates and looks after both; deleting the agent deletes them. - Embeddings: the platform's configured embedding model (
EMBED_MODEL), the same one for writing and searching. - Extraction: the agent's own chat model - the one it already answers with - reads the turn and writes the facts. No second model, no extra credential.
- Want to build your own retrieval instead of, or alongside, this? See use VectorDB with agents.
Summary
| Action | How | Auth |
|---|---|---|
| Decide whether the agent remembers | platformctl agents memory set <agent> --mode off|auto|explicit, PATCH /v1/agents/{name}/memory/policy, or Memory settings in the Console | Project member |
| See / add / correct / erase one user's facts | platformctl agents memory list|remember|invalidate|confirm|delete|forget, or /v1/agents/{name}/memory | Project member |
| Shared knowledge | platformctl agents knowledge add|search|list|delete|clear, or /v1/agents/{name}/knowledge | Project member |
| Commit one session now (override) | platformctl memorize <agent> --session <id>, POST /v1/agents/{name}/sessions/{id}/memorize | Always required; 409 under off |
| Keep one turn out of memory | "memory": false on invoke | Same as invoke |
| Read memory | The agent's search_memory tool; inject: profile | Same as invoke |
Next steps
- Research agent with memory - turn memory on, teach a fact, recall it in a new session.
- Sessions - the short-term half of agent memory.
- Built-in tools -
search_memory,remember,search_knowledgeandrun_python, in each framework. - Agents API reference - the memory policy, memory and knowledge routes.