Docs
CodeRabbit
Cloudflare
AG Grid
SerpAPI
Netlify
OpenRouter
Neon
WorkOS
Clerk
Electric
PowerSync
Sentry
Railway
Prisma
Strapi
Unkey
CodeRabbit
Cloudflare
AG Grid
SerpAPI
Netlify
OpenRouter
Neon
WorkOS
Clerk
Electric
PowerSync
Sentry
Railway
Prisma
Strapi
Unkey
Class References
Function References
Interface References
Type Alias References
Variable References

Adapters

Every adapter implements the same recall/save contract, so they're interchangeable in memoryMiddleware. This page is the full option reference: each adapter's options with an example of each.

Common options

inMemory() and redis() are both client-side rankers built on the same pipeline, so they share these options.

OptionTypeDefaultPurpose
topKnumber6Max hits returned by recall.
minScorenumber0.15Drop hits scoring below this.
kindsArray<MemoryKind>allRestrict recall to these record kinds ('message', 'summary', 'fact', 'preference').
embedder{ embed(text): Promise<number[]> }noneEnable semantic scoring (embeds on both recall and save).
extract(turn, scope) => ExtractedFact[]nonePersist derived facts on save, alongside the raw turn.
render(hits) => stringbuilt-inReplace the prompt renderer.

Every option, in one adapter:

ts
import { inMemory } from '@tanstack/ai-memory/in-memory'

// `embedText` stands in for your embedding client (OpenAI, Cohere, a local model).
declare function embedText(text: string): Promise<Array<number>>

const memory = inMemory({
  topK: 8, // return up to 8 hits
  minScore: 0.2, // ignore weak matches
  kinds: ['message', 'fact', 'preference'], // skip summaries
  embedder: { embed: embedText }, // semantic + lexical scoring
  extract: (turn) => [
    // store a derived fact in addition to the raw turn
    { text: `User said: ${turn.user}`, kind: 'fact', importance: 0.8 },
  ],
  render: (hits) =>
    // custom prompt block instead of the default renderer
    `What I remember:\n${hits.map((h) => `- ${h.record.text}`).join('\n')}`,
})
import { inMemory } from '@tanstack/ai-memory/in-memory'

// `embedText` stands in for your embedding client (OpenAI, Cohere, a local model).
declare function embedText(text: string): Promise<Array<number>>

const memory = inMemory({
  topK: 8, // return up to 8 hits
  minScore: 0.2, // ignore weak matches
  kinds: ['message', 'fact', 'preference'], // skip summaries
  embedder: { embed: embedText }, // semantic + lexical scoring
  extract: (turn) => [
    // store a derived fact in addition to the raw turn
    { text: `User said: ${turn.user}`, kind: 'fact', importance: 0.8 },
  ],
  render: (hits) =>
    // custom prompt block instead of the default renderer
    `What I remember:\n${hits.map((h) => `- ${h.record.text}`).join('\n')}`,
})

extract returns ExtractedFact[] ({ text, kind?, importance?, metadata? }). Return undefined for a no-op. It's where an LLM-based fact extractor plugs in without the adapter taking a hard dependency on any model.

embedder is invoked on the recall path (to embed the query) and again on save (to embed stored text). Without it, scoring is lexical + recency only.

inMemory()

Zero-dependency, Map-backed. Takes only the common options above. Records vanish on restart, so use it for dev, tests, and single-process demos.

ts
import { inMemory } from '@tanstack/ai-memory/in-memory'

const memory = inMemory() // all options are optional
import { inMemory } from '@tanstack/ai-memory/in-memory'

const memory = inMemory() // all options are optional

redis()

Plain-Redis adapter. Adds two options to the common options, and requires a client.

OptionTypeDefaultPurpose
redisRedisLike(required)Your Redis client (ioredis, or node-redis via fromNodeRedis).
prefixstring'tanstack-ai:memory'Key namespace.
ts
import Redis from 'ioredis'
import { redis } from '@tanstack/ai-memory/redis'

const memory = redis({
  redis: new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379'), // required
  prefix: 'myapp:memory', // key namespace
  topK: 8, // common options apply here too
  minScore: 0.2,
})
import Redis from 'ioredis'
import { redis } from '@tanstack/ai-memory/redis'

const memory = redis({
  redis: new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379'), // required
  prefix: 'myapp:memory', // key namespace
  topK: 8, // common options apply here too
  minScore: 0.2,
})

Using node-redis (redis package) instead of ioredis? Its camelCase API doesn't match RedisLike, so wrap it with fromNodeRedis:

ts
import { createClient } from 'redis'
import { redis, fromNodeRedis } from '@tanstack/ai-memory/redis'

const client = createClient({ url: process.env.REDIS_URL })
await client.connect()

