diff --git a/redis/sdks/agentkit/eve.mdx b/redis/sdks/agentkit/eve.mdx index 312338d6..418db547 100644 --- a/redis/sdks/agentkit/eve.mdx +++ b/redis/sdks/agentkit/eve.mdx @@ -116,7 +116,41 @@ export default agentkit({ chatHistory: true }); Both tools take `userId` from the session, so the model cannot widen a lookup past the current user's own transcripts. - +Your own code reads the same store with `ChatHistory` from `@upstash/agentkit-sdk`, which is how you'd +build a history sidebar or run evals over past sessions: + +```bash +npm install @upstash/agentkit-sdk @upstash/redis +``` + +```ts +// app/api/chats/route.ts — server-side only; `userId` comes from your session, never the client +import { Redis } from "@upstash/redis"; +import { ChatHistory } from "@upstash/agentkit-sdk"; + +// `ChatHistory` is generic over the message type, and the extension doesn't export the shape its +// hook writes — declare it to get a typed `messages` array back. +type StoredMessage = { role: "user" | "assistant"; content: string; createdAt: number }; + +// Pass the same prefix / indexName / ttlSeconds you set on `chatHistory` in the mount file. +const history = new ChatHistory({ redis: Redis.fromEnv() }); + +// List: summaries only (no messages), newest-updated first. +const chats = await history.listChats({ userId, limit: 50 }); + +// Search: `$smart` fuzzy match, summaries plus a BM25 `score`. target: "user" | "model" | "both". +const hits = await history.searchChats({ userId, query: "the retry schema", target: "both", limit: 20 }); + +// Read: one full transcript, or null if this user has no chat with that sessionId. +const chat = await history.getChat({ userId, sessionId: hits[0].sessionId }); +chat?.messages.forEach((m) => console.log(m.role, m.content)); +``` + +`userId` must be the same value the extension resolved for those sessions, and both ids are Redis key +parts, so `:` in a derived value is replaced with `_`. `deleteChat({ userId, sessionId })` removes a +chat and its index entry. + + Pass an object in place of `true` to tune storage: - `chatHistory.prefix` — base key prefix (default `agentkit:chat`). @@ -128,10 +162,7 @@ own transcripts. plus `$smart`-indexed user and model text. A search returns summaries, and a read is capped at 50 messages per call with a `truncated` flag, so neither can flood the context window. - Your own code can read the same store with `ChatHistory` from `@upstash/agentkit-sdk` - (`listChats` / `searchChats` / `getChat`), which is how you'd build a history sidebar or run evals - over past sessions. Redis is the durable record here, since Eve's own workflow store is pruned after - a run completes. + Redis is the durable record here, since Eve's own workflow store is pruned after a run completes. These tools look history up on demand. They don't resume a session: Eve does that through its own session cursor. @@ -451,8 +482,9 @@ export default defineSearchTools({ and `count_books.ts`. The index is created on first use, and every returned tool is already `defineTool`-branded. - This package has no chat history. It comes from the extension, or from `ChatHistory` in - `@upstash/agentkit-sdk` if you're writing the code yourself. + This package has no chat history. It comes from the extension, or from + [`ChatHistory` in `@upstash/agentkit-sdk`](#how-to-add-searchable-chat-history-to-vercel-eve) if + you're writing the code yourself. ## Working with Eve's `agent/` files