Memory class
The Memory class provides a reliable system for managing conversation history and thread-based message storage in Mastra. It enables persistent storage of conversations, semantic search capabilities, and efficient message retrieval. You must configure a storage provider for conversation history, and if you enable semantic recall you will also need to provide a vector store and, unless that vector store embeds text itself, an embedder.
Usage exampleDirect link to Usage example
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
export const agent = new Agent({
id: 'test-agent',
name: 'test-agent',
instructions: 'You are an agent with memory.',
model: 'openai/gpt-6.1-sol',
memory: new Memory({
options: {
workingMemory: {
enabled: true,
},
},
}),
})
To enable workingMemory on an agent, you’ll need a storage provider configured on your main Mastra instance. See Mastra class for more information.
Constructor parametersDirect link to Constructor parameters
storage?:
memory.storage throws Memory requires a storage provider to function.vector?:
false to disable vector operations.embedder?:
"openai/text-embedding-3-small"), an EmbeddingModel, or an EmbeddingModelV2. Required when semantic recall is enabled and the vector store doesn't generate embeddings itself (vector.isSelfEmbedding is false).embeddingDimension?:
MASTRA_MEMORY_EMBEDDING_DIMENSION_MISMATCH error before any index is created. See Setting the embedding dimension.options?:
lastMessages?:
false to disable the message history feature entirely (messages are not loaded into context or saved). Use Number.MAX_SAFE_INTEGER to retrieve all messages with no limit. To load messages without saving new ones, use the readOnly option. The window slides forward on every request, so once a thread exceeds the limit, each turn invalidates the provider prompt cache. For long-running conversations, use Observational Memory instead.messageHistory?:
maxTokens, the oldest remembered messages are dropped until the prompt is at most maxTokens - atMaxRemoveTokens (defaults to 25% of maxTokens). Protected content is never removed. Linked tool calls and results are removed together. During agent runs, trimmed history is excluded from later turns via a persisted per-thread boundary, but the messages themselves stay in storage. When set without an explicit lastMessages, the default 10-message cap is not applied. Set maxTokens to 0 to disable message history. Prefer this over lastMessages, since message count is a poor proxy for context size.readOnly?:
retainFullInput?:
memory.options or agent-wide in the memory constructor options.semanticRecall?:
isSelfEmbedding). Default topK is 4, default messageRange is {before: 1, after: 1}. maxChunkChars caps the characters of message text per embedded chunk; see Long messages.workingMemory?:
{ enabled: boolean; template?: string; schema?: ZodObject<any> | JSONSchema7; scope?: 'thread' | 'resource' } or { enabled: boolean } to disable.observationalMemory?:
true for defaults, or pass a config object to customize token budgets, models, and scope. See Observational Memory reference for configuration details.generateTitle?:
MastraModelConfig: a model instance, a "provider/model" ID, or an OpenAI-compatible config; defaults to the agent's own model), custom instructions, a minimum message count, and emitEvent. With emitEvent: true the run's stream waits for the title and emits it as a transient data-thread-title chunk before finish (durable and evented agents persist the title but don't emit the chunk yet).ReturnsDirect link to Returns
memory:
saveMessages()Direct link to savemessages
agent.generate() and agent.stream() persist messages for you. Call memory.saveMessages() when you need to write messages yourself, for example to seed a thread, to import a transcript, or to store messages that originated outside Mastra. Each message needs a threadId and a resourceId, so create the thread with createThread() before saving into it.
await memory.saveMessages({
messages: [
{
id: 'msg-1',
threadId: 'thread-123',
resourceId: 'user-456',
role: 'user',
createdAt: new Date(),
content: {
format: 2,
parts: [{ type: 'text', text: 'Where is my order?' }],
},
},
],
})
ParametersDirect link to Parameters
messages:
threadId and a resourceId.memoryConfig?:
observabilityContext?:
Returns Promise<{ messages: MastraDBMessage[]; usage?: { tokens: number } }>. usage is present when the embedder reports token usage while indexing messages for semantic recall.
MastraDBMessageDirect link to mastradbmessage
Storage uses a single message shape, MastraDBMessage. The methods that hand messages back or take them in use this shape, including saveMessages() and recall().
id:
role:
threadId?:
resourceId?:
createdAt:
content:
parts array holds the text, reasoning, tool calls, and attachments.content.parts is the part the agent actually reads. content.format is always 2 for stored messages, and content.metadata carries arbitrary custom data. content.toolInvocations, content.reasoning, and content.experimental_attachments are flat mirrors kept for AI SDK v4 compatibility; write to parts instead.
const assistantMessage = {
id: 'msg-2',
threadId: 'thread-123',
resourceId: 'user-456',
role: 'assistant',
createdAt: new Date(),
content: {
format: 2,
parts: [
{ type: 'text', text: 'It ships tomorrow.' },
{
type: 'tool-invocation',
toolInvocation: {
state: 'result',
toolCallId: 'call-1',
toolName: 'lookupOrder',
args: { orderId: 'A-1' },
result: { eta: '2026-10-30' },
},
},
],
metadata: { source: 'import' },
},
}
Extended usage exampleDirect link to Extended usage example
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
export const agent = new Agent({
name: 'test-agent',
instructions: 'You are an agent with memory.',
model: 'openai/gpt-6.1-sol',
memory: new Memory({
storage: new LibSQLStore({
id: 'test-agent-storage',
url: 'file:./working-memory.db',
}),
vector: new LibSQLVector({
id: 'test-agent-vector',
url: 'file:./vector-memory.db',
}),
options: {
lastMessages: 10,
semanticRecall: {
topK: 3,
messageRange: 2,
scope: 'resource',
},
workingMemory: {
enabled: true,
},
generateTitle: true,
},
}),
})
PostgreSQL with index configurationDirect link to PostgreSQL with index configuration
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
import { PostgresStore, PgVector } from '@mastra/pg'
export const agent = new Agent({
name: 'pg-agent',
instructions: 'You are an agent with optimized PostgreSQL memory.',
model: 'openai/gpt-6.1-sol',
memory: new Memory({
storage: new PostgresStore({
id: 'pg-agent-storage',
connectionString: process.env.DATABASE_URL,
}),
vector: new PgVector({
id: 'pg-agent-vector',
connectionString: process.env.DATABASE_URL,
}),
embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
options: {
lastMessages: 20,
semanticRecall: {
topK: 5,
messageRange: 3,
scope: 'resource',
indexConfig: {
type: 'hnsw', // Use HNSW for better performance
metric: 'dotproduct', // Optimal for OpenAI embeddings
hnsw: {
m: 16, // Number of bi-directional links
efConstruction: 64, // Construction-time candidate list size
},
},
},
workingMemory: {
enabled: true,
},
},
}),
})