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 "@use-crux/core";
import { generate } from "@use-crux/ai";
import { memory, episodes } from "@use-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