Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions redis/sdks/agentkit/eve.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<Accordion title="Options, storage, and reading history from your own code">
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<StoredMessage>({ 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.

<Accordion title="Options and storage">
Pass an object in place of `true` to tune storage:

- `chatHistory.prefix` — base key prefix (default `agentkit:chat`).
Expand All @@ -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.
Expand Down Expand Up @@ -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.
</Accordion>

## Working with Eve's `agent/` files
Expand Down
Loading