跳至主要內容

訊息歷史

訊息歷史是最基本也最重要的 Memory 形式。它讓 LLM 能在 context window 中看到近期訊息,使 Agent 可以引用先前的交流內容並連貫地回應。

你也可以擷取訊息歷史,在 UI 中顯示過往對話。

資訊

每則訊息都屬於一個 thread(對話),以及一個 resource(與其相關聯的使用者或實體)。如需詳細資訊,請參閱 Thread 與 resource

警告

在用戶端應用程式中使用 Memory 時,用戶端只應傳送新訊息,不要傳送完整的對話歷史。

傳送完整歷史是多餘的,因為 Mastra 會從儲存空間載入訊息;而且當用戶端時間戳記與已儲存的時間戳記衝突時,可能導致訊息順序錯誤。

如需 AI SDK 範例,請參閱使用 Mastra Memory

Thread 與 resource
「Thread 與 resource」的直接連結

Mastra 使用兩個識別碼整理對話:

  • Thread:包含一系列訊息的對話工作階段。
  • Resource:擁有該 thread 的實體,例如應用程式中的使用者、組織、專案或其他領域實體。

Studio 會自動為你產生 thread 與 resource ID。自行呼叫 stream()generate() 時,請明確提供這些識別碼。

開始使用
「開始使用」的直接連結

安裝 Mastra Memory 模組,以及資料庫所需的儲存 adapter。以下範例使用 @mastra/libsql,它會將資料儲存在本機的 mastra.db 檔案中。

npm install @mastra/memory@latest @mastra/libsql@latest

訊息歷史需要儲存 adapter 才能保存對話。若尚未設定,請在 Mastra 執行個體上設定儲存空間:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { LibSQLStore } from '@mastra/libsql'

export const mastra = new Mastra({
storage: new LibSQLStore({
id: 'mastra-storage',
url: 'file:./mastra.db',
}),
})

在 Agent 中建立 Memory 執行個體:

src/mastra/agents/test-agent.ts
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'

export const agent = new Agent({
id: 'test-agent',
memory: new Memory({
options: {
lastMessages: 10,
},
}),
})

呼叫 Agent 時,訊息會自動儲存至資料庫。你可以指定 threadIdresourceId 及選用的 metadata

await agent.generate('Hello', {
memory: {
thread: {
id: 'thread-123',
title: 'Support conversation',
metadata: { category: 'billing' },
},
resource: 'user-456',
},
})
資訊

呼叫 agent.generate()agent.stream() 時,系統會自動建立 thread 與訊息;你也可以使用 createThread()saveMessages() 手動建立。

你可以透過兩種方式使用這份歷史:

  • 自動納入:Mastra 會自動擷取近期訊息,並將其納入 context window。預設會納入最近 10 則訊息,讓 Agent 以對話內容為依據。你可以使用 lastMessages 調整數量,但多數情況下不需要特別處理。
  • 手動查詢:若需要更多控制,請使用 recall() 函式直接查詢 thread 與訊息。如此便能精確選擇 context window 中要納入哪些記憶,或擷取訊息以在 UI 中呈現對話歷史。
提示

啟用 Memory 後,Studio 會使用訊息歷史,在聊天側邊欄顯示過往對話。

產生 thread 標題
「產生 thread 標題」的直接連結

啟用 generateTitle 後,Mastra 可以根據對話逐字稿自動產生描述性的 thread 標題。若你建立的聊天介面會在 thread 清單或側邊欄呈現對話標題,請使用此選項。

src/mastra/agents/support-agent.ts
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'

export const supportAgent = new Agent({
id: 'support-agent',
name: 'Support agent',
instructions: 'Answer customer support questions.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
options: {
generateTitle: true,
},
}),
})

標題會在 Agent 回應後以非同步方式產生,不會影響回應時間。

若要最佳化成本或行為,請提供較小的 model 與自訂 instructions

src/mastra/agents/support-agent.ts
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'

export const supportAgent = new Agent({
id: 'support-agent',
name: 'Support agent',
instructions: 'Answer customer support questions.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
options: {
generateTitle: {
model: 'openai/gpt-5-mini',
instructions: 'Generate a one-word title.',
},
},
}),
})

存取 Memory
「存取 Memory」的直接連結

若要存取 Memory 函式以查詢、複製或刪除 thread 與訊息,請對 Agent 呼叫 getMemory()

