$smart fuzzy operator.
@upstash/agentkit-ai-sdk is the Vercel AI SDK adapter — drop-ins for
generateText / streamText. redis defaults to Redis.fromEnv(), so you import only from this
package.
| Import | Feature |
|---|---|
createChatHistory | Durable chat history on Redis Search — save, list, and $smart-search a user’s transcripts. |
createMemoryTools | recall_memory + save_memory tools so the model reads and writes long-term memory. |
createSearchTools | search / aggregate / count tools over a Redis Search index (this is how you do RAG). |
createRateLimit | A configured Upstash Ratelimit to call before the model. |
cachedTools | Memoize a map of AI SDK tools’ results in Redis. |
AgentKit reads
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN from the environment by default.
Pass your own @upstash/redis client as redis to any helper to override.How to store chat history with the AI SDK
A Redis-backedChatHistory<UIMessage>, the durable source of truth for your conversations. userId
comes from your auth session; chatId is the useChat id that the client posts. Save the full
transcript from your route’s onFinish:
chatId from the page route and userId from the session, then seed useChat:
Config and how it's stored
Config and how it's stored
agentkit:chat:<userId>:<sessionId> (keyed per user, so two users
can’t collide on a sessionId), indexed over userId + sessionId (filters) and userMessages +
modelMessages ($smart fuzzy text); the raw messages array rides along unindexed. saveChat
overwrites the whole array (no delta merge) — useChat sends the full conversation. Other
methods: getChat / deleteChat ({ userId, sessionId }), listChats / searchChats
({ userId }).Security — userId is the tenant boundary
Security — userId is the tenant boundary
Every method takes a single object;
userId is required, non-empty, and may not contain :.
Derive it from a verified server-side auth source — the subject/user id from your auth provider
(Clerk, Auth.js/NextAuth, Supabase Auth, Auth0, …) — and never from a client-supplied header,
query param, or body (read it from the session in your route). A chat can’t be read or
overwritten under a different userId.How to add agent memory with the AI SDK
recall_memory and save_memory tools so the model reads and writes its own long-term memory.
Options and the userId tenant boundary
Options and the userId tenant boundary
userId(required) — a string, or(input, options) => string.redis— defaults toRedis.fromEnv().topK— max memoriesrecallreturns.minScore— BM25 relevance floor.recallToolName/saveToolName— override the tool names.
userId is the only tenant boundary (required, non-empty, no :). Derive it from a verified
server-side auth source (Clerk, Auth.js/NextAuth, Supabase Auth, Auth0, …) — never a
client-supplied value. Memories are stored at agentkit:memory:<userId>:<id>.How to add RAG with the AI SDK
search / aggregate / count tools over an Upstash Redis Search index; the model-facing
descriptions are generated from your schema.
Options
Options
schema(required) — built withsfrom@upstash/redis.redis— defaults toRedis.fromEnv().indexName— defaults to"agentkit:search".prefix— key prefix for indexed JSON docs (defaults to"<indexName>:").defaultLimit— default page size forsearch(10).
waitIndexing-ed) reactively on first use — no setup step.How to add rate limiting with the AI SDK
A configured Upstash Ratelimit. Call.limit(identifier) before
the model and short-circuit when over the limit.
Options
Options
limiter(required) — e.g.Ratelimit.slidingWindow(20, "1 m")orfixedWindow(...).redis— defaults toRedis.fromEnv().prefix— base key prefix; keys are<prefix>:<identifier>(defaultagentkit:rateLimit).
identifier to .limit() to throttle per user.How to cache tools with the AI SDK
Memoize a map of AI SDK tools’ results in Redis. Each tool is cached under its map key, scoped touserId.
Options
Options
Pass tools built with the AI SDK’s
tool() (so each keeps full input/output inference). Second arg:userId(required) — a string, or(input, options) => string; scopes every entry to this user.redis— defaults toRedis.fromEnv().ttlSeconds— default per-result TTL for every tool.
agentkit:toolCache:<userId>:<toolName>:<hash-of-input> — the toolName is the map
key, so you never pass a name yourself.How to put it all together with the AI SDK
A singlestreamText route can wire every feature: rate limit first, then memory, search, and cached
tools, persisting the whole conversation in onFinish:
useChat UI, chat sidebar with fuzzy search, inline tool calls)
lives in examples/ai-sdk-demo.
AgentKit on GitHub
Source, packages, and the full example apps.
Vercel AI SDK
The AI SDK this adapter plugs into.