Does LlamaIndex have built-in memory?
Yes, but the current API is more specific than the old “chat memory” examples. The `Memory` class assembles the context an agent sees: recent chat history within a token limit, plus optional memory blocks that inject static facts, extracted facts or vector-retrieved messages. A `ChatStore` persists the underlying messages so a later session can load them.
That is a memory toolkit, not a managed memory product. LlamaIndex gives you the interfaces and the retrieval mechanics. Your application still decides which facts become durable, how conflicting facts are merged, which tenant owns a record, how long it is retained and how deletion propagates to every derived copy.
What is the difference between Memory, ChatStore and VectorStoreIndex?
These three layers answer different questions. `Memory` decides what enters the model context for this run. `ChatStore` saves messages so a later run can reload them. `VectorStoreIndex` retrieves documents or passages for retrieval-augmented generation. A document index is not a durable memory of the user, and a chat history is not automatically a corrected fact store.
| Layer | Primary question | What it does not solve |
|---|---|---|
| Memory | What context should this agent see now? | Long-term governance, cross-framework sharing |
| ChatStore | Where are the messages stored between sessions? | Fact extraction, merge, relevance and deletion policy |
| VectorStoreIndex | Which documents are relevant to this query? | User identity, correction, retention and provenance |
| External memory API | Which durable facts and relations should be recalled across products? | The source system of record for accounts and permissions |
How does the LlamaIndex Memory class work?
The current guidance uses `Memory.from_defaults()` rather than the deprecated `ChatMemoryBuffer`. The class keeps short-term chat history under `token_limit`, with `chat_history_token_ratio` controlling how much of that budget belongs to recent messages. When the ratio is exceeded, the oldest messages are dropped from the active context. You can also call `memory.put_messages()` and `memory.get()` directly when you want to manage the history yourself.
The important detail is that the token limit is a context budget, not a retention policy. Dropping the oldest message from the active prompt does not delete it from a chat store, a vector index or an external memory service. Keep the context budget, the persistence layer and the deletion policy separate.
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.memory import Memory
memory = Memory.from_defaults(
session_id="support-user-4821",
token_limit=40000,
chat_history_token_ratio=0.7,
)
agent = FunctionAgent(llm=llm, tools=tools)
response = await agent.run(
"What did we decide about the migration?",
memory=memory,
)Which LlamaIndex memory blocks should you use?
The Memory class can compose blocks with different priorities. A static block injects fixed context, such as a product name or a core instruction. A fact-extraction block uses an LLM to turn chat history into a bounded set of facts. A vector-memory block stores and retrieves batches of past messages by similarity to the current query. Each block has a different failure mode, so enable only the ones that support a measured behavior.
| Block | Use it for | Watch for |
|---|---|---|
| StaticMemoryBlock | Stable facts that should always be present | Staleness, token cost and conflicting source-of-truth data |
| FactExtractionMemoryBlock | Turning conversation into a bounded fact list | Extraction errors, duplicate facts and lost provenance |
| VectorMemoryBlock | Recalling relevant earlier messages | Similarity without correctness, ordering and stale context |
| Chat history | Continuity for the current task | Token growth, compaction and accidental permanence |
A memory block changes what the model sees; it does not create an authorization boundary, a retention rule or a deletion guarantee.
How do you persist LlamaIndex memory across sessions?
Pass a `chat_store` to `Memory` when messages must survive a process restart. LlamaIndex documents a SQLAlchemy-backed chat store for SQL databases plus the `AsyncDBChatStore` interface for custom storage. A stable `session_id` selects the conversation; the store holds the messages that belong to it.
Do not treat `session_id` as a security token. It is a lookup key. Resolve the authenticated user and tenant before choosing or accepting a session ID, and test that a caller cannot read another tenant’s history by guessing or reusing a key.
from llama_index.core.memory import Memory
from llama_index.storage.chat_store.postgres import PostgresChatStore
chat_store = PostgresChatStore.from_uri(
uri="postgresql+asyncpg://app:secret@db/app",
)
memory = Memory.from_defaults(
session_id=f"tenant:{tenant_id}:user:{user_id}",
token_limit=30000,
chat_store=chat_store,
)How should LlamaIndex memory map users and tenants?
Use the narrowest safe scope and make the tenant the outer boundary. A practical order is tenant, user, agent and task. Store the scope with every message or fact, not only inside the session ID string. Then filter on it when loading memory, retrieving from a vector index or writing to an external service.
LlamaIndex does not know which tenant is allowed to read a session. The application must resolve identity from its own authentication context and reject a mismatched tenant before the memory layer is called. If the same memory is shared with another framework, keep the scope names consistent across both implementations.
| Scope segment | Example | Rule |
|---|---|---|
| Tenant | `tenant:acme` | Required on every production read and write |
| User | `user:dana` | Required for personal memory |
| Agent | `agent:support` | Separates role-specific context |
| Task | `task:migration` | Limits temporary context to one initiative |
| Session | `session:4821` | Selects one conversation, not an authorization grant |
When do you need an external memory layer with LlamaIndex?
The native Memory class and chat store are enough when one LlamaIndex application owns the data, the team is comfortable owning extraction and retrieval quality, and the product already has a complete lifecycle for identity, correction and deletion. Add an external memory service when several frameworks, products or agent runtimes need the same durable user context.
| Requirement | Native LlamaIndex is enough when… | External memory is better when… |
|---|---|---|
| Runtime | One LlamaIndex application owns the memory | LangGraph, OpenAI SDK, CrewAI or several services share it |
| Extraction | The team wants to own fact extraction and merging | Managed extraction, conflict handling and token budgeting are required |
| Identity | Session IDs map cleanly to existing product IDs | One contract must cover user, agent, project and tenant scopes |
| Lifecycle | A custom deletion path is acceptable | Centralized correction, export and deletion are hard requirements |
| Portability | The application can be changed with the storage layer | Memory must survive a framework migration |
How do you test LlamaIndex memory before production?
Test the context assembly and the persistence separately. First verify that a new session for the same user loads the intended history and facts. Then change a fact, start another session and confirm the new value wins. Finally, use a similar user in another tenant and prove that no message, fact or vector result crosses the boundary.
Measure retrieval quality independently from answer quality. A model change can hide a memory regression, and a larger token budget can make a bad retrieval look better by including more noise. Record which block contributed which context so a failure can be attributed.
| Test | Pass condition |
|---|---|
| Same session resumes | The chat store returns the expected messages |
| New session, same user | Only allowed durable memory follows the user |
| Changed fact | The newest authorized fact wins and history stays auditable |
| Wrong tenant | No message, fact or vector result is returned |
| Token limit | The oldest context is dropped without corrupting the session |
| Deletion | Chat store, memory blocks and derived vector copies disappear |
| Framework change | Exported memory can be replayed with source and scope intact |
What is the recommended LlamaIndex memory architecture?
Use the Memory class for context assembly, a database-backed ChatStore for message persistence and a VectorStoreIndex only for document retrieval. Add an external memory contract when durable facts must follow a user across agents, services or frameworks. Resolve tenant identity outside the model, keep the token budget separate from retention and treat deletion as a workflow that covers every layer.
Frequently asked questions
Does LlamaIndex have built-in long-term memory?
LlamaIndex provides the Memory class, composable memory blocks and chat stores that can persist messages across sessions. The application still defines extraction, scope, correction, retention and deletion policy.
What is the difference between Memory and ChatStore?
Memory assembles the context the agent sees for a run. ChatStore persists messages so a later run can load them. A chat store does not decide which messages are useful, correct or allowed.
Is ChatMemoryBuffer still recommended?
Current LlamaIndex documentation marks ChatMemoryBuffer as deprecated and uses the Memory class in its examples. The Memory class supports configurable token limits and composable memory blocks.
How do you persist LlamaIndex memory across sessions?
Pass a database-backed chat store to Memory and use a stable session ID. A custom store can implement the AsyncDBChatStore interface when SQLAlchemy is not a fit.
Can LlamaIndex memory isolate tenants?
It can partition data by session ID, metadata or namespace, but it does not enforce authorization. Resolve the tenant and user from trusted application context and reject mismatches before calling the memory layer.
When should I add an external memory API?
Add one when several frameworks or products need the same durable context, when you need managed extraction and conflict handling, or when centralized correction, export and deletion are hard requirements.
