Memory.recall()
The Memory.recall() method retrieves messages from a specific thread, with support for pagination, filtering options, and semantic search.
Usage exampleDirect link to Usage example
const { messages } = await memory.recall({
threadId: 'thread-123',
perPage: 20,
})
ParametersDirect link to Parameters
threadId:
resourceId?:
vectorSearchString?:
perPage?:
page?:
include?:
id (required), optional threadId (defaults to main threadId), withPreviousMessages (number of messages before, defaults to 2 for vector search, 0 otherwise), and withNextMessages (number of messages after, defaults to 2 for vector search, 0 otherwise).filter?:
dateRange filters messages by creation date. metadata filters shallow message metadata by exact scalar key-value pairs using AND semantics. Metadata values can be strings, finite numbers, booleans, or null.hideSignals?:
includeSystemReminders?:
orderBy?:
threadConfig?:
lastMessages?:
semanticRecall?:
workingMemory?:
{ enabled: boolean; template?: string; schema?: ZodObject<any> | JSONSchema7; scope?: 'thread' | 'resource' } or { enabled: boolean } to disable.threads?:
generateTitle controls automatic thread title generation from the conversation transcript. Can be a boolean or an object with custom model and instructions.Signal visibilityDirect link to Signal visibility
hideSignals filters messages returned by this call, not the underlying storage or later model requests. Ordinary messages remain available. This option isn't a security boundary and doesn't change signal delivery or persistence policies such as ifActive, ifIdle, or transient.
Defaults and precedenceDirect link to Defaults and precedence
hideSignals | includeSystemReminders | Returned signals |
|---|---|---|
| Omitted | Omitted or false | Existing reminder-hidden history |
| Omitted | true | All signals |
false or [] | Any value | All signals |
true | Any value | No recognized signals, including legacy reminders |
| Nonempty list | Any value | All except matching types |
Unlike agent streams, recall continues to hide reminders by default for compatibility. The deprecated includeSystemReminders flag only applies when hideSignals is omitted.
const all = await memory.recall({
threadId: 'thread-123',
hideSignals: false,
})
const withoutSignals = await memory.recall({
threadId: 'thread-123',
hideSignals: true,
})
const withoutReminders = await memory.recall({
threadId: 'thread-123',
hideSignals: ['reactive', 'system-reminder'],
})
Stored types and legacy messagesDirect link to Stored types and legacy messages
Recall matches the exact stored type, without alias normalization. For example, ['reactive'] doesn't exclude a row encoded as system-reminder, and ['user'] doesn't exclude one encoded as user-message. Modern streams and subscriptions normalize these aliases instead. Use ['reactive', 'system-reminder'] to exclude both reminder representations across these APIs.
A recognized type in a data-signal or data-user-message part takes precedence over signal metadata and legacy reminder markers. Signal-role messages can also encode their type in content.metadata.signal.type. Unknown types and malformed signal parts don't match exclusions, including hideSignals: true.
If no recognized encoded type exists, a message classified by the existing legacy reminder rules counts as system-reminder, not reactive. These rules include user messages with systemReminder or dynamicAgentsMdReminder metadata, or a first text part starting with <system-reminder. Such rows remain visible with ['reactive'] and are excluded with ['system-reminder'].
Pagination and API scopeDirect link to Pagination and API scope
Filtering happens after the storage query and pagination. A page can contain fewer than perPage messages, or none, without changing total, hasMore, or page offsets. Totals still describe the underlying query, not the filtered messages.
The option applies to in-process memory.recall() calls. HTTP and client-js contracts don't expose hideSignals in this release.
Metadata filteringDirect link to Metadata filtering
Use filter.metadata to match shallow scalar metadata stored on messages:
const { messages } = await memory.recall({
threadId: 'thread-123',
filter: {
metadata: {
category: 'billing',
escalated: true,
priority: 2,
archivedAt: null,
},
},
})
All metadata entries are combined with AND semantics. A message must match every key and value with exact type equality. null matches metadata that's explicitly set to null. It doesn't match a missing key.
Metadata filters only support shallow scalar values: string, finite number, boolean, and null. Nested objects, arrays, NaN, and infinities aren't supported. Metadata keys must start with a letter or underscore and contain only alphanumeric or underscore characters. The limit is 128 characters. Reserved prototype keys such as __proto__, constructor, and prototype aren't allowed. Performance depends on the storage backend. Arbitrary metadata filters may require scanning candidate messages, so narrow the query with threadId, resourceId, or dateRange when possible.
ReturnsDirect link to Returns
messages:
Extended usage exampleDirect link to Extended usage example
import { mastra } from './mastra'
const agent = mastra.getAgent('agent')
const memory = await agent.getMemory()
// Retrieve messages with pagination
const { messages } = await memory!.recall({
threadId: 'thread-123',
perPage: 50,
vectorSearchString: 'What messages are there?',
include: [
{
id: 'msg-123',
},
{
id: 'msg-456',
withPreviousMessages: 3,
withNextMessages: 1,
},
],
threadConfig: {
semanticRecall: true,
},
})
console.log(messages) // MastraDBMessage[]
// Fetch all messages without pagination
const allMessages = await memory!.recall({
threadId: 'thread-123',
perPage: false, // Fetch all
})
// Convert to AI SDK format if needed
import { toAISdkV5Messages } from '@mastra/ai-sdk/ui'
const uiMessages = toAISdkV5Messages(messages)