Crux
CookbookBasics

Chat with memory

Compose recent messages, working state, episodes, and proposed facts for a practical chat agent.

This recipe shows the default memory shape for a useful assistant. It keeps a short recent window, tracks typed task state, records notable events, and proposes long-term facts instead of silently changing the user's profile.

import { prompt } from "@use-crux/core";
import { generate } from "@use-crux/ai";
import {
  memory,
  recentMessages,
  workingState,
  episodes,
  facts,
} from "@use-crux/core/memory";
import { z } from "zod";

const assistantMemory = memory({
  id: "chat-assistant",
  records,
  namespace: ({ input }) => `user:${input.userId}:thread:${input.threadId}`,
  blocks: [
    recentMessages({ id: "recent", maxMessages: 12 }),
    workingState({
      id: "state",
      schema: z.object({
        goal: z.string().optional(),
        openQuestions: z.array(z.string()).default([]),
      }),
    }),
    episodes({ id: "episodes", embed: dense }),
    facts({
      id: "facts",
      embed: dense,
      extract: async (turn) => extractProfileFacts(turn),
      write: { mode: "propose" },
    }),
  ],
});

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

const chatPrompt = prompt({
  id: "chat",
  use: [assistantMemory],
  input: chatInput,
  system: "Answer clearly. Use memory only when it is relevant.",
  prompt: ({ input }) => input.message,
});

export async function reply(input: z.infer<typeof chatInput>) {
  const result = await generate(chatPrompt, { model, input });
  return result.text;
}

After generate() finishes, Crux captures the user and assistant messages and flushes the memory blocks. If the model extracts a candidate fact, it becomes a proposal:

const pending = await assistantMemory.proposals.list({
  namespace: "user:u1:thread:t1",
});

await assistantMemory.proposals.approve(pending[0].id);

For product UX, surface proposals in a settings panel or admin review queue. Use write: { mode: 'auto' } only for memories sourced from explicit user actions or trusted product events.

On this page

No Headings