本页还没有译文
本页 23 段还没译成Русский,下面显示的是英文原文。Quickstart
还没翻译译自英文(tanstack.com)本页 23 段都还没译
You have a working chat() call and you want it to remember context across turns or
sessions. By the end of this guide, memoryMiddleware recalls relevant memory into the
prompt and saves each finished turn through a real adapter, scoped safely from your
server-validated session.
Want the full contract first? See the Overview.
Step 1: Install the package
npm i @tanstack/ai-memorypnpm add @tanstack/ai-memoryyarn add @tanstack/ai-memorybun add @tanstack/ai-memory@tanstack/ai-memory ships memoryMiddleware, the MemoryAdapter contract, and the
built-in and vendor adapters (each on its own subpath).
Step 2: Pick an adapter
In-memory:
inMemory()is zero-dependency and stores records in aMap. Use it for local development, tests, and single-process demos. Records vanish on restart.Redis:
redis({ redis })persists across restarts and shares state across processes. Bring your own client (ioredis, orredisviafromNodeRedis).Vendors:
hindsight(),mem0(), andhoncho()delegate to a hosted memory service.
Custom adapters implement the recall/save contract. See Custom Adapter.
Step 3: Wire memoryMiddleware into chat()
Start with the in-memory adapter, the fastest path to a working setup:
import { chat } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { memoryMiddleware } from '@tanstack/ai-memory'
import { inMemory } from '@tanstack/ai-memory/in-memory'
const memory = inMemory()
const stream = chat({
adapter: openaiText('gpt-5.5'),
messages: [{ role: 'user', content: 'Hello' }],
middleware: [
memoryMiddleware({
adapter: memory,
scope: { threadId: 'demo-thread', userId: 'alice' },
}),
],
})Each turn, the middleware recalls relevant memory into the system prompt (lexical scoring by default), then deferred-saves the user and assistant turn after the stream finishes.
When you're ready to ship, swap the adapter and keep everything else the same:
import Redis from 'ioredis'
import { memoryMiddleware } from '@tanstack/ai-memory'
import { redis } from '@tanstack/ai-memory/redis'
import type { MemoryScope } from '@tanstack/ai-memory'
declare const scope: MemoryScope // from Step 5
const client = new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379')
const memory = redis({ redis: client })
memoryMiddleware({ adapter: memory, scope })Using a hosted service? Swap
inMemory()forhindsight({ user }),mem0({ user }), orhoncho({ user }). The middleware wiring is identical. The adapter mapsrecall/saveonto the vendor API.
Step 4: Semantic scoring (optional)
The built-in adapters score lexically by default. Pass an embedder for semantic recall
when scopes grow large or queries don't share keywords with stored text:
import OpenAI from 'openai'
import { inMemory } from '@tanstack/ai-memory/in-memory'
const openai = new OpenAI()
const memory = inMemory({
embedder: {
async embed(text) {
const result = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
})
const embedding = result.data[0]?.embedding
if (!embedding) throw new Error('embedding request returned no vector')
return embedding
},
},
})Step 5: Derive scope server-side
scope is the isolation boundary. Static scopes are fine for fixtures, but in any real
app derive scope per request from server-validated session data, never from the request
body.
import { chat } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { memoryMiddleware } from '@tanstack/ai-memory'
import type { ModelMessage } from '@tanstack/ai'
import type { MemoryAdapter } from '@tanstack/ai-memory'
// From earlier steps / your auth layer.
declare const messages: Array<ModelMessage>
declare const memory: MemoryAdapter
declare const session: { userId: string; threadId: string }
declare function getSession(ctx: unknown): { threadId: string; userId: string }
const stream = chat({
adapter: openaiText('gpt-5.5'),
messages,
context: { session }, // attached by your auth middleware, not from req.body
middleware: [
memoryMiddleware({
adapter: memory,
scope: (ctx) => {
const session = getSession(ctx)
return { threadId: session.threadId, userId: session.userId }
},
}),
],
})On the client, nothing changes for memory wiring — consume the same stream as any
other chat() endpoint:
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'
function Chat() {
const { messages, sendMessage, isLoading } = useChat({
connection: fetchServerSentEvents('/api/chat'),
})
// Memory is entirely server-side; the client only sees the usual message stream.
return (
// render messages, input, sendMessage, isLoading…
null
)
}Where to go next
- Overview: the
recall/savecontract, scope, and how a turn flows - Adapters: every adapter's options, with an example of each
- Operating memory: options, telemetry, devtools events, and failures
- Custom Adapter: implement
recall/savefor a backend that isn't shipped