Skip to content

Memory

Memory retrieves durable background before generation and records new facts after a completed turn. It is off by default and must be bound to the verified user.

Enable Drizzle memory

code
import { createDrizzleMemory }
  from '@mordn/chat-widget/server/memory/drizzle';
 
export const { GET, POST, DELETE } = createChatHandler({
  getUserId: getChatUserId,
  model: anthropic('claude-sonnet-4-5'),
  store: createDrizzleChatStore(),
  memory: {
    adapter: createDrizzleMemory({
      agentId: 'support-bot',
      // Optional AI SDK models:
      // embeddingModel: google.textEmbeddingModel('text-embedding-004'),
      // extractionModel: anthropic('claude-haiku-4-5'),
    }),
    inject: true,
    extract: true,
    limit: 6,
    retrieveTimeoutMs: 1500,
  },
});

Without an embedding model, the Drizzle adapter uses keyword retrieval. Without an extraction model, it uses heuristic extraction.

Lifecycle

  1. Retrieve relevant memories before generation under a bounded timeout.
  2. Inject them as non-authoritative background.
  3. After answer content settles, extract and record memories during stream finalization.

Recording is fail-soft, but it is intentionally awaited during finalization so a serverless runtime does not freeze before writes finish. It is post-content, not fire-and-forget.

Configuration

adapterMemoryAdapterFactoryrequired
User-bound adapter factory.
injectbooleandefault: true
Retrieve and inject memories.
extractbooleandefault: true
Extract and record after turns.
limitnumberdefault: 6
Maximum injected memories.
minScorenumberdefault: 0
Minimum adapter score.
retrieveTimeoutMsnumberdefault: 1500
Hot-path retrieval budget.
formatForPrompt(memories, ctx) => string
Custom safe prompt block.
isEnabledForUser(ctx) => boolean | Promise<boolean>
Consent gate for read and write.
scopesMemoryScope[]default: ['user']
Requested retrieval tiers.
autoSaveScopeMemoryScopedefault: user
Tier used for extraction writes.
resolveOrgId(ctx) => string | null | Promise<string | null>
Server-verified org id for org memory.

Tiers and adapters

  • session: bound to user, agent, and conversation.
  • user: durable across the bound user's conversations.
  • org: intentionally shared across users in the same server-verified org and agent namespace.

Org retrieval is not restricted to facts written by the current user; sharing is the purpose of that tier. resolveOrgId must therefore be server-authoritative.

Built-in user controls

When memory is configured, the handler exposes:

RouteEffect
GET /memoryList the bound user's user-tier memories
DELETE /memoryDelete every memory row owned by the bound user for this agent, across tiers
DELETE /memory/:idDelete one memory row owned by the bound user
code
const response = await fetch('/api/chat/memory');
const { memories } = await response.json();

The built-in list route does not expose every session/org memory. The bulk-delete route removes rows owned by the bound user, including session/org rows they wrote, but never removes shared org rows owned by other users. Do not describe the list route as a complete cross-tier transparency view without adding an explicit, authorized admin surface.