개요
세션이 끝나는 순간 어시스턴트가 모든 것을 잊어버립니다. 사용자가 이번 주에 자신의 이름을
알려줘도 다음 주에는 다시 묻습니다. memoryMiddleware가 이를 해결합니다. chat()
실행에 턴과 세션을 넘어 유지되는 메모리를 제공합니다.
두 단계로 작동합니다. 모델이 실행되기 전에 플러그형 어댑터에서 관련 메모리를 불러와 시스템 프롬프트에 추가합니다. 실행이 끝나면 해당 턴을 저장합니다. 저장은 지연되어 처리되므로 스트리밍을 차단하지 않습니다.
턴이나 세션을 넘어 내용을 불러와야 할 때 사용합니다. 동일한 요청에서 마지막 몇 개의 메시지만
유지하려면 messages에 전달하면 됩니다. 이 경우 메모리는 과합니다.
모든 기능은 @tanstack/ai-memory에 포함되어 있습니다. 미들웨어, 어댑터 계약,
내장 어댑터와 벤더 어댑터가 여기에 있습니다.
복사해 붙여 넣을 수 있는 설정이 필요하신가요? 빠른 시작을 참고하세요. 제공되지 않는 백엔드용 어댑터를 만들고 있나요? 사용자 지정 어댑터 가이드를 참고하세요.
언제 사용해야 하나요
| 필요한 기능 | 사용할 항목 |
|---|---|
| "지난주에 사용자가 알려준 내용을 기억합니다" | 영속 어댑터를 사용하는 메모리 미들웨어 |
| "사용자마다 각자의 컨텍스트를 가집니다" | 범위가 지정된 어댑터를 사용하는 메모리 미들웨어 |
| "호스팅된 메모리 서비스(mem0, Honcho, Hindsight)를 사용합니다" | 해당 벤더 어댑터 |
| 동일한 요청에서 마지막 몇 개의 턴을 유지합니다 | messages에 전달하고 메모리는 건너뜁니다 |
계약: 불러오기와 저장
메모리 어댑터에는 하나의 식별자와 두 개의 동작이 있습니다. 추출, 순위 지정, 렌더링, 저장은 모두 어댑터의 역할입니다. 미들웨어는 레코드 내부를 확인하지 않습니다.
| 멤버 | 용도 |
|---|---|
id | 로그와 devtools에서 사용하는 안정적인 식별자입니다. |
recall(scope, query) | scope 내에서 query와 관련된 내용을 반환합니다. 렌더링된 systemPrompt, 선택적 fragments, 선택적 LLM tools와 toolGuidance가 포함됩니다. |
save(scope, turn) | 완료된 { user, assistant } 턴을 영속화합니다. 추출은 여기서 수행됩니다. 쓰기마다 하나의 SaveReceipt를 반환합니다. |
inspect(scope)? | 선택 사항입니다. devtools 패널용 전체 스냅샷입니다. |
listFacts(scope)? | 선택 사항입니다. devtools 패널용 평면 사실 목록입니다. |
// The MemoryAdapter contract, from `@tanstack/ai-memory`:
import type { MemoryAdapter } from '@tanstack/ai-memory'
내장 어댑터는 각각 트리 셰이킹 가능한 서브 경로를 제공합니다.
import { inMemory } from '@tanstack/ai-memory/in-memory'
import { redis } from '@tanstack/ai-memory/redis'
벤더 어댑터입니다.
import { hindsight } from '@tanstack/ai-memory/hindsight'
import { mem0 } from '@tanstack/ai-memory/mem0'
import { honcho } from '@tanstack/ai-memory/honcho'
모든 어댑터와 옵션은 어댑터를 참고하세요.
턴의 흐름
- 불러오기는 모델보다 먼저, 실행의
init단계에서 수행됩니다.adapter.recall(scope, userText)가 메모리를 반환하면 미들웨어가systemPrompt,toolGuidance, 모든tools를 실행에 추가합니다. - 저장은 스트림이 끝난 후
ctx.defer를 통해 지연되어 수행되므로 응답을 차단하지 않습니다. 미들웨어는{ user, assistant }턴을adapter.save(scope, turn)에 전달합니다.
텔레메트리를 추가하거나, devtools에서 메모리를 확인하거나, 불러오지 않고 영속화하거나, 실패를 처리하려면 메모리 운영을 참고하세요.
범위와 보안
MemoryScope는 격리 경계입니다. @tanstack/ai의 공유 Scope 식별자 타입에 대한
별칭이며, 영속성에서 사용하는 것과 동일한 용어이므로 메모리와 채팅이 하나의 대화 키를
중심으로 작동합니다.
// MemoryScope is an alias of Scope from `@tanstack/ai`, exported by `@tanstack/ai-memory`:
type MemoryScope = {
threadId: string // required — same as ChatMiddlewareContext.threadId
userId?: string
tenantId?: string
namespace?: string // reserved — no adapter keys on it yet
}
서버에서는 신뢰할 수 있는 세션/인증 상태를 바탕으로 항상 범위를 확인해야 합니다. 클라이언트에서
시작된 threadId는 세션 사용자에게 속하는지 검증한 후에만 사용할 수 있으며, 요청 본문만으로
userId/tenantId를 절대 수락해서는 안 됩니다. scope의 함수 형식은 요청마다 실행되며 서버가
채팅 컨텍스트에 연결한 내용만 확인할 수 있습니다.
import { memoryMiddleware } from '@tanstack/ai-memory'
import type { MemoryAdapter } from '@tanstack/ai-memory'
declare const adapter: MemoryAdapter
declare function getSession(ctx: unknown): { threadId: string; userId: string }
memoryMiddleware({
adapter,
scope: (ctx) => {
const session = getSession(ctx) // your server-validated session
return { threadId: session.threadId, userId: session.userId }
},
})
다음 단계
- 빠른 시작: 실제
chat()호출에memoryMiddleware연결 - 어댑터: 각 어댑터의 옵션과 어댑터별 예시
- 사용자 지정 어댑터: 제공되지 않는 백엔드용
recall/save구현 - 메모리 운영: 옵션, 텔레메트리, devtools 이벤트, 실패 동작