const memory = redis({ redis: fromNodeRedis(client) })
import { createClient } from 'redis'
import { redis, fromNodeRedis } from '@tanstack/ai-memory/redis'

const client = createClient({ url: process.env.REDIS_URL })
await client.connect()

const memory = redis({ redis: fromNodeRedis(client) })

ioredis and redis are both optional peer dependencies. Install whichever you use.

hindsight()

Hosted adapter backed by Hindsight. Owns extraction/ranking server-side and exposes retain/recall/reflect LLM tools through recall. @vectorize-io/hindsight-client is an optional peer, loaded lazily.

OptionTypeDefaultPurpose
userstringscope.userIdDurable user id used in the bank key ({user}__{sessionId}).
baseUrlstringHINDSIGHT_URL / http://localhost:8888Server URL.
budget'low' | 'mid' | 'high''mid'Recall budget.
onToolRetain(receipt) => voidnoneFired when the model calls hindsight_retain.
onToolRecall(query, result) => voidnoneFired when the model calls hindsight_recall.
ts
import { hindsight } from '@tanstack/ai-memory/hindsight'

const memory = hindsight({
  user: 'alice', // bank = alice__{sessionId}
  baseUrl: 'https://hindsight.internal', // default: HINDSIGHT_URL
  budget: 'high', // deeper recall
  onToolRetain: (receipt) => console.log('model retained', receipt.ok),
  onToolRecall: (query, result) =>
    console.log('model recalled', query, result.fragments?.length),
})
import { hindsight } from '@tanstack/ai-memory/hindsight'

const memory = hindsight({
  user: 'alice', // bank = alice__{sessionId}
  baseUrl: 'https://hindsight.internal', // default: HINDSIGHT_URL
  budget: 'high', // deeper recall
  onToolRetain: (receipt) => console.log('model retained', receipt.ok),
  onToolRecall: (query, result) =>
    console.log('model recalled', query, result.fragments?.length),
})

mem0()

Hosted adapter backed by a mem0 server, over plain HTTP (no SDK peer). Requires a running mem0 server.

OptionTypeDefaultPurpose
userstringscope.userId / 'demo-user'mem0 user_id.
baseUrlstringMEM0_URL / http://localhost:8000Server URL.
apiKeystringMEM0_ADMIN_API_KEYBearer token.
rerankbooleantrueAsk mem0 to rerank search results.
thresholdnumber0.1Minimum search score.
ts
import { mem0 } from '@tanstack/ai-memory/mem0'

const memory = mem0({
  user: 'alice', // mem0 user_id
  baseUrl: 'https://mem0.internal', // default: MEM0_URL
  apiKey: process.env.MEM0_ADMIN_API_KEY, // bearer token
  rerank: true, // rerank results
  threshold: 0.2, // stricter score floor
})
import { mem0 } from '@tanstack/ai-memory/mem0'

const memory = mem0({
  user: 'alice', // mem0 user_id
  baseUrl: 'https://mem0.internal', // default: MEM0_URL
  apiKey: process.env.MEM0_ADMIN_API_KEY, // bearer token
  rerank: true, // rerank results
  threshold: 0.2, // stricter score floor
})

honcho()

Hosted adapter backed by Honcho. recall returns a synthesized dialectic answer over the user's representation (no discrete fragments). @honcho-ai/sdk is an optional peer, loaded lazily.

OptionTypeDefaultPurpose
userstringscope.userId / 'demo-user'User peer id.
baseURLstringHONCHO_URL / http://localhost:8001Server URL.
workspaceIdstringHONCHO_APP_NAME / 'ai-memory'Workspace id.
apiKeystringHONCHO_API_KEY / 'dev-no-auth'API key.
assistantIdstring'assistant'Assistant peer id.
ts
import { honcho } from '@tanstack/ai-memory/honcho'

const memory = honcho({
  user: 'alice', // user peer
  baseURL: 'https://honcho.internal', // default: HONCHO_URL
  workspaceId: 'my-app', // default: HONCHO_APP_NAME
  apiKey: process.env.HONCHO_API_KEY, // default: 'dev-no-auth'
  assistantId: 'support-bot', // default: 'assistant'
})
import { honcho } from '@tanstack/ai-memory/honcho'

const memory = honcho({
  user: 'alice', // user peer
  baseURL: 'https://honcho.internal', // default: HONCHO_URL
  workspaceId: 'my-app', // default: HONCHO_APP_NAME
  apiKey: process.env.HONCHO_API_KEY, // default: 'dev-no-auth'
  assistantId: 'support-bot', // default: 'assistant'
})

Where to go next

  • Overview: the recall/save contract and how a turn flows
  • Quickstart: wire an adapter into a real chat() call
  • Operating memory: options, telemetry, devtools events, and failures
  • Custom Adapter: implement recall/save for a backend that isn't shipped