Vercel AI SDK Integration
Persistent memory and message history for the Vercel AI SDK
Persistent chat history and long-term user memory in one API. Semantic search included, no vector database to run.
streamText({ model, messages })
.toUIMessageStreamResponse({
onFinish: async ({ messages }) => {
// ← DialogueDB slots in here
},
})await dialogue.saveMessages(
toStoredMessages(messages)
)
// history is one call, fed to useChat
await db.getDialogue(id, { namespace })The integration in one call
From onFinish to a persisted conversation, in one line
Everything an AI app needs to remember users, without a schema, a vector database, or a load-history endpoint to maintain.
The conversation database with messages, memory, and semantic search behind one API. A single call inside onFinish persists the full turn.
onFinish: async ({ messages }) => {
await dialogue.saveMessages(
toStoredMessages(messages)
)
}A chat store for messages, a memory service for facts, a vector layer for search, and code to keep them aligned. Every piece works on its own; together they multiply the SDKs, auth tokens, and data models to maintain.
onFinish: async ({ response }) => {
// save messages via a chat store SDK
// send updates to a memory service SDK
// keep user IDs aligned across both
// track two data models in app code
// handle failures in either half
// pay for two subscriptions
}The memory difference
Memory that lives alongside every message, not in a second service
Standalone memory tools run beside a chat store and ask you to sync between them. DialogueDB puts messages, memory, and semantic search behind one API and one namespace, so agents pull both from the same place.
The whole conversation, not just extracted facts
Full message history and structured memory live in the same database. Search past turns by meaning, replay tool calls, or query stored facts, without forcing a choice between remembering everything and remembering meaningfully.
You decide what gets remembered
No background inference over conversations, no facts extracted for you. Call createMemory with the value you want to persist, so the memory store stays intentional and easy to audit.
One system, one integration
The same SDK, the same namespace, and the same auth token cover messages, memory, threads, and state. A standalone memory service adds another integration surface and sync logic between two stores.
Search memories relevant to the latest turn
db.searchMemories(userMessage, { namespace })Inject the matches into the system prompt
system: buildPrompt(memories)Stream the response with useChat, unchanged
streamText({ system, messages, onFinish })Save new context worth remembering
db.createMemory({ value, namespace })The Vercel AI SDK stays stateless. DialogueDB carries the user context between calls without touching the streaming path.
Install in 3 steps
From npm install to the first persisted turn, in under five minutes.
Install the client
npm install dialogue-dbSet the API key
DIALOGUE_DB_API_KEY=...Wire onFinish
await dialogue.saveMessages(
toStoredMessages(messages)
)No credit card. Free tier to start. Starter is $29/month when usage grows.
The reference example
A working Route Handler and client component you can clone and run as-is.
Persist the UI messages from toUIMessageStreamResponse's onFinish with a small toStoredMessages mapper, then reload them with validateUIMessages. The mapper is written to keep structured tool calls and the tool role intact so they round-trip unchanged.
Runs on Edge and serverless too. The client is HTTP-only, with no connection pool and no native dependencies.
The same client does more
Every capability below runs on the SDK you already installed, shown by what it lets you build.
Agent handoffs that keep context
Parent-child dialogues let sub-agents pick up mid-conversation without losing the thread.
dialogue.createThread()Facts and preferences across sessions
Store what an agent should remember about a user, separate from the message history.
db.createMemory()Search past conversations by meaning
Find every message a user has sent on a topic without relying on shared keywords.
db.searchMessages()Per-conversation scratchpads
Give each dialogue its own state for agent workflows, session flags, or in-progress context.
dialogue.saveState()Multi-user isolation without query code
Namespace every operation so users, tenants, and workspaces stay separated at the data layer.
namespace: "user_abc"Faithful tool call replay
Every tool invocation and result persists inside the message, so replays match reality.
toStoredMessages(messages)Where DialogueDB fits
Three trade-offs to weigh when adding memory and persistence to a Vercel AI SDK app.
| Approach | Persists messages | User memory across sessions | Same system |
|---|---|---|---|
| Standalone memory service | No, or a second store required | Yes, usually extracted for you | No, two services to run |
| Framework-bundled persistence | Yes | Rarely, or basic | Yes but framework-locked |
| Self-managed (Postgres + pgvector) | Design your own | Design your own | If you build it that way |
| DialogueDB | Yes | Yes, you control what's stored | Yes, one API |
If you know the AI SDK, you already know DialogueDB
Everything nests under a namespace. The core concepts map one-to-one to what the AI SDK already exposes.
The data model
namespace
scoped to one user or tenant
dialogue
messages, threads, state
indexed for semantic search
memory
facts and preferences, cross-session
indexed for semantic search
| AI SDK | DialogueDB |
|---|---|
Message | message |
useChat conversation | dialogue |
| User (from auth) | namespace |
| Tool call | message with tool metadata |
| User context to remember | memory |
What DialogueDB sees
Only what's needed for conversation storage
Model provider calls run directly from your Route Handler to the LLM. DialogueDB sits alongside that request path, not inside it.
The SDK only receives what you explicitly send (message content, memory values, and the identifiers you use to scope them). Model keys, user tokens, and unrelated app data never pass through, even by accident.
What we receive
- Message content and roles
- Memory values and metadata
- Dialogue and namespace IDs
What we never see
- Model provider credentials
- User authentication tokens
- Data outside the conversation
Two paths from your Route Handler
Route Handler
app/api/chat/route.ts
Your server code decides what goes where.
two independent calls
Model provider
OpenAI, Anthropic, etc.
Streaming call goes directly. DialogueDB never sees the payload or the credentials.
DialogueDB
Message + memory only
Receives what you explicitly send. Nothing implicit, nothing extra.
Frequently asked questions
One API for messages, memory, and search
Add it to your Vercel AI SDK app in minutes.