Package Exports
- memvault
- memvault/ai-sdk
- memvault/anthropic
- memvault/openai
Readme
memvault
Persistent, tenant-isolated memory tools for AI agents. Prisma-powered. Drop-in tools for Vercel AI SDK, OpenAI, and Anthropic.
No cloud. No Neo4j. No $249/mo paywall. Just your PostgreSQL.
Install
npm install memvaultSetup
1. Add the model to your Prisma schema
model MemvaultMemory {
id String @id @default(cuid())
tenantId String
type String @default("general")
content String
metadata Json?
tags String[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
expiresAt DateTime?
@@index([tenantId])
@@index([tenantId, type])
@@map("memvault_memories")
}2. Run migration
npx prisma migrate dev --name add-memvault3. Create vault instance
import { MemVault } from "memvault"
const vault = new MemVault({ db: prisma.memvaultMemory })Usage with AI SDKs
Vercel AI SDK
import { createMemVaultTools } from "memvault/ai-sdk"
import { generateText } from "ai"
import { anthropic } from "@ai-sdk/anthropic"
const tools = createMemVaultTools({ vault, tenantId: user.id })
const result = await generateText({
model: anthropic("claude-sonnet-4-6"),
tools,
prompt: "Help the user with their project"
})OpenAI SDK
import { createMemVaultTools } from "memvault/openai"
const { tools, handleToolCall } = createMemVaultTools({ vault, tenantId: user.id })
const response = await openai.responses.create({
model: "gpt-4o",
tools,
input: "Help the user..."
})
// Handle tool calls from the response
for (const output of response.output) {
if (output.type === "function_call") {
const result = await handleToolCall(output.name, JSON.parse(output.arguments))
}
}Anthropic SDK
import { createMemVaultTools } from "memvault/anthropic"
const { tools, handleToolCall } = createMemVaultTools({ vault, tenantId: user.id })
const message = await anthropic.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
tools,
messages: [{ role: "user", content: "Help me..." }]
})
// Handle tool calls from the response
for (const block of message.content) {
if (block.type === "tool_use") {
const result = await handleToolCall(block.name, block.input)
}
}Standalone (no LLM)
const tenant = vault.tenant("user-123")
await tenant.remember({
content: "Prefers dark mode",
type: "preference",
tags: ["ui", "theme"]
})
const memories = await tenant.recall({ type: "preference" })
await tenant.update(memoryId, { content: "Switched to light mode" })
await tenant.forget(memoryId)Tools Provided
Each SDK integration provides 4 tools:
| Tool | Description |
|---|---|
memvault_remember |
Save information to persistent memory |
memvault_recall |
Retrieve relevant memories with filters |
memvault_update |
Update existing memories |
memvault_forget |
Delete a specific memory |
The LLM decides when to use each tool based on the built-in descriptions.
Tenant Isolation
Every operation is scoped to a tenantId. No tenant can read, update, or delete another tenant's memories.
const alice = vault.tenant("alice")
const bob = vault.tenant("bob")
await alice.remember({ content: "Alice's secret" })
await bob.recall() // Returns empty — Bob can't see Alice's memoriesMemory Types
Organize memories by type:
preference— User preferences and settingsfact— Facts about the userfeedback— User feedback on behaviorproject— Project context and detailsreference— Links and external referencesgeneral— Default catch-all- Any custom string
TTL (Time-to-Live)
Set temporary memories that auto-expire:
await tenant.remember({
content: "Currently debugging auth flow",
type: "context",
ttl: 3600 // expires in 1 hour
})API
MemVault
new MemVault({ db })— Create instance with Prisma delegatevault.tenant(tenantId)— Get tenant-scoped vault
TenantVault
tenant.remember(input)— Save a memorytenant.recall(filter?)— Query memoriestenant.get(id)— Get specific memorytenant.update(id, input)— Update a memorytenant.forget(id)— Delete a memorytenant.forgetAll()— Delete all tenant memoriestenant.count(filter?)— Count memories
License
MIT