const agent = mastra.getAgentById('test-agent')
const memory = await agent.getMemory()

Memory 執行個體可讓你使用列出 thread、回想訊息、複製對話等函式。

查詢
「查詢」的直接連結

使用以下方法擷取 thread 與訊息,以便在 UI 中顯示對話歷史,或用於自訂 Memory 擷取邏輯。

警告

Memory 系統不會強制執行存取控制。執行任何查詢前,請在應用程式邏輯中確認目前使用者有權存取要查詢的 resourceId

Thread
「Thread」的直接連結

使用 listThreads() 擷取 resource 的 thread:

const result = await memory.listThreads({
filter: { resourceId: 'user-123' },
perPage: false,
})

以分頁方式瀏覽 thread:

const result = await memory.listThreads({
filter: { resourceId: 'user-123' },
page: 0,
perPage: 10,
})

console.log(result.threads) // thread objects
console.log(result.hasMore) // more pages available?

你也可以依 metadata 篩選並控制排序順序:

const result = await memory.listThreads({
filter: {
resourceId: 'user-123',
metadata: { status: 'active' },
},
orderBy: { field: 'createdAt', direction: 'DESC' },
})

若要依 ID 擷取單一 thread,請使用 getThreadById()

const thread = await memory.getThreadById({ threadId: 'thread-123' })

訊息
「訊息」的直接連結

取得 thread 後,請使用 recall() 擷取其訊息。它支援分頁、日期篩選與語意搜尋

基本回想會傳回 thread 中的所有訊息:

const { messages } = await memory.recall({
threadId: 'thread-123',
perPage: false,
})

以分頁方式瀏覽訊息:

const { messages } = await memory.recall({
threadId: 'thread-123',
page: 0,
perPage: 50,
})

依日期範圍篩選:

const { messages } = await memory.recall({
threadId: 'thread-123',
filter: {
dateRange: {
start: new Date('2025-01-01'),
end: new Date('2025-06-01'),
},
},
})

依淺層訊息 metadata 篩選:

const { messages } = await memory.recall({
threadId: 'thread-123',
filter: {
metadata: {
category: 'billing',
escalated: true,
priority: 2,
archivedAt: null,
},
},
})

Metadata 篩選條件只會比對淺層純量值:string、有限的 numberbooleannull

所有指定的 metadata key 都使用 AND 語意。null 篩選條件只會比對明確的 null 值;缺少 metadata key 時不會相符。

Metadata key 必須以字母或底線開頭,且只能包含英數字元。長度不得超過 128 個字元,也不能使用 __proto__constructorprototype 等保留的 prototype key。

效能取決於儲存後端。部分後端可將部分篩選條件下推至資料庫;其他後端則會先套用 thread、resource 與日期限制,再掃描候選訊息,最後才進行分頁。

依 ID 擷取單一訊息:

const { messages } = await memory.recall({
threadId: 'thread-123',
include: [{ id: 'msg-123' }],
})

依 ID 擷取多則訊息及其周邊脈絡:

const { messages } = await memory.recall({
threadId: 'thread-123',
include: [
{ id: 'msg-123' },
{
id: 'msg-456',
withPreviousMessages: 3,
withNextMessages: 1,
},
],
})

依語意搜尋(設定方式請參閱語意回憶):

const { messages } = await memory.recall({
threadId: 'thread-123',
vectorSearchString: 'project deadline discussion',
threadConfig: {
semanticRecall: true,
},
})

UI 格式
「UI 格式」的直接連結

訊息查詢會傳回 MastraDBMessage[] 格式。若要在前端顯示訊息,你可能需要轉換成 UI 程式庫預期的格式。例如,toAISdkV5Messages 可將訊息轉換為 AI SDK UI 格式。

複製 thread
「複製 thread」的直接連結

複製 thread 會建立現有 thread 及其訊息的副本。這適合用來建立對話分支、在可能造成破壞的操作前建立檢查點,或測試不同的對話變化。

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

你可以依數量或日期範圍篩選要複製的訊息、指定自訂 thread ID,並使用公用方法檢查複製關係。

如需完整 API,請參閱 cloneThread()複製公用方法

刪除訊息
「刪除訊息」的直接連結

若要從 thread 移除訊息,請使用 deleteMessages()。你可以依訊息 ID 刪除,或清除 thread 中的所有訊息。