Memory Stores
The named stores an agent remembers into — the other half of retrieval, beside the project's documents.
Overview
A memory store is a container with a name, a description and tags. It holds memories: individual facts, each embedded so knowledge search can rank them against a query.
The split between documents and memory stores is what each is for. A document is reference material you supply — a handbook, a policy, a spec. A memory is what an agent learns while working: a customer's preference, a decision that was made, a correction. Both are searched by the same call and both feed an agent's retrieval configuration.
This module is a verbatim mirror of the runtime: every field, method, status code and error shape is the runtime's own, re-rooted under the project in the path.
See the OpenAPI spec for the full endpoint and schema reference, or browse it rendered under API Reference → Memory Stores.
Data Model
MemoryStore
| Field | Type | Description |
|---|---|---|
id | string | Public memory store ID (mstore_ prefix). |
project_id | string | The owning project. |
name | string | The store's name. Required on create. |
description | string, nullable | What this store is for. |
tags | object, nullable | Key-value tag map used to scope the store in knowledge search — see Selecting stores by tag. |
duplicate_threshold | number, nullable | Cosine similarity at or above which an incoming fact counts as already known and the write is skipped. null uses the algorithm constant — see What a write returns. |
supersede_threshold | number, nullable | Cosine similarity at or above which an incoming fact restates a known one that has changed, retiring it. null uses the algorithm constant. Must be lower than the effective duplicate_threshold. |
created_at | string (date-time) | |
updated_at | string (date-time) |
Key Concepts
One store or several
A memory store is a scope, so the useful question is what you want to be able to search separately. One store per customer keeps one customer's facts out of another's answers. One store per agent keeps a support agent from recalling what a sales agent learned — the choice Give an agent long-term memory makes. One store for the whole project is fine when neither separation matters.
Nothing enforces a convention here — the scope is whatever you make the container mean.
Selecting stores by tag
Knowledge search and an agent's knowledge_config both take
memory_store_ids to name stores directly — the form
Give an agent long-term memory
uses — and tags to select by label
instead. tags is a key-value map and every pair must match exactly; for
memories it matches at memory granularity, so a memory is returned when its
parent store's tags match or its own do.
Tagging is what makes the selection survive change: an agent configured with
tags: { team: "support" } picks up a new support store the moment it is
created, with no edit to the agent.
Writing to a store from an agent
An agent writes into a store when its knowledge_config.write_memory_store_id
names one — that is what makes the write_memory tool available to it during a
generation, as in
Limit what an agent may do. That door is the agent's to use mid-turn. The other door is the
store's own: a memory rule reads completed turns and mines
them for facts, so what the corpus accepts is decided where the corpus lives.
Every write into a store is consolidated against what it already holds — a fact that is already known is skipped, and one that restates a stored fact retires it — so a store accumulates knowledge rather than copies. The store is where that policy is set, through the two thresholds above; a memory has none of its own. See What a write returns.
Who may do what
Every route needs any project member. Deleting a store removes the memories inside it.
Examples
Create a memory store
- CLI
- SDK
- curl
naturali create-memory-store \
--project-id proj_V1StGXR8Z5jdHi6B \
--name "support-tickets" \
--description "What we learn while answering support tickets" \
--tags '{"team":"support"}'
const { data: memoryStore } = await naturali.memoryStores.createMemoryStore({
path: { project_id: 'proj_V1StGXR8Z5jdHi6B' },
body: {
name: 'support-tickets',
description: 'What we learn while answering support tickets',
tags: { team: 'support' },
},
});
curl -X POST https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/memory-stores \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "support-tickets",
"description": "What we learn while answering support tickets",
"tags": { "team": "support" }
}'
List the project's memory stores
- CLI
- SDK
- curl
naturali list-memory-stores \
--project-id proj_V1StGXR8Z5jdHi6B \
--tags team:support
const { data: memoryStores } = await naturali.memoryStores.listMemoryStores({
path: { project_id: 'proj_V1StGXR8Z5jdHi6B' },
query: { tags: ['team:support'] },
});
curl "https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/memory-stores?tags=team:support" \
-H "Authorization: Bearer $NATURALI_TOKEN"
Rename one
- CLI
- SDK
- curl
naturali update-memory-store \
--project-id proj_V1StGXR8Z5jdHi6B \
--memory-store-id mstore_V1StGXR8Z5jdHi6B \
--name "support-tickets-emea"
const { data: memoryStore } = await naturali.memoryStores.updateMemoryStore({
path: {
project_id: 'proj_V1StGXR8Z5jdHi6B',
memory_store_id: 'mstore_V1StGXR8Z5jdHi6B',
},
body: { name: 'support-tickets-emea' },
});
curl -X PUT https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/memory-stores/mstore_V1StGXR8Z5jdHi6B \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "support-tickets-emea" }'
Delete a store and everything in it
- CLI
- SDK
- curl
naturali delete-memory-store \
--project-id proj_V1StGXR8Z5jdHi6B \
--memory-store-id mstore_V1StGXR8Z5jdHi6B
await naturali.memoryStores.deleteMemoryStore({
path: {
project_id: 'proj_V1StGXR8Z5jdHi6B',
memory_store_id: 'mstore_V1StGXR8Z5jdHi6B',
},
});
curl -X DELETE https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/memory-stores/mstore_V1StGXR8Z5jdHi6B \
-H "Authorization: Bearer $NATURALI_TOKEN"