跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

Memory.cloneThread()

The .cloneThread() method creates a copy of an existing conversation thread, including all its messages. It supports creating divergent conversation paths from a specific point in a conversation. When semantic recall is enabled, the method also creates vector embeddings for the cloned messages.

cloneThread() loads the cloned messages to return them. If you only need the new thread ID, use copyThread(), which copies the thread without loading message content into memory.

Usage example
Usage example的直接链接

The following example creates a Memory instance and clones an existing thread.

import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'

const memory = new Memory({
storage: new LibSQLStore({ id: 'memory-store', url: 'file:./memory.db' }),
})

const { thread, clonedMessages } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
})

Parameters
Parameters的直接链接

sourceThreadId:

string
The ID of the thread to clone

newThreadId?:

string
Optional custom ID for the cloned thread. If not provided, one will be generated.

resourceId?:

string
Optional resource ID for the cloned thread. Defaults to the source thread's resourceId.

title?:

string
Optional title for the cloned thread. If omitted, the clone uses Clone of ${sourceThread.title} when the source thread has a title. Otherwise, the title is empty.

metadata?:

Record<string, unknown>
Optional metadata to merge with the source thread's metadata. Clone metadata is automatically added.

options?:

CloneOptions
Optional filtering options for the clone operation.
CloneOptions

messageLimit?:

number
Maximum number of messages to clone. When set, clones the most recent N messages.

messageFilter?:

MessageFilter
Filter criteria for selecting which messages to clone.
MessageFilter

startDate?:

Date
Only clone messages created on or after this date.

endDate?:

Date
Only clone messages created on or before this date.

messageIds?:

string[]
Only clone messages with these specific IDs.

Returns
Returns的直接链接

thread:

StorageThreadType
The newly created cloned thread with clone metadata.

clonedMessages:

MastraDBMessage[]
Array of the cloned messages with new IDs assigned to the new thread.

messageIdMap?:

Record<string, string>
A mapping from source message IDs to their corresponding cloned message IDs.

Clone metadata
Clone metadata的直接链接

The cloned thread's metadata includes a clone property with:

sourceThreadId:

string
The ID of the original thread that was cloned.

clonedAt:

Date
Timestamp when the clone was created.

lastMessageId?:

string
The ID of the last message in the source thread at the time of cloning.

Extended usage example
Extended usage example的直接链接

src/test-clone.ts
import { mastra } from './mastra'

const agent = mastra.getAgent('agent')
const memory = await agent.getMemory()

// Clone a thread with all messages
const { thread: fullClone } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
title: 'Alternative Conversation Path',
})

// Clone with a custom ID
const { thread: customIdClone } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
newThreadId: 'my-custom-clone-id',
})

// Clone only the last 5 messages
const { thread: partialClone, clonedMessages } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
options: {
messageLimit: 5,
},
})

// Clone messages from a specific date range
const { thread: dateFilteredClone } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
options: {
messageFilter: {
startDate: new Date('2024-01-01'),
endDate: new Date('2024-01-31'),
},
},
})

// Clone specific messages
const { thread: selectedMessagesClone } = await memory.cloneThread({
sourceThreadId: 'original-thread-123',
options: {
messageFilter: {
messageIds: ['message-1', 'message-2'],
},
},
})

// Continue conversation on the cloned thread
const response = await agent.generate('Try a different approach', {
memory: {
thread: fullClone.id,
resource: fullClone.resourceId,
},
})

Pass the cloned thread.id and thread.resourceId to agent.generate() to continue the conversation from the cloned thread.

Vector embeddings
Vector embeddings的直接链接

When the Memory instance has semantic recall enabled with a vector store and embedder configured, cloneThread() automatically creates vector embeddings for all cloned messages. It ensures that semantic search works correctly on the cloned thread.

In this example, embeddingModel is the embedding model configured for the project.

import { Memory } from '@mastra/memory'
import { LibSQLStore, LibSQLVector } from '@mastra/libsql'

const memory = new Memory({
storage: new LibSQLStore({ id: 'memory-store', url: 'file:./memory.db' }),
vector: new LibSQLVector({ id: 'vector-store', url: 'file:./vector.db' }),
embedder: embeddingModel,
options: {
semanticRecall: true,
},
})

// Clone will also create embeddings for cloned messages
const { thread } = await memory.cloneThread({
sourceThreadId: 'original-thread',
})

// Semantic search works on the cloned thread
const results = await memory.recall({
threadId: thread.id,
vectorSearchString: 'search query',
})

Working memory
Working memory的直接链接

When working memory is enabled, cloneThread() copies or shares working memory based on the working-memory scope and the clone's resourceId:

  • Thread-scoped working memory: The working memory is copied to the cloned thread.
  • Resource-scoped working memory with the same resourceId: The working memory is shared because the source and cloned threads belong to the same resource.
  • Resource-scoped working memory with a different resourceId: The working memory is copied to the cloned thread's resource.

Observational Memory
Observational Memory的直接链接

When Observational Memory is enabled, cloneThread() automatically clones the OM records associated with the source thread. The behavior depends on the OM scope:

  • Thread-scoped OM: The OM record is cloned to the new thread. All internal message ID references are remapped to point to the cloned messages.
  • Resource-scoped OM (deprecated, same resourceId): The OM record is shared between the source and cloned threads since they belong to the same resource. No duplication occurs.
  • Resource-scoped OM (deprecated, different resourceId): The OM record is cloned to the new resource. Message IDs are remapped and any thread-identifying tags within observations are updated to reference the cloned thread.

Only the current (most recent) OM generation is cloned. Older history generations aren't copied. Transient processing state (observation/reflection in-progress flags) is reset on the cloned record.