Crux
CookbookRAG

Episodic recall

Recall relevant past chat events with the episodes memory block.

Use episodes() when the agent needs to answer questions about what happened before. It is append-only, scoped by namespace, and can use dense vector search when the backing store supports it.

import { prompt } from '@crux/core'
import { generate } from '@crux/ai'
import { memory, episodes } from '@crux/core/memory'
import { z } from 'zod'

const chatEpisodes = episodes({
  id: 'episodes',
  embed: dense,
})

const chatMemory = memory({
  id: 'chat',
  store,
  namespace: ({ input }) => `user:${input.userId}:thread:${input.threadId}`,
  blocks: [chatEpisodes],
})

const assistantInput = z.object({
  userId: z.string(),
  threadId: z.string(),
  message: z.string(),
})

const assistant = prompt({
  id: 'assistant',
  use: [chatMemory],
  input: assistantInput,
  system: 'Use relevant prior episodes when answering.',
  prompt: ({ input }) => input.message,
})

export async function handleMessage(input: z.infer<typeof assistantInput>) {
  return generate(assistant, { model, input })
}

You can also record non-chat events directly:

await chatEpisodes.record(
  {
    content: 'User accepted the pricing recommendation',
    metadata: { source: 'ui', event: 'accepted_recommendation' },
  },
  {
    store,
    namespace: 'user:u1:thread:t1',
    memoryId: 'chat',
  },
)

Direct calls should pass the same memoryId and namespace as the composed memory() instance so reads and writes share keys.

On this page

No Headings