Memory.copyThread()
The .copyThread() method copies an existing thread and its messages to a new thread. It behaves like cloneThread(), including working memory, observational memory, and semantic-recall embeddings, but it doesn't return the copied messages. On @mastra/libsql and @mastra/pg the rows are copied inside the database, so the copy itself never loads message content into the Node.js process. See Memory usage for the cases where content is still read.
Use copyThread() when you only need the new thread ID, such as forking a conversation for a subagent. Use cloneThread() when you need the copied messages in the response.
Usage exampleDirect link to Usage example
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, messageIdMap } = await memory.copyThread({
sourceThreadId: 'original-thread-123',
})
ParametersDirect link to Parameters
copyThread() accepts the same parameters as cloneThread().
sourceThreadId:
newThreadId?:
resourceId?:
title?:
Clone of ${sourceThread.title} when the source thread has a title. Otherwise, the title is empty.metadata?:
options?:
messageLimit?:
messageFilter?:
ReturnsDirect link to Returns
thread:
messageIdMap?:
Memory usageDirect link to Memory usage
copyThread() is designed for large threads:
@mastra/libsqland@mastra/pgcopy messages withINSERT … SELECTstatements, so the copy step doesn't read message content into the process.- Other storage adapters copy messages through the adapter's existing
cloneThread()implementation, which may read and re-write each message.copyThread()still discards the payloads before returning. - When semantic recall is enabled, the copied messages are read back to generate embeddings. This happens in batches of 100 by destination message ID, so only one batch is held in memory at a time.
cloneThread() calls copyThread() and then reads the new thread's messages back to populate clonedMessages.