docs: staleness sweep — current model IDs, AI SDK APIs, one search signature

Fixes across existing pages: stale claude-3-sonnet -> current models,
deprecated ai/react + toAIStreamResponse -> current AI SDK APIs, five
divergent search signatures unified to client.search.memories (v4) /
client.search.documents (v3), singular containerTag in v4 contexts,
from-zep containerTag type error, canonical processing-status enum,
corrected 'v4 has no SDK' claim, internal links re-pointed at final
destinations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dhravya Shah 2026-07-17 15:54:30 -07:00
parent 4970ad4b2c
commit 492e09bae2
57 changed files with 95 additions and 8082 deletions

View file

@ -385,7 +385,7 @@ When you add content, Supermemory:
Track progress with `GET /v3/documents/{id}`:
```typescript
const doc = await client.documents.get("abc123");
console.log(doc.status); // "queued" | "processing" | "done"
console.log(doc.status); // "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed"
```
<AccordionGroup>
@ -479,4 +479,4 @@ console.log(doc.status); // "queued" | "processing" | "done"
- [Search Memories](/search) — Query your content
- [User Profiles](/user-profiles) — Get user context
- [Organizing & Filtering](/concepts/filtering) — Container tags and metadata
- [Organizing & Filtering](/concepts/hybrid-search) — Container tags and metadata

View file

@ -1,278 +0,0 @@
---
title: "Basic Usage"
description: "Simple examples of adding text content to Supermemory"
---
Learn how to add basic text content to Supermemory with simple, practical examples.
## Add Simple Text
The most basic operation - adding plain text content.
<CodeGroup>
```typescript TypeScript
const response = await client.add({
content: "Artificial intelligence is transforming how we work and live"
});
console.log(response);
// Output: { id: "abc123", status: "queued" }
```
```python Python
response = client.add(
content="Artificial intelligence is transforming how we work and live"
)
print(response)
# Output: {"id": "abc123", "status": "queued"}
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Artificial intelligence is transforming how we work and live"
}'
```
</CodeGroup>
## Add with Container Tags
Group related content using container tags.
<CodeGroup>
```typescript TypeScript
const response = await client.add({
content: "Q4 2024 revenue exceeded projections by 15%",
containerTag: "financial_reports"
});
console.log(response.id);
// Output: xyz789
```
```python Python
response = client.add(
content="Q4 2024 revenue exceeded projections by 15%",
container_tag="financial_reports"
)
print(response['id'])
# Output: xyz789
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Q4 2024 revenue exceeded projections by 15%",
"containerTag": "financial_reports"
}'
# Response: {"id": "xyz789", "status": "queued"}
```
</CodeGroup>
## Add with Metadata
Attach metadata for better search and filtering.
<CodeGroup>
```typescript TypeScript
await client.add({
content: "New onboarding flow reduces drop-off by 30%",
containerTag: "product_updates",
metadata: {
impact: "high",
team: "product"
}
});
```
```python Python
client.add(
content="New onboarding flow reduces drop-off by 30%",
container_tag="product_updates",
metadata={
"impact": "high",
"team": "product"
}
)
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "New onboarding flow reduces drop-off by 30%",
"containerTag": "product_updates",
"metadata": {"impact": "high", "team": "product"}
}'
```
</CodeGroup>
## Add Multiple Documents
Process multiple related documents.
<CodeGroup>
```typescript TypeScript
const notes = [
"API redesign discussion",
"Security audit next month",
"New hire starting Monday"
];
const results = await Promise.all(
notes.map(note =>
client.add({
content: note,
containerTag: "meeting_2024_01_15"
})
)
);
```
```python Python
notes = [
"API redesign discussion",
"Security audit next month",
"New hire starting Monday"
]
for note in notes:
client.add(
content=note,
container_tag="meeting_2024_01_15"
)
```
```bash cURL
# Add each note with separate requests
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "API redesign discussion", "containerTag": "meeting_2024_01_15"}'
```
</CodeGroup>
## Add URLs
Process web pages, YouTube videos, and other URLs automatically.
<CodeGroup>
```typescript TypeScript
// Web page
await client.add({
content: "https://example.com/article",
containerTag: "articles"
});
// YouTube video (auto-transcribed)
await client.add({
content: "https://youtube.com/watch?v=dQw4w9WgXcQ",
containerTag: "videos"
});
// Google Docs
await client.add({
content: "https://docs.google.com/document/d/abc123/edit",
containerTag: "docs"
});
```
```python Python
# Web page
client.add(
content="https://example.com/article",
container_tag="articles"
)
# YouTube video (auto-transcribed)
client.add(
content="https://youtube.com/watch?v=dQw4w9WgXcQ",
container_tag="videos"
)
# Google Docs
client.add(
content="https://docs.google.com/document/d/abc123/edit",
container_tag="docs"
)
```
```bash cURL
# Web page
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "https://example.com/article", "containerTag": "articles"}'
# YouTube video
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "https://youtube.com/watch?v=dQw4w9WgXcQ", "containerTag": "videos"}'
```
</CodeGroup>
## Add Markdown Content
Supermemory preserves markdown formatting.
<CodeGroup>
```typescript TypeScript
const markdown = `
# Project Documentation
## Features
- **Real-time sync**
- **AI search**
- **Enterprise security**
`;
await client.add({
content: markdown,
containerTag: "docs"
});
```
```python Python
markdown = """
# Project Documentation
## Features
- **Real-time sync**
- **AI search**
- **Enterprise security**
"""
client.add(
content=markdown,
container_tag="docs"
)
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "# Project Documentation\n\n## Features\n- **Real-time sync**\n- **AI search**", "containerTag": "docs"}'
```
</CodeGroup>

View file

@ -1,195 +0,0 @@
---
title: "File Upload"
description: "Upload PDFs, images, and other files to Supermemory"
---
Upload files directly to Supermemory for automatic content extraction and processing.
## Upload a PDF
Extract text from PDFs with OCR support.
<CodeGroup>
```typescript TypeScript
const file = fs.createReadStream('document.pdf');
const response = await client.documents.uploadFile({
file: file,
containerTags: 'documents'
});
console.log(response.id);
// Output: pdf_123
```
```python Python
with open('document.pdf', 'rb') as file:
response = client.documents.upload_file(
file=file,
container_tags='documents'
)
print(response['id'])
# Output: pdf_123
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "file=@document.pdf" \
-F "containerTags=documents"
# Response: {"id": "pdf_123", "status": "processing"}
```
</CodeGroup>
## Upload Images with OCR
Extract text from images.
<CodeGroup>
```typescript TypeScript
const image = fs.createReadStream('screenshot.png');
await client.documents.uploadFile({
file: image,
containerTags: 'images'
});
```
```python Python
with open('screenshot.png', 'rb') as file:
client.documents.upload_file(
file=file,
container_tags='images'
)
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "file=@screenshot.png" \
-F "containerTags=images"
```
</CodeGroup>
## Browser File Upload
Handle browser file uploads.
<CodeGroup>
```javascript JavaScript
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('containerTags', 'uploads');
const response = await fetch('https://api.supermemory.ai/v3/documents/file', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`
},
body: formData
});
const result = await response.json();
console.log(result.id);
```
```typescript React
function handleUpload(file: File) {
const formData = new FormData();
formData.append('file', file);
formData.append('containerTags', 'uploads');
return fetch('https://api.supermemory.ai/v3/documents/file', {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: formData
});
}
```
```bash cURL
# Browser uploads use FormData, same as file upload
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "file=@document.pdf" \
-F "containerTags=uploads"
```
</CodeGroup>
## Upload Multiple Files
Batch upload with rate limiting.
<CodeGroup>
```typescript TypeScript
for (const file of files) {
const stream = fs.createReadStream(file);
await client.documents.uploadFile({
file: stream,
containerTags: 'batch'
});
// Rate limit
await new Promise(r => setTimeout(r, 1000));
}
```
```python Python
import time
for file_path in files:
with open(file_path, 'rb') as file:
client.documents.upload_file(
file=file,
container_tags='batch'
)
time.sleep(1) # Rate limit
```
```bash cURL
# Upload each file separately with delays
for file in *.pdf; do
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "file=@$file" \
-F "containerTags=batch"
sleep 1 # Rate limit
done
```
</CodeGroup>
## Supported File Types
### Documents
| Format | Extensions | Processing |
|--------|------------|------------|
| PDF | .pdf | Text extraction, OCR for scanned pages |
| Microsoft Word | .doc, .docx | Full text and formatting extraction |
| Plain Text | .txt, .md | Direct text processing |
| CSV | .csv | Structured data extraction |
### Images
| Format | Extensions | Processing |
|--------|------------|------------|
| JPEG | .jpg, .jpeg | OCR text extraction |
| PNG | .png | OCR text extraction |
| GIF | .gif | OCR for static images |
| WebP | .webp | OCR text extraction |
### Size Limits
- **Maximum file size**: 50MB
- **Recommended size**: < 10MB for optimal processing
- **Large files**: May take longer to process

View file

@ -1,249 +0,0 @@
---
title: "Add Memories Overview"
description: "Add content to Supermemory through text, files, or URLs"
sidebarTitle: "Overview"
---
Add any type of content to Supermemory - text, files, URLs, images, videos, and more. Everything is automatically processed into searchable memories that form part of your intelligent knowledge graph.
## Prerequisites
Before adding memories, you need to set up the Supermemory client:
- **Install the SDK** for your language
- **Get your API key** from [Supermemory Console](https://console.supermemory.ai)
- **Initialize the client** with your API key
<CodeGroup>
```bash npm
npm install supermemory
```
```bash pip
pip install supermemory
```
</CodeGroup>
<CodeGroup>
```typescript TypeScript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
```
```python Python
from supermemory import Supermemory
import os
client = Supermemory(
api_key=os.environ.get("SUPERMEMORY_API_KEY")
)
```
</CodeGroup>
## Quick Start
<CodeGroup>
```typescript TypeScript
// Add text content
const result = await client.add({
content: "Machine learning enables computers to learn from data",
containerTag: "ai-research",
metadata: { priority: "high" }
});
console.log(result);
// Output: { id: "abc123", status: "queued" }
```
```python Python
# Add text content
result = client.add(
content="Machine learning enables computers to learn from data",
container_tags=["ai-research"],
metadata={"priority": "high"}
)
print(result)
# Output: {"id": "abc123", "status": "queued"}
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Machine learning enables computers to learn from data",
"containerTag": "ai-research",
"metadata": {"priority": "high"}
}'
# Response: {"id": "abc123", "status": "queued"}
```
</CodeGroup>
## Key Concepts
<Note>
**New to Supermemory?** Read [How Supermemory Works](/how-it-works) to understand the knowledge graph architecture and the distinction between documents and memories.
</Note>
### Quick Overview
- **Documents**: Raw content you upload (PDFs, URLs, text)
- **Memories**: Searchable chunks created automatically with relationships
- **Container Tags**: Group related content for better context
- **Metadata**: Additional information for filtering
### Content Sources
Add content through three methods:
1. **Direct Text**: Send text content directly via API
2. **File Upload**: Upload PDFs, images, videos for extraction
3. **URL Processing**: Automatic extraction from web pages and platforms
## Endpoints
<Warning>
Remember, these endpoints add documents. Memories are inferred by Supermemory.
</Warning>
### Add Content
`POST /v3/documents`
Add text content, URLs, or any supported format.
<CodeGroup>
```typescript TypeScript
await client.add({
content: "Your content here",
containerTag: "project"
});
```
```python Python
client.add(
content="Your content here",
container_tags=["project"]
)
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Your content here", "containerTag": "project"}'
```
</CodeGroup>
### Upload File
`POST /v3/documents/file`
Upload files directly for processing.
<CodeGroup>
```typescript TypeScript
await client.documents.uploadFile({
file: fileStream,
containerTag: "project"
});
```
```python Python
client.documents.upload_file(
file=open('file.pdf', 'rb'),
container_tags='project'
)
```
```bash cURL
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "file=@document.pdf" \
-F "containerTags=project"
```
</CodeGroup>
### Update Memory
`PATCH /v3/documents/{id}`
Update existing document content or metadata. Content changes trigger reindexing; metadata-only updates do not.
<CodeGroup>
```typescript TypeScript
await client.documents.update("doc_id", {
content: "Updated content"
});
```
```python Python
client.documents.update("doc_id", {
"content": "Updated content"
})
```
```bash cURL
curl -X PATCH "https://api.supermemory.ai/v3/documents/doc_id" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Updated content"}'
```
</CodeGroup>
## Supported Content Types
### Documents
- PDF with OCR support
- Google Docs, Sheets, Slides
- Notion pages
- Microsoft Office files
### Media
- Images (JPG, PNG, GIF, WebP) with OCR
### Web Content
- Twitter/X posts
- YouTube videos with captions
### Text Formats
- Plain text
- Markdown
- CSV files
<Note> Refer to the [connectors guide](/connectors/overview) to learn how you can connect Google Drive, Notion, and OneDrive and sync files in real-time. </Note>
## Response Format
```json
{
"id": "D2Ar7Vo7ub83w3PRPZcaP1",
"status": "queued"
}
```
- **`id`**: Unique document identifier
- **`status`**: Processing state (`queued`, `processing`, `done`)
## Next Steps
- [Memory Operations](/memory-operations) - Track status, list, update, and delete memories
- [Search Memories](/search) - Search your content

View file

@ -1,156 +0,0 @@
---
title: "Parameters"
description: "Complete reference for add memory parameters"
---
Detailed parameter documentation for adding memories to Supermemory.
## Request Parameters
### Required Parameters
<ParamField body="content" type="string" required>
The content to process into memories. Can be:
- Plain text content
- URL to process
- HTML content
- Markdown text
```json
{
"content": "Machine learning is a subset of AI..."
}
```
**URL Examples:**
```json
{
"content": "https://youtube.com/watch?v=dQw4w9WgXcQ"
}
```
</ParamField>
### Optional Parameters
<ParamField body="containerTag" type="string">
**Recommended.** Single tag to group related memories. Improves search performance.
Default: `"sm_project_default"`
```json
{
"containerTag": "project_alpha"
}
```
<Note>
Use `containerTag` (singular) for better performance than `containerTags` (array).
</Note>
</ParamField>
<ParamField body="metadata" type="object">
Additional metadata as key-value pairs. Values must be strings, numbers, or booleans.
```json
{
"metadata": {
"source": "research-paper",
"author": "John Doe",
"priority": 1,
"reviewed": true
}
}
```
**Restrictions:**
- No nested objects
- No arrays as values
- Keys must be strings
- Values: string, number, or boolean only
</ParamField>
<ParamField body="customId" type="string">
Your own identifier for the document. Enables deduplication and updates.
**Maximum length:** 255 characters
```json
{
"customId": "doc_2024_01_research_ml"
}
```
**Use cases:**
- Prevent duplicate uploads
- Update existing documents
- Sync with external systems
</ParamField>
<ParamField body="raw" type="string">
Raw content to store alongside processed content. Useful for preserving original formatting.
```json
{
"content": "# Machine Learning\n\nML is a subset of AI...",
"raw": "# Machine Learning\n\nML is a subset of AI..."
}
```
</ParamField>
## File Upload Parameters
For `POST /v3/documents/file` endpoint:
<ParamField body="file" type="file" required>
The file to upload. Supported formats:
- **Documents:** PDF, DOC, DOCX, TXT, MD
- **Images:** JPG, PNG, GIF, WebP
- **Videos:** MP4, WebM, AVI
**Maximum size:** 50MB
</ParamField>
<ParamField body="containerTags" type="string">
Container tag for the uploaded file (sent as form field).
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-F "file=@document.pdf" \
-F "containerTags=research"
```
</ParamField>
## Container Tag Patterns
### Recommended Patterns
```typescript
// By user
"user_123"
// By project
"project_alpha"
// By organization and type
"org_456_research"
// By time period
"2024_q1_reports"
// By data source
"slack_channel_general"
```
### Performance Considerations
```typescript
// ✅ FAST: Single tag
{ "containerTag": "project_alpha" }
// ⚠️ SLOWER: Multiple tags
{ "containerTags": ["project_alpha", "backend", "auth"] }
// ❌ AVOID: Too many tags
{ "containerTags": ["tag1", "tag2", "tag3", "tag4", "tag5"] }
```

View file

@ -1,216 +0,0 @@
---
title: "Infinite Chat"
description: "Unlimited context for chat applications with automatic memory management"
sidebarTitle: "Infinite Chat"
---
Infinite Chat provides unlimited context for chat applications with automatic memory management.
## Setup
```typescript
import { streamText } from "ai"
const infiniteChat = createAnthropic({
baseUrl: 'https://api.supermemory.ai/v3/https://api.anthropic.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("claude-3-sonnet"),
messages: [
{ role: "user", content: "Hello! Remember that I love TypeScript." }
]
})
```
## Provider Configuration
### Named Providers
<CodeGroup>
```typescript OpenAI
const infiniteChat = createOpenAI({
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("gpt-5"),
messages: [...]
})
```
```typescript Anthropic
const infiniteChat = createAnthropic({
baseUrl: 'https://api.supermemory.ai/v3/https://api.anthropic.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("claude-3-sonnet"),
messages: [...]
})
```
```typescript Google
const infiniteChat = createGoogleGenerativeAI({
baseUrl: 'https://api.supermemory.ai/v3/https://generativelanguage.googleapis.com/v1beta',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("gemini-pro"),
messages: [...]
})
```
```typescript Groq
const infiniteChat = createGroq({
baseUrl: 'https://api.supermemory.ai/v3/https://api.groq.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("mixtral-8x7b"),
messages: [...]
})
```
</CodeGroup>
### Custom Provider URL
```typescript
const infiniteChat = createOpenAI({
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
```
## Example Usage
```typescript
import { streamText } from "ai"
const infiniteChat = createOpenAI({
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
const result = await streamText({
model: infiniteChat("gpt-5"),
messages: [
{ role: "user", content: "What did we discuss yesterday?" }
]
})
return result.toAIStreamResponse()
```
## Configuration Options
```typescript
interface ConfigWithProviderName {
providerName: 'openai' | 'anthropic' | 'openrouter' |
'deepinfra' | 'groq' | 'google' | 'cloudflare'
providerApiKey: string
headers?: Record<string, string>
}
interface ConfigWithProviderUrl {
providerUrl: string
providerApiKey: string
headers?: Record<string, string>
}
```
### Custom Headers
Add user IDs, conversation IDs, or other metadata:
```typescript
const infiniteChat = createOpenAI({
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
```
## Comparison with Memory Tools
| Feature | Infinite Chat | Memory Tools |
|---------|--------------|--------------|
| Memory Management | Automatic | Manual |
| Context Handling | Automatic | Manual |
| Tool Calls | None | searchMemories, addMemory, fetchMemory |
| Best For | Chat apps | AI agents |
| Setup Complexity | Simple | Moderate |
## Headers
Add user and conversation context:
```typescript
const infiniteChat = createOpenAI({
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
apiKey: 'your-provider-api-key',
headers: {
'x-supermemory-api-key': 'supermemory-api-key',
'x-sm-conversation-id': 'conversation-id'
}
})
```
## Comparison
| Feature | Infinite Chat | Memory Tools |
|---------|--------------|-------------|
| Memory Management | Automatic | Manual |
| Context Handling | Automatic | Manual |
| Tool Calls | None | searchMemories, addMemory, fetchMemory |
| Best For | Chat apps | AI agents |
## Next Steps
<CardGroup cols={2}>
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
Explore explicit memory control
</Card>
<Card title="Examples" icon="code" href="/cookbook/ai-sdk-integration">
See complete implementations
</Card>
</CardGroup>

View file

@ -1,147 +0,0 @@
---
title: "Memory Tools"
description: "Add memory capabilities to your AI agents with Vercel AI SDK tools"
sidebarTitle: "Memory Tools"
---
Memory tools allow AI agents to search, add, and fetch memories.
## Setup
```typescript
import { streamText } from "ai"
import { createOpenAI } from "@ai-sdk/openai"
import { supermemoryTools } from "@supermemory/tools/ai-sdk"
const openai = createOpenAI({
apiKey: "YOUR_OPENAI_KEY"
})
const result = await streamText({
model: openai("gpt-5"),
prompt: "Remember that my name is Alice",
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
})
```
## Available Tools
### Search Memories
Semantic search through user memories:
```typescript
const result = await streamText({
model: openai("gpt-5"),
prompt: "What are my dietary preferences?",
tools: supermemoryTools("API_KEY")
})
// The AI will automatically call searchMemories tool
// Example tool call:
// searchMemories({ informationToGet: "dietary preferences and restrictions" })
```
### Add Memory
Store new information:
```typescript
const result = await streamText({
model: anthropic("claude-3-sonnet"),
prompt: "Remember that I'm allergic to peanuts",
tools: supermemoryTools("API_KEY")
})
// The AI will automatically call addMemory tool
// Example tool call:
// addMemory({ memory: "User is allergic to peanuts" })
```
### Fetch Memory
Retrieve specific memory by ID:
```typescript
const result = await streamText({
model: openai("gpt-5"),
prompt: "Get the details of memory abc123",
tools: supermemoryTools("API_KEY")
})
// The AI will automatically call fetchMemory tool
// Example tool call:
// fetchMemory({ memoryId: "abc123" })
```
## Using Individual Tools
For more control, import tools separately:
```typescript
import {
searchMemoriesTool,
addMemoryTool,
fetchMemoryTool
} from "@supermemory/tools/ai-sdk"
// Use only search tool
const result = await streamText({
model: openai("gpt-5"),
prompt: "What do you know about me?",
tools: {
searchMemories: searchMemoriesTool("API_KEY", {
projectId: "personal"
})
}
})
// Combine with custom tools
const result = await streamText({
model: anthropic("claude-3"),
prompt: "Help me with my calendar",
tools: {
searchMemories: searchMemoriesTool("API_KEY"),
// Your custom tools
createEvent: yourCustomTool,
sendEmail: anotherCustomTool
}
})
```
## Tool Results
Each tool returns a result object:
```typescript
// searchMemories result
{
success: true,
results: [...], // Array of memories
count: 5
}
// addMemory result
{
success: true,
memory: { id: "mem_123", ... }
}
// fetchMemory result
{
success: true,
memory: { id: "mem_123", content: "...", ... }
}
```
## Next Steps
<CardGroup cols={2}>
<Card title="User Profiles" icon="user" href="/integrations/ai-sdk">
Automatic personalization with profiles
</Card>
<Card title="Examples" icon="code" href="/cookbook/ai-sdk-integration">
See more complete examples
</Card>
</CardGroup>

View file

@ -1,93 +0,0 @@
---
title: "AI SDK Integration"
description: "Use Supermemory with Vercel AI SDK for seamless memory management"
sidebarTitle: "Overview"
---
The Supermemory AI SDK provides native integration with Vercel's AI SDK through two approaches: **User Profiles** for automatic personalization and **Memory Tools** for agent-based interactions.
<Card title="Supermemory tools on npm" icon="npm" href="https://www.npmjs.com/package/@supermemory/tools">
Check out the NPM page for more details
</Card>
## Installation
```bash
npm install @supermemory/tools
```
## User Profiles with Middleware
Automatically inject user profiles into every LLM call for instant personalization. Customize how memories are formatted with the `promptTemplate` option for XML-based prompting, custom branding, or model-specific formatting.
```typescript
import { generateText } from "ai"
import { withSupermemory } from "@supermemory/tools/ai-sdk"
import { openai } from "@ai-sdk/openai"
// Wrap your model with Supermemory - profiles are automatically injected
const modelWithMemory = withSupermemory(openai("gpt-5"), {
containerTag: "user-123",
customId: "conversation-456",
})
const result = await generateText({
model: modelWithMemory,
messages: [{ role: "user", content: "What do you know about me?" }]
})
// The model automatically has the user's profile context!
```
<Note>
**Memory saving is enabled by default** (`addMemory: "always"`). New conversations are persisted automatically. To opt out, set `addMemory: "never"`:
```typescript
const modelWithMemory = withSupermemory(openai("gpt-5"), {
containerTag: "user-123",
customId: "conversation-456",
addMemory: "never",
})
```
</Note>
```typescript
```
## Memory Tools
Add memory capabilities to AI agents with search, add, and fetch operations.
```typescript
import { streamText } from "ai"
import { createAnthropic } from "@ai-sdk/anthropic"
import { supermemoryTools } from "@supermemory/tools/ai-sdk"
const anthropic = createAnthropic({
apiKey: "YOUR_ANTHROPIC_KEY"
})
const result = await streamText({
model: anthropic("claude-3-sonnet"),
prompt: "Remember that my name is Alice",
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
})
```
## When to Use
| Approach | Use Case |
|----------|----------|
| User Profiles | Personalized LLM responses with automatic user context |
| Memory Tools | AI agents that need explicit memory control |
## Next Steps
<CardGroup cols={2}>
<Card title="User Profiles" icon="user" href="/integrations/ai-sdk">
Automatic personalization with profiles
</Card>
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
Agent-based memory management
</Card>
</CardGroup>

View file

@ -1,357 +0,0 @@
---
title: "User Profiles with AI SDK"
description: "Automatically inject user profiles into LLM calls for instant personalization"
sidebarTitle: "User Profiles"
---
## Overview
The `withSupermemory` middleware automatically injects user profiles into your LLM calls, providing instant personalization without manual prompt engineering or API calls.
<Note>
**New to User Profiles?** Read the [conceptual overview](/user-profiles) to understand what profiles are and why they're powerful for LLM personalization.
</Note>
## Quick Start
```typescript
import { generateText } from "ai"
import { withSupermemory } from "@supermemory/tools/ai-sdk"
import { openai } from "@ai-sdk/openai"
// Wrap any model with Supermemory middleware
const modelWithMemory = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conversation-456",
})
// Use normally - profiles are automatically injected!
const result = await generateText({
model: modelWithMemory,
messages: [{ role: "user", content: "Help me with my current project" }]
})
// The model knows about the user's background, skills, and current work!
```
## How It Works
The `withSupermemory` middleware:
1. **Intercepts** your LLM calls before they reach the model
2. **Fetches** the user's profile based on the container tag
3. **Injects** profile data into the system prompt automatically
4. **Forwards** the enhanced prompt to your LLM
All of this happens transparently - you write code as if using a normal model, but get personalized responses.
<Note>
**Memory saving is enabled by default** (`addMemory: "always"`). New conversations are persisted automatically. To opt out, set `addMemory: "never"`:
```typescript
const model = withSupermemory(openai("gpt-5"), {
containerTag: "user-123",
customId: "conversation-456",
addMemory: "never",
})
```
</Note>
## Memory Search Modes
Configure how the middleware retrieves and uses memory:
### Profile Mode (Default)
Retrieves the user's complete profile without query-specific search. Best for general personalization.
```typescript
// Default behavior - profile mode
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
})
// Or explicitly specify
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
mode: "profile",
})
const result = await generateText({
model,
messages: [{ role: "user", content: "What do you know about me?" }]
})
// Response uses full user profile for context
```
### Query Mode
Searches memories based on the user's specific message. Best for finding relevant information.
```typescript
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
mode: "query",
})
const result = await generateText({
model,
messages: [{
role: "user",
content: "What was that Python script I wrote last week?"
}]
})
// Searches for memories about Python scripts from last week
```
### Full Mode
Combines profile AND query-based search for comprehensive context. Best for complex interactions.
```typescript
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
mode: "full",
})
const result = await generateText({
model,
messages: [{
role: "user",
content: "Help me debug this similar to what we did before"
}]
})
// Uses both profile (user's expertise) AND search (previous debugging sessions)
```
## Custom Prompt Templates
Customize how memories are formatted and injected into the system prompt using the `promptTemplate` option. This is useful for:
- Using XML-based prompting (e.g., for Claude models)
- Custom branding (removing "supermemories" references)
- Controlling how your agent describes where information comes from
```typescript
import { generateText } from "ai"
import { withSupermemory, type MemoryPromptData } from "@supermemory/tools/ai-sdk"
import { openai } from "@ai-sdk/openai"
const customPrompt = (data: MemoryPromptData) => `
<user_memories>
Here is some information about your past conversations with the user:
${data.userMemories}
${data.generalSearchMemories}
</user_memories>
`.trim()
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
mode: "full",
promptTemplate: customPrompt,
})
const result = await generateText({
model,
messages: [{ role: "user", content: "What do you know about me?" }]
})
```
### MemoryPromptData Interface
The `MemoryPromptData` object passed to your template function provides:
- `userMemories`: Pre-formatted markdown combining static profile facts (name, preferences, goals) and dynamic context (current projects, recent interests)
- `generalSearchMemories`: Pre-formatted search results based on semantic similarity to the current query (empty string if mode is "profile")
- `searchResults`: Raw search results array (`Array<{ memory: string; metadata?: Record<string, unknown> }>`) for traversing, filtering, or selectively including results based on metadata
### XML-Based Prompting for Claude
Claude models perform better with XML-structured prompts:
```typescript
const claudePrompt = (data: MemoryPromptData) => `
<context>
<user_profile>
${data.userMemories}
</user_profile>
<relevant_memories>
${data.generalSearchMemories}
</relevant_memories>
</context>
Use the above context to provide personalized responses.
`.trim()
const model = withSupermemory(anthropic("claude-3-sonnet"), {
containerTag: "user-123",
customId: "conv-1",
mode: "full",
promptTemplate: claudePrompt,
})
```
### Filtering Search Results
Use `searchResults` to traverse the raw data and pick what's important:
```typescript
const selectivePrompt = (data: MemoryPromptData) => {
const relevant = data.searchResults.filter(
(r) => (r.metadata?.score as number) > 0.7
)
return `
<user_memories>
${data.userMemories}
</user_memories>
<relevant_context>
${relevant.map((r) => `- ${r.memory}`).join("\n")}
</relevant_context>
`.trim()
}
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
mode: "full",
promptTemplate: selectivePrompt,
})
```
### Custom Branding
Remove "supermemories" references and use your own branding:
```typescript
const brandedPrompt = (data: MemoryPromptData) => `
You are an AI assistant with access to the user's personal knowledge base.
User Profile:
${data.userMemories}
Relevant Context:
${data.generalSearchMemories}
Use this information to provide personalized and contextually relevant responses.
`.trim()
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
promptTemplate: brandedPrompt,
})
```
### Default Template
If no `promptTemplate` is provided, the default format is used:
```typescript
const defaultPrompt = (data: MemoryPromptData) =>
`User Supermemories: \n${data.userMemories}\n${data.generalSearchMemories}`.trim()
```
## Verbose Logging
Enable detailed logging to see exactly what's happening:
```typescript
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
verbose: true, // Enable detailed logging
})
const result = await generateText({
model,
messages: [{ role: "user", content: "Where do I live?" }]
})
// Console output:
// [supermemory] Searching memories for container: user-123
// [supermemory] User message: Where do I live?
// [supermemory] System prompt exists: false
// [supermemory] Found 3 memories
// [supermemory] Memory content: You live in San Francisco, California...
// [supermemory] Creating new system prompt with memories
```
## Comparison with Direct API
The AI SDK middleware abstracts away the complexity of manual profile management:
<Tabs>
<Tab title="With AI SDK (Simple)">
```typescript
// Simple setup
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
})
// Use normally
const result = await generateText({
model,
messages: [{ role: "user", content: "Help me" }]
})
```
</Tab>
<Tab title="Without AI SDK (Complex)">
```typescript
// Manual profile fetching
const profileRes = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: { /* ... */ },
body: JSON.stringify({ containerTag: "user-123" })
})
const profile = await profileRes.json()
// Manual prompt construction
const systemPrompt = `User Profile:\n${profile.profile.static?.join('\n')}`
// Manual LLM call with profile
const result = await generateText({
model: openai("gpt-4"),
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: "Help me" }
]
})
```
</Tab>
</Tabs>
## Limitations
- **Beta Feature**: The `withSupermemory` middleware is currently in beta
- **Container Tag Required**: You must provide a valid container tag
- **API Key Required**: Ensure `SUPERMEMORY_API_KEY` is set in your environment
## Next Steps
<CardGroup cols={2}>
<Card title="User Profiles Concepts" icon="brain" href="/user-profiles">
Understand how profiles work conceptually
</Card>
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
Add explicit memory operations to your agents
</Card>
<Card title="API Reference" icon="code" href="https://api.supermemory.ai/v3/reference#tag/profile">
Explore the underlying profile API
</Card>
<Card title="NPM Package" icon="npm" href="https://www.npmjs.com/package/@supermemory/tools">
View the package on NPM
</Card>
</CardGroup>
<Info>
**Pro Tip**: Start with profile mode for general personalization, then experiment with query and full modes as you understand your use case better.
</Info>

View file

@ -1,176 +0,0 @@
---
title: "Container Tags"
sidebarTitle: "Container Tags"
description: "The isolation boundary that groups and partitions memories by user, project, or any logical scope"
icon: "folder"
---
A **container tag** is the primary way you organize and isolate memories in Supermemory. It's a simple string identifier you attach to content when you add it — and that you pass back when you search, list, or update it.
Think of a container tag as a **namespace**: every memory tagged with `user_alex` lives in its own isolated space, completely separate from memories tagged `user_jordan`. This is what makes Supermemory safe to use in multi-tenant applications — one user can never see another user's memories unless you explicitly query across both tags.
<CardGroup cols={2}>
<Card title="Group" icon="layers">
Bucket memories by user, project, agent, workspace, or any boundary that makes sense for your app.
</Card>
<Card title="Isolate" icon="shield">
Each container tag maps to its own vector namespace, so search and retrieval never leak across boundaries.
</Card>
</CardGroup>
---
## How it works
When you add a memory with a container tag, Supermemory automatically creates a **space** for that tag (scoped to your organization) if one doesn't already exist. You don't need to provision anything ahead of time — the first write with a new tag creates the container, and subsequent writes reuse it.
```typescript
// First call auto-creates the "user_alex" container
await client.add({
content: "Alex prefers dark mode and concise answers",
containerTag: "user_alex",
});
// Later, retrieve only Alex's memories
const results = await client.search.memories({
q: "what are the user's UI preferences?",
containerTag: "user_alex",
});
```
Under the hood, each container tag is hashed into a dedicated vector namespace. Embeddings, chunks, and memory entries for one tag are stored and searched independently of every other tag — there is no shared index to filter through, which is why isolation is strict rather than best-effort.
<Note>
A container tag is an **opaque identifier you choose**. Supermemory does not parse meaning out of it — `user_123`, `project_mobile`, and `org:acme:team:growth` are all equally valid. Pick a convention that mirrors the access boundaries in your own application.
</Note>
---
## Naming rules
Container tags are validated on every request. A tag must:
- Be **100 characters or less**
- Contain only **alphanumeric characters, hyphens (`-`), underscores (`_`), and colons (`:`)**
Matching pattern: `^[a-zA-Z0-9_:-]+$`
```typescript
// ✅ Valid
"user_123"
"project-mobile-app"
"org:acme:user:john"
"tenant_42_workspace_7"
// ❌ Invalid — spaces, slashes, and other symbols are rejected
"user 123"
"project/mobile"
"team@acme"
```
The colon is intentionally allowed so you can build **hierarchical** tags (for example `org:acme:user:john`) that encode several levels of structure in a single identifier.
---
## `containerTag` vs `containerTags`
Supermemory's current API uses a **single** `containerTag` string per request.
<Warning>
The plural `containerTags` array field is **deprecated**. It still works for backward compatibility on older (`/v3`) endpoints, but new integrations should use the singular `containerTag` string. The `/v4` API only accepts `containerTag`.
</Warning>
| API field | Type | Status |
|-----------|------|--------|
| `containerTag` | `string` | ✅ Current — use this |
| `containerTags` | `string[]` | ⚠️ Deprecated |
---
## Where container tags are used
The same tag flows through the entire lifecycle of a memory. Pass it consistently and your data stays neatly partitioned.
| Operation | Behavior |
|-----------|----------|
| **Add** | Writes the memory into the tag's container (auto-creating the space). |
| **Search** | Restricts retrieval to the given tag's namespace. |
| **List** | Returns only memories belonging to the tag(s). |
| **Update / Delete** | Targets the memory inside the specified tag's container. |
```typescript
// Add
await client.add({ content: "Q1 planning notes", containerTag: "project_q1" });
// Search within the same container
await client.search.memories({ q: "planning", containerTag: "project_q1" });
// List everything in the container
await client.documents.list({ containerTags: ["project_q1"] });
```
---
## Access control
Container tags are also an **authorization boundary**, not just an organizational one. Two mechanisms can restrict which tags a given caller may touch:
- **API key scopes** — an API key can be limited to a specific set of container tags, with read or write permission per tag.
- **Member restrictions** — an organization member can be granted access to only certain container tags.
When a request is restricted, Supermemory validates the requested tag against the caller's allowed set:
- Requesting a tag outside the allowed set returns `403 Forbidden`.
- A write (add/update/delete) to a read-only tag returns `403 Forbidden`.
- If no tag is supplied by a restricted caller, the request is automatically scoped to their allowed tag(s).
This means you can hand out an API key that is physically incapable of reading or writing another tenant's data, enforced at the data layer rather than in your application code.
---
## Per-container settings
Each container tag can carry its own configuration, independent of other tags in the same organization:
| Setting | Purpose |
|---------|---------|
| `name` | A human-friendly display name for the container. |
| `entityContext` | A custom context prompt applied when processing documents in this container — useful for steering extraction and summarization per project or tenant. |
```typescript
await client.containerTags.update("project_research", {
entityContext: "This project contains research papers about machine learning.",
});
```
Container tags can also be **merged** when you need to consolidate two buckets of memories into one.
---
## Choosing a convention
Pick a tagging scheme that maps onto the isolation boundaries your application actually needs.
| Pattern | Example | Use case |
|---------|---------|----------|
| User isolation | `user_{userId}` | Per-user memory in a consumer app |
| Project grouping | `project_{projectId}` | Project- or workspace-scoped content |
| Agent scoping | `agent_{agentId}` | Separate long-term memory per AI agent |
| Hierarchical | `org:{orgId}:user:{userId}` | Multi-level, multi-tenant SaaS |
<Tip>
Keep tags **deterministic** — derive them directly from IDs you already have (a user ID, a tenant ID) so you can always reconstruct the right tag at query time without a lookup.
</Tip>
---
## Next steps
<CardGroup cols={2}>
<Card title="Organizing & Filtering" icon="filter" href="/concepts/filtering">
Combine container tags with metadata filters for precise retrieval.
</Card>
<Card title="Adding Memories" icon="plus" href="/add-memories">
See container tags in action across the add API.
</Card>
</CardGroup>

View file

@ -14,7 +14,7 @@ Raw text, conversations, notes, or any string content.
```typescript
await client.add({
content: "User prefers dark mode and uses vim keybindings",
containerTags: ["user_123"]
containerTag: "user_123"
});
```
@ -29,7 +29,7 @@ Send a URL and Supermemory fetches, extracts, and indexes the content.
```typescript
await client.add({
content: "https://docs.example.com/api-reference",
containerTags: ["documentation"]
containerTag: "documentation"
});
```

View file

@ -1,359 +0,0 @@
---
title: "Organizing & Filtering Memories"
sidebarTitle: "Multi-Tenancy / Filtering"
description: "Use container tags and metadata to organize and retrieve memories"
icon: "users"
---
Supermemory provides two ways to organize your memories:
<CardGroup cols={2}>
<Card title="Container Tags" icon="folder">
**Organize memories** into isolated spaces by user, project, or workspace
</Card>
<Card title="Metadata Filtering" icon="database">
**Query memories** by custom properties like category, status, or date
</Card>
</CardGroup>
Both can be used independently or together for precise filtering.
---
## Container Tags
Container tags create isolated memory spaces. Use them to separate memories by user, project, or any logical boundary.
### Adding Memories with Tags
```typescript
await client.add({
content: "Meeting notes from Q1 planning",
containerTags: ["user_123"]
});
```
### Searching with Tags
```typescript
const results = await client.search.documents({
q: "planning notes",
containerTags: ["user_123"]
});
```
<Note>
Container tags use **exact array matching**. A memory tagged `["user_123", "project_a"]` won't match a search for just `["user_123"]`.
</Note>
### Recommended Patterns
| Pattern | Example | Use Case |
|---------|---------|----------|
| User isolation | `user_{userId}` | Per-user memories |
| Project grouping | `project_{projectId}` | Project-specific content |
| Hierarchical | `org_{orgId}_team_{teamId}` | Multi-level organization |
<AccordionGroup>
<Accordion title="More Container Tag Examples">
```typescript
// Multi-tenant SaaS - isolate by organization and user
await client.add({
content: "Company policy document",
containerTags: ["org_acme_user_john"]
});
// Search only within that user's org context
const results = await client.search.documents({
q: "vacation policy",
containerTags: ["org_acme_user_john"]
});
// Project-based isolation
await client.add({
content: "Sprint 5 retrospective notes",
containerTags: ["project_mobile_app"]
});
// Time-based segmentation
await client.add({
content: "Q1 2024 financial report",
containerTags: ["user_cfo_2024_q1"]
});
```
**API field differences:**
| Endpoint | Field | Type |
|----------|-------|------|
| `/v3/search` | `containerTags` | Array |
| `/v4/search` | `containerTag` | String |
| `/v3/documents/list` | `containerTags` | Array |
</Accordion>
</AccordionGroup>
---
## Metadata
Metadata lets you attach custom properties to memories and filter by them later.
### Adding Memories with Metadata
```typescript
await client.add({
content: "Technical design document for auth system",
containerTags: ["user_123"],
metadata: {
category: "engineering",
priority: "high",
year: 2024
}
});
```
### Searching with Metadata Filters
Filters must be wrapped in `AND` or `OR` arrays:
```typescript
const results = await client.search.documents({
q: "design document",
containerTags: ["user_123"],
filters: {
AND: [
{ key: "category", value: "engineering" },
{ key: "priority", value: "high" }
]
}
});
```
### Filter Types
| Type | Example | Description |
|------|---------|-------------|
| String equality | `{ key: "status", value: "published" }` | Exact match |
| String contains | `{ filterType: "string_contains", key: "title", value: "react" }` | Substring match |
| Numeric | `{ filterType: "numeric", key: "priority", value: "5", numericOperator: ">=" }` | Number comparison |
| Array contains | `{ filterType: "array_contains", key: "tags", value: "important" }` | Check array membership |
### Combining Filters
Use `AND` and `OR` for complex queries:
```typescript
const results = await client.search.documents({
q: "meeting notes",
filters: {
AND: [
{ key: "type", value: "meeting" },
{
OR: [
{ key: "team", value: "engineering" },
{ key: "team", value: "product" }
]
}
]
}
});
```
### Excluding Results
Use `negate: true` to exclude matches:
```typescript
const results = await client.search.documents({
q: "documentation",
filters: {
AND: [
{ key: "status", value: "draft", negate: true }
]
}
});
```
<AccordionGroup>
<Accordion title="More Metadata Filter Examples">
**String contains (substring search):**
```typescript
// Find documents with "machine learning" in the description
const results = await client.search.documents({
q: "AI research",
filters: {
AND: [
{
filterType: "string_contains",
key: "description",
value: "machine learning",
ignoreCase: true
}
]
}
});
```
**Numeric comparisons:**
```typescript
// Find high-priority items created after a specific date
const results = await client.search.documents({
q: "tasks",
filters: {
AND: [
{
filterType: "numeric",
key: "priority",
value: "7",
numericOperator: ">="
},
{
filterType: "numeric",
key: "created_timestamp",
value: "1704067200", // Unix timestamp
numericOperator: ">="
}
]
}
});
```
**Array contains (check array membership):**
```typescript
// Find documents where a specific user is a participant
const results = await client.search.documents({
q: "meeting notes",
filters: {
AND: [
{
filterType: "array_contains",
key: "participants",
value: "alice@company.com"
}
]
}
});
```
**Complex nested filters:**
```typescript
// (category = "tech" OR category = "science") AND status != "archived"
const results = await client.search.documents({
q: "research papers",
filters: {
AND: [
{
OR: [
{ key: "category", value: "tech" },
{ key: "category", value: "science" }
]
},
{ key: "status", value: "archived", negate: true }
]
}
});
```
**Numeric operator negation mapping:**
When using `negate: true`, operators flip:
- `<` becomes `>=`
- `<=` becomes `>`
- `>` becomes `<=`
- `>=` becomes `<`
- `=` becomes `!=`
</Accordion>
<Accordion title="Real-World Patterns">
**User's work documents from 2024:**
```typescript
const results = await client.search.documents({
q: "quarterly report",
containerTags: ["user_123"],
filters: {
AND: [
{ key: "category", value: "work" },
{ key: "type", value: "report" },
{ filterType: "numeric", key: "year", value: "2024", numericOperator: "=" }
]
}
});
```
**Team meeting notes with specific participants:**
```typescript
const results = await client.search.documents({
q: "sprint planning",
containerTags: ["project_alpha"],
filters: {
AND: [
{ key: "type", value: "meeting" },
{
OR: [
{ filterType: "array_contains", key: "participants", value: "alice" },
{ filterType: "array_contains", key: "participants", value: "bob" }
]
}
]
}
});
```
**Exclude drafts and deprecated content:**
```typescript
const results = await client.search.documents({
q: "documentation",
filters: {
AND: [
{ key: "status", value: "draft", negate: true },
{ filterType: "string_contains", key: "content", value: "deprecated", negate: true },
{ filterType: "array_contains", key: "tags", value: "archived", negate: true }
]
}
});
```
</Accordion>
</AccordionGroup>
---
## Quick Reference
### When Adding Memories
```typescript
await client.add({
content: "Your content here",
containerTags: ["user_123"], // Isolation
metadata: { key: "value" } // Custom properties
});
```
### When Searching
```typescript
const results = await client.search.documents({
q: "search query",
containerTags: ["user_123"], // Must match exactly
filters: { // Optional metadata filters
AND: [{ key: "status", value: "published" }]
}
});
```
### Metadata Key Rules
- Allowed characters: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`
- Max length: 64 characters
- No spaces or special characters
---
## Next Steps
<CardGroup cols={2}>
<Card title="Search" icon="search" href="/search">
Apply filters in search queries
</Card>
<Card title="Add Memories" icon="plus" href="/add-memories">
Add content with container tags and metadata
</Card>
</CardGroup>

View file

@ -205,7 +205,7 @@ client.add(
# Add a user-specific memory
client.add(
content="User prefers Android over iOS",
container_tags=["user_123"], # User-specific
container_tag="user_123", # User-specific
metadata={
"type": "preference",
"confidence": "high"
@ -216,9 +216,9 @@ client.add(
### 3. Hybrid Retrieval
```python
# Search combines both approaches
results = client.documents.search(
query="What phone should I recommend?",
container_tags=["user_123"], # Gets user memories
results = client.search.memories(
q="What phone should I recommend?",
container_tag="user_123", # Gets user memories
# Also searches general knowledge
)

View file

@ -95,13 +95,13 @@ Supermemory combines the best of both approaches in every search:
</Card>
</CardGroup>
With `searchMode: "hybrid"` (the default), you get both:
Search memories and include the matching documents, and you get both:
```typescript
const results = await client.search({
const results = await client.search.memories({
q: "how do I deploy the app?",
containerTag: "user_123",
searchMode: "hybrid"
include: { documents: true }
});
// Returns:
@ -121,8 +121,9 @@ Two flags give you fine-grained control over result quality:
Re-scores results using a cross-encoder model for better relevance:
```typescript
const results = await client.search({
const results = await client.search.memories({
q: "complex technical question",
containerTag: "user_123",
rerank: true // +~100ms, significantly better ranking
});
```
@ -134,8 +135,9 @@ const results = await client.search({
Expands your query to capture more relevant results:
```typescript
const results = await client.search({
const results = await client.search.memories({
q: "how to auth",
containerTag: "user_123",
rewriteQuery: true // Expands to "authentication login oauth jwt..."
});
```

View file

@ -24,7 +24,7 @@ export async function POST(request: Request) {
const { messages } = await request.json()
const result = await streamText({
model: anthropic('claude-3-sonnet-20240229'),
model: anthropic('claude-sonnet-4-5'),
messages,
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
system: `You are a helpful personal assistant. When users share information about themselves,
@ -32,14 +32,14 @@ export async function POST(request: Request) {
personalized responses. Always be proactive about remembering important details.`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```
```typescript Client Component
'use client'
import { useChat } from 'ai/react'
import { useChat } from '@ai-sdk/react'
export default function PersonalAssistant() {
const { messages, input, handleInputChange, handleSubmit } = useChat()
@ -109,7 +109,7 @@ export async function POST(request: Request) {
4. Always be empathetic and solution-focused`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```
@ -130,7 +130,7 @@ export async function POST(request: Request) {
const { messages, userId, courseId } = await request.json()
const result = await streamText({
model: anthropic('claude-3-haiku-20240307'),
model: anthropic('claude-haiku-4-5'),
messages,
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
containerTags: [userId]
@ -142,7 +142,7 @@ export async function POST(request: Request) {
4. Tracking topics they've mastered vs topics they need more help with`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```
@ -177,7 +177,7 @@ export async function POST(request: Request) {
4. Track research progress and important discoveries`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```
@ -230,7 +230,7 @@ export async function POST(request: Request) {
const { messages, repositoryId } = await request.json()
const result = await streamText({
model: anthropic('claude-3-sonnet-20240229'),
model: anthropic('claude-sonnet-4-5'),
messages,
tools: {
// Use individual tools for more control
@ -262,7 +262,7 @@ export async function POST(request: Request) {
4. Learn from debugging sessions and common issues`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```
@ -313,7 +313,7 @@ export async function POST(request: Request) {
3. Search for conflicts using searchMemories`
})
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
}
```

View file

@ -480,12 +480,12 @@ If you cannot resolve the issue completely, prepare a clear summary for escalati
}
})
return result.toAIStreamResponse({
data: {
return result.toUIMessageStreamResponse({
messageMetadata: () => ({
needsEscalation,
customerTier: customer.tier,
contextCount: contextResults.length
}
})
})
} catch (error) {
@ -724,7 +724,7 @@ If you cannot resolve the issue completely, prepare a clear summary for escalati
'use client'
import { useState, useEffect } from 'react'
import { useChat } from 'ai/react'
import { useChat } from '@ai-sdk/react'
import { CustomerContextManager } from '@/lib/customer-context'
interface Customer {

View file

@ -369,12 +369,12 @@ If the question cannot be answered from the provided documents, respond with: "I
maxTokens: 1000
})
return result.toAIStreamResponse({
data: {
return result.toUIMessageStreamResponse({
messageMetadata: () => ({
sources,
searchResultsCount: searchResults.results.length,
totalResults: searchResults.total
}
})
})
} catch (error) {
@ -525,7 +525,7 @@ If the question cannot be answered from the provided documents, respond with: "I
'use client'
import { useState, useRef } from 'react'
import { useChat } from 'ai/react'
import { useChat } from '@ai-sdk/react'
import { DocumentProcessor } from '@/lib/document-processor'
interface Document {

View file

@ -610,10 +610,10 @@ Later:
#### Return Streaming Response
```typescript
return result.toAIStreamResponse()
return result.toUIMessageStreamResponse()
```
`toAIStreamResponse()` converts the streaming result into a format the frontend can consume. It:
`toUIMessageStreamResponse()` converts the streaming result into a format the frontend can consume. It:
- Sets appropriate headers for streaming
- Formats data for the `useChat` hook
- Handles errors gracefully
@ -643,7 +643,7 @@ Catches any errors (API failures, tool errors, etc.) and returns a clean error r
| **Memory Search** | Manual `search_user_memories()` call | AI SDK calls `searchMemories` tool automatically |
| **Memory Add** | Manual `add_user_memory()` call | AI SDK calls `addMemory` tool automatically |
| **Tool Decision** | You decide when to search/add | AI decides based on conversation context |
| **Streaming** | Manual SSE formatting | `toAIStreamResponse()` handles it |
| **Streaming** | Manual SSE formatting | `toUIMessageStreamResponse()` handles it |
| **Error Handling** | Try/catch in each function | AI SDK handles tool errors |
**Python = Manual Control**
@ -660,7 +660,7 @@ Replace `app/page.tsx`:
```typescript
'use client'
import { useChat } from 'ai/react'
import { useChat } from '@ai-sdk/react'
import { useState } from 'react'
export default function ChatPage() {
@ -824,7 +824,7 @@ Create `scripts/check-memories.ts`:
const userId = "your_user_id_here"
const containerTag = `user_${userId}`
const response = await fetch('https://api.supermemory.ai/v3/memories', {
const response = await fetch('https://api.supermemory.ai/v3/documents/list', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,

View file

@ -125,7 +125,7 @@ Get a specific document with its processing status.
```typescript
const doc = await client.documents.get("doc_abc123");
console.log(doc.status); // "queued" | "processing" | "done" | "failed"
console.log(doc.status); // "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed"
console.log(doc.content);
```
</Tab>
@ -153,6 +153,7 @@ Get a specific document with its processing status.
| `extracting` | Extracting content (OCR, transcription) |
| `chunking` | Breaking into searchable pieces |
| `embedding` | Creating vector representations |
| `indexing` | Indexing for retrieval |
| `done` | Ready for search |
| `failed` | Processing failed |

View file

@ -136,7 +136,6 @@ Look up past interactions:
results = memory.search.memories(
q="pasta recipes we discussed",
container_tag="user_123",
search_mode="hybrid",
limit=5
)

View file

@ -74,19 +74,19 @@ Both `containerTag` and `customId` are required.
**Profile Mode (Default)** - Retrieves the user's complete profile:
```typescript
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "profile" })
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "profile" })
```
**Query Mode** - Searches memories based on the user's message:
```typescript
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "query" })
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "query" })
```
**Full Mode** - Combines profile AND query-based search:
```typescript
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "full" })
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "full" })
```
### Custom Prompt Templates
@ -107,7 +107,7 @@ const claudePrompt = (data: MemoryPromptData) => `
</context>
`.trim()
const model = withSupermemory(anthropic("claude-3-sonnet"), {
const model = withSupermemory(anthropic("claude-sonnet-4-5"), {
containerTag: "user-123",
customId: "conv-1",
mode: "full",
@ -118,7 +118,7 @@ const model = withSupermemory(anthropic("claude-3-sonnet"), {
### Verbose Logging
```typescript
const model = withSupermemory(openai("gpt-4"), {
const model = withSupermemory(openai("gpt-4o"), {
containerTag: "user-123",
customId: "conv-1",
verbose: true,
@ -166,7 +166,7 @@ import { supermemoryTools } from "@supermemory/tools/ai-sdk"
const anthropic = createAnthropic({ apiKey: "YOUR_ANTHROPIC_KEY" })
const result = await streamText({
model: anthropic("claude-3-sonnet"),
model: anthropic("claude-sonnet-4-5"),
prompt: "Remember that my name is Alice",
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
})
@ -189,7 +189,7 @@ const result = await streamText({
```typescript
const result = await streamText({
model: anthropic("claude-3-sonnet"),
model: anthropic("claude-sonnet-4-5"),
prompt: "Remember that I'm allergic to peanuts",
tools: supermemoryTools("API_KEY")
})

View file

@ -77,7 +77,6 @@ export const searchMemories = action({
return await memory.search.memories({
q: query,
containerTag: userId,
searchMode: "hybrid",
limit: limit ?? 10,
});
},

View file

@ -122,7 +122,6 @@ Pull up past interactions before running a crew:
results = memory.search.memories(
q="previous project recommendations",
container_tag="user_abc",
search_mode="hybrid",
limit=10
)

View file

@ -148,4 +148,4 @@ If you run your own supermemory API, set **`base_url`** (and any other host-spec
</Card>
</CardGroup>
Questions about the API or product? [Discord](https://supermemory.link/discord) · [support@supermemory.com](mailto:support@supermemory.com) · [Developer docs](/intro)
Questions about the API or product? [Discord](https://supermemory.link/discord) · [support@supermemory.ai](mailto:support@supermemory.ai) · [Developer docs](/intro)

View file

@ -137,7 +137,6 @@ Search returns both extracted memories and document chunks:
results = memory.search.memories(
q="async programming",
container_tag="user_123",
search_mode="hybrid", # Searches memories + document chunks
limit=5
)

View file

@ -154,7 +154,6 @@ Search returns both extracted memories and document chunks:
results = memory.search.memories(
q="graph algorithms",
container_tag="user_123",
search_mode="hybrid",
limit=5
)

View file

@ -289,7 +289,7 @@ interface DocumentWithMemories {
url?: string | null;
source?: string | null;
type?: string | null;
status: 'pending' | 'processing' | 'done' | 'failed';
status: 'unknown' | 'queued' | 'extracting' | 'chunking' | 'embedding' | 'indexing' | 'done' | 'failed';
metadata?: Record<string, string | number | boolean> | null;
createdAt: string | Date;
updatedAt: string | Date;

View file

@ -135,7 +135,6 @@ Look up past interactions before running an agent:
results = memory.search.memories(
q="previous travel recommendations",
container_tag="user_123",
search_mode="hybrid",
limit=5
)

View file

@ -269,7 +269,7 @@ openclaw supermemory wipe # Delete all memories (requires confirma
Automatic per-channel separation is not supported yet. If you need this, let us know — with enough requests, we'll implement it right away.
<Card title="Request this feature" icon="mail" href="mailto:support@supermemory.com?subject=Feature%20Request%3A%20Per-Channel%20Container%20Tags&body=Hey%2C%0A%0AMy%20name%20is%20%5Byour%20name%5D.%20I%20just%20saw%20that%20you%20offer%20custom%20plugins.%0A%0AThis%20is%20my%20use%20case%3A%20%5Bdescribe%20your%20use%20case%5D%0A%0AI%20would%20love%20to%20have%20separate%20container%20tags%20for%20each%20channel%20so%20my%20session%20memories%20are%20automatically%20isolated.%0A%0AThanks!">
<Card title="Request this feature" icon="mail" href="mailto:support@supermemory.ai?subject=Feature%20Request%3A%20Per-Channel%20Container%20Tags&body=Hey%2C%0A%0AMy%20name%20is%20%5Byour%20name%5D.%20I%20just%20saw%20that%20you%20offer%20custom%20plugins.%0A%0AThis%20is%20my%20use%20case%3A%20%5Bdescribe%20your%20use%20case%5D%0A%0AI%20would%20love%20to%20have%20separate%20container%20tags%20for%20each%20channel%20so%20my%20session%20memories%20are%20automatically%20isolated.%0A%0AThanks!">
Email us with your use case.
</Card>
</Accordion>

View file

@ -36,7 +36,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
});
// Add a memory
await client.add({ content: "Meeting notes from Q1 planning", containerTags: ["user_123"] });
await client.add({ content: "Meeting notes from Q1 planning", containerTag: "user_123" });
// Search memories
const response = await client.search.documents({
@ -57,7 +57,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
// Add with metadata
await client.add({
content: "Technical design doc",
containerTags: ["user_123"],
containerTag: "user_123",
metadata: { category: "engineering", priority: "high" }
});
@ -98,7 +98,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
)
# Add a memory
client.add(content="Meeting notes from Q1 planning", container_tags=["user_123"])
client.add(content="Meeting notes from Q1 planning", container_tag="user_123")
# Search memories
response = client.search.documents(
@ -119,7 +119,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
# Add with metadata
client.add(
content="Technical design doc",
container_tags=["user_123"],
container_tag="user_123",
metadata={"category": "engineering", "priority": "high"}
)

View file

@ -1,87 +0,0 @@
---
title: "Basic Listing"
description: "Simple memory retrieval across languages"
---
Simple memory retrieval examples for getting started with the list memories endpoint.
## Basic Usage
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
const response = await client.documents.list({ limit: 10 });
console.log(response);
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
response = client.documents.list(limit=10)
print(response)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 10}'
```
</Tab>
</Tabs>
## With Custom Parameters
<Tabs>
<Tab title="TypeScript">
```typescript
const response = await client.documents.list({
containerTags: ["user_123"],
limit: 20,
sort: "updatedAt",
order: "desc"
});
console.log(`Found ${response.memories.length} memories`);
```
</Tab>
<Tab title="Python">
```python
response = client.documents.list(
container_tags=["user_123"],
limit=20,
sort="updatedAt",
order="desc"
)
print(f"Found {len(response.memories)} memories")
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"containerTags": ["user_123"],
"limit": 20,
"sort": "updatedAt",
"order": "desc"
}'
```
</Tab>
</Tabs>
<Info>
Start with small `limit` values (10-20) when testing to avoid overwhelming responses.
</Info>

View file

@ -1,506 +0,0 @@
---
title: "Filtering Memories"
description: "Filter memories by container tags and metadata using SQL-based filtering"
---
Filter memories using container tags and metadata. The filtering system uses SQL query construction, so you need to structure your filters like database queries.
## Filter by Container Tags
Container tags use exact array matching - memories must have the exact same tags in the same order.
<Tabs>
<Tab title="TypeScript">
```typescript
// Single tag - matches memories with exactly ["user_123"]
const userMemories = await client.documents.list({
containerTags: ["user_123"]
});
// Multiple tags - matches memories with exactly ["user_123", "project_ai"]
const projectMemories = await client.documents.list({
containerTags: ["user_123", "project_ai"]
});
```
</Tab>
<Tab title="Python">
```python
# Single tag
user_memories = client.documents.list(container_tags=["user_123"])
# Multiple tags (exact match)
project_memories = client.documents.list(
container_tags=["user_123", "project_ai"]
)
```
</Tab>
<Tab title="cURL">
```bash
# Single tag
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTags": ["user_123"]}'
# Multiple tags
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTags": ["user_123", "project_ai"]}'
```
</Tab>
</Tabs>
## Metadata Filtering with SQL Logic
The `filters` parameter allows filtering by metadata fields using SQL-like query structures. Since we use SQL query construction in the backend, you need to structure your filters like database queries with explicit AND/OR logic.
### Why This Structure?
In SQL databases, `AND` has higher precedence than `OR`. Without explicit grouping, a query like:
```
category = 'programming' OR framework = 'react' AND difficulty = 'advanced'
```
Is interpreted as:
```
category = 'programming' OR (framework = 'react' AND difficulty = 'advanced')
```
The JSON structure forces explicit grouping to prevent unexpected results.
<Info>
**Filter Structure Rules:**
- Always wrap conditions in `AND` or `OR` arrays (even single conditions)
- Pass the filter as an object (TypeScript/Python) or JSON string (cURL)
- Each condition needs `key`, `value`, and `negate` properties
- `negate: false` for normal matching, `negate: true` for exclusion
</Info>
### Simple Metadata Filter
<Tabs>
<Tab title="TypeScript">
```typescript
// Filter by single metadata field
const programmingMemories = await client.documents.list({
filters: {
AND: [
{ key: "category", value: "programming", negate: false }
]
}
});
```
</Tab>
<Tab title="Python">
```python
# Filter by single metadata field
programming_memories = client.documents.list(
filters={
"AND": [
{"key": "category", "value": "programming", "negate": False}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"programming\",\"negate\":false}]}"
}'
```
</Tab>
</Tabs>
### Multiple Conditions (AND Logic)
<Tabs>
<Tab title="TypeScript">
```typescript
// All conditions must match
const reactTutorials = await client.documents.list({
filters: {
AND: [
{ key: "category", value: "tutorial", negate: false },
{ key: "framework", value: "react", negate: false },
{ key: "difficulty", value: "beginner", negate: false }
]
}
});
```
</Tab>
<Tab title="Python">
```python
# All conditions must match
react_tutorials = client.documents.list(
filters={
"AND": [
{"key": "category", "value": "tutorial", "negate": False},
{"key": "framework", "value": "react", "negate": False},
{"key": "difficulty", "value": "beginner", "negate": False}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"tutorial\",\"negate\":false},{\"key\":\"framework\",\"value\":\"react\",\"negate\":false}]}"
}'
```
</Tab>
</Tabs>
### Alternative Conditions (OR Logic)
<Tabs>
<Tab title="TypeScript">
```typescript
// Any condition can match
const frontendMemories = await client.documents.list({
filters: {
OR: [
{ key: "framework", value: "react", negate: false },
{ key: "framework", value: "vue", negate: false },
{ key: "framework", value: "angular", negate: false }
]
}
});
```
</Tab>
<Tab title="Python">
```python
# Any condition can match
frontend_memories = client.documents.list(
filters={
"OR": [
{"key": "framework", "value": "react", "negate": False},
{"key": "framework", "value": "vue", "negate": False},
{"key": "framework", "value": "angular", "negate": False}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"OR\":[{\"key\":\"framework\",\"value\":\"react\",\"negate\":false},{\"key\":\"framework\",\"value\":\"vue\",\"negate\":false}]}"
}'
```
</Tab>
</Tabs>
### Complex Nested Logic
<Tabs>
<Tab title="TypeScript">
```typescript
// Complex logic: programming AND (react OR advanced difficulty)
const advancedContent = await client.documents.list({
filters: {
AND: [
{ key: "category", value: "programming", negate: false },
{
OR: [
{ key: "framework", value: "react", negate: false },
{ key: "difficulty", value: "advanced", negate: false }
]
}
]
}
});
```
</Tab>
<Tab title="Python">
```python
# Complex logic: programming AND (react OR advanced difficulty)
advanced_content = client.documents.list(
filters={
"AND": [
{"key": "category", "value": "programming", "negate": False},
{
"OR": [
{"key": "framework", "value": "react", "negate": False},
{"key": "difficulty", "value": "advanced", "negate": False}
]
}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"programming\",\"negate\":false},{\"OR\":[{\"key\":\"framework\",\"value\":\"react\",\"negate\":false},{\"key\":\"difficulty\",\"value\":\"advanced\",\"negate\":false}]}]}"
}'
```
</Tab>
</Tabs>
## Array Contains Filtering
Filter memories that contain specific values in array fields like participants, tags, or team members.
### Basic Array Contains
<Tabs>
<Tab title="TypeScript">
```typescript
// Find memories where john.doe participated
const meetingMemories = await client.documents.list({
filters: {
AND: [
{
key: "participants",
value: "john.doe",
filterType: "array_contains",
negate: false
}
]
}
});
```
</Tab>
<Tab title="Python">
```python
# Find memories where john.doe participated
meeting_memories = client.documents.list(
filters={
"AND": [
{
"key": "participants",
"value": "john.doe",
"filterType": "array_contains",
"negate": False
}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"AND\":[{\"key\":\"participants\",\"value\":\"john.doe\",\"filterType\":\"array_contains\",\"negate\":false}]}"
}'
```
</Tab>
</Tabs>
### Array Contains with Exclusion
<Tabs>
<Tab title="TypeScript">
```typescript
// Find memories that don't include a specific team member
const filteredMemories = await client.documents.list({
filters: {
AND: [
{
key: "reviewers",
value: "external.consultant",
filterType: "array_contains",
negate: true // Exclude memories with external consultants
},
{
key: "project_tags",
value: "internal-only",
filterType: "array_contains",
negate: false
}
]
}
});
```
</Tab>
<Tab title="Python">
```python
# Find memories that don't include a specific team member
filtered_memories = client.documents.list(
filters={
"AND": [
{
"key": "reviewers",
"value": "external.consultant",
"filterType": "array_contains",
"negate": True # Exclude memories with external consultants
},
{
"key": "project_tags",
"value": "internal-only",
"filterType": "array_contains",
"negate": False
}
]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"AND\":[{\"key\":\"reviewers\",\"value\":\"external.consultant\",\"filterType\":\"array_contains\",\"negate\":true},{\"key\":\"project_tags\",\"value\":\"internal-only\",\"filterType\":\"array_contains\",\"negate\":false}]}"
}'
```
</Tab>
</Tabs>
### Multiple Array Contains (OR Logic)
<Tabs>
<Tab title="TypeScript">
```typescript
// Find memories involving any of several team leads
const leadershipMemories = await client.documents.list({
filters: {
OR: [
{
key: "attendees",
value: "engineering.lead",
filterType: "array_contains"
},
{
key: "attendees",
value: "product.lead",
filterType: "array_contains"
},
{
key: "attendees",
value: "design.lead",
filterType: "array_contains"
}
]
},
sort: "updatedAt",
order: "desc"
});
```
</Tab>
<Tab title="Python">
```python
# Find memories involving any of several team leads
leadership_memories = client.documents.list(
filters={
"OR": [
{
"key": "attendees",
"value": "engineering.lead",
"filterType": "array_contains"
},
{
"key": "attendees",
"value": "product.lead",
"filterType": "array_contains"
},
{
"key": "attendees",
"value": "design.lead",
"filterType": "array_contains"
}
]
},
sort="updatedAt",
order="desc"
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": "{\"OR\":[{\"key\":\"attendees\",\"value\":\"engineering.lead\",\"filterType\":\"array_contains\"},{\"key\":\"attendees\",\"value\":\"product.lead\",\"filterType\":\"array_contains\"},{\"key\":\"attendees\",\"value\":\"design.lead\",\"filterType\":\"array_contains\"}]}",
"sort": "updatedAt",
"order": "desc"
}'
```
</Tab>
</Tabs>
## Combined Container Tags + Metadata Filtering
<Tabs>
<Tab title="TypeScript">
```typescript
const filteredMemories = await client.documents.list({
containerTags: ["user_123"],
filters: {
AND: [
{ key: "category", value: "tutorial", negate: false },
{ key: "framework", value: "react", negate: false }
]
},
sort: "updatedAt",
order: "desc",
limit: 50
});
```
</Tab>
<Tab title="Python">
```python
filtered_memories = client.documents.list(
container_tags=["user_123"],
filters={
"AND": [
{"key": "category", "value": "tutorial", "negate": False},
{"key": "framework", "value": "react", "negate": False}
]
},
sort="updatedAt",
order="desc",
limit=50
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"containerTags": ["user_123"],
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"tutorial\",\"negate\":false},{\"key\":\"framework\",\"value\":\"react\",\"negate\":false}]}",
"sort": "updatedAt",
"order": "desc",
"limit": 50
}'
```
</Tab>
</Tabs>
<Warning>
**Common Mistakes:**
- Using bare condition objects: `{"key": "category", "value": "programming"}` without wrapping in `AND` or `OR`
- Missing negate property: always include `"negate": false` or `"negate": true`
- For cURL requests: forgetting to properly escape the JSON string
</Warning>
<Note>
**Container Tags vs Metadata Filtering:**
- Container tags: Exact array matching for organizational grouping
- Metadata filters: SQL-like queries on custom metadata fields with complex logic
- Both can be combined for powerful filtering capabilities
</Note>

View file

@ -1,119 +0,0 @@
---
title: "Status Monitoring"
description: "Monitor memory processing status and completion rates"
---
Monitor memory processing status and track completion rates using the list endpoint.
## Status Overview
<Tabs>
<Tab title="TypeScript">
```typescript
const response = await client.documents.list({ limit: 100 });
const statusCounts = response.memories.reduce((acc: any, memory) => {
acc[memory.status] = (acc[memory.status] || 0) + 1;
return acc;
}, {});
console.log('Status breakdown:', statusCounts);
```
</Tab>
<Tab title="Python">
```python
response = client.documents.list(limit=100)
status_counts = {}
for memory in response.memories:
status = memory.status
status_counts[status] = status_counts.get(status, 0) + 1
print("Status breakdown:", status_counts)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 100}' | \
jq '.memories | group_by(.status) | map({status: .[0].status, count: length})'
```
</Tab>
</Tabs>
## Filter Processing Memories
<Tabs>
<Tab title="TypeScript">
```typescript
const response = await client.documents.list({ limit: 100 });
const processing = response.memories.filter(m =>
['queued', 'extracting', 'chunking', 'embedding', 'indexing'].includes(m.status)
);
console.log(`${processing.length} memories currently processing`);
```
</Tab>
<Tab title="Python">
```python
response = client.documents.list(limit=100)
processing_statuses = ['queued', 'extracting', 'chunking', 'embedding', 'indexing']
processing = [m for m in response.memories if m.status in processing_statuses]
print(f"{len(processing)} memories currently processing")
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 100}' | \
jq '.memories[] | select(.status | IN("queued", "extracting", "chunking", "embedding", "indexing"))'
```
</Tab>
</Tabs>
## Failed Memories
<Tabs>
<Tab title="TypeScript">
```typescript
const response = await client.documents.list({ limit: 100 });
const failedMemories = response.memories.filter(m => m.status === 'failed');
failedMemories.forEach(memory => {
console.log(`Failed: ${memory.id} - ${memory.title || 'Untitled'}`);
});
```
</Tab>
<Tab title="Python">
```python
response = client.documents.list(limit=100)
failed_memories = [m for m in response.memories if m.status == 'failed']
for memory in failed_memories:
title = memory.title or 'Untitled'
print(f"Failed: {memory.id} - {title}")
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 100}' | \
jq '.memories[] | select(.status == "failed") | {id, title, status}'
```
</Tab>
</Tabs>
<Note>
For real-time monitoring of individual memories, use the [Track Processing Status](/memory-api/track-progress) guide.
</Note>

View file

@ -1,110 +0,0 @@
---
title: "Pagination"
description: "Handle large memory collections with pagination"
---
Handle large memory collections efficiently using pagination to process data in manageable chunks.
## Basic Pagination
<Tabs>
<Tab title="TypeScript">
```typescript
// Get first page
const page1 = await client.documents.list({
limit: 20,
page: 1
});
// Get next page
const page2 = await client.documents.list({
limit: 20,
page: 2
});
console.log(`Page 1: ${page1.memories.length} memories`);
console.log(`Page 2: ${page2.memories.length} memories`);
```
</Tab>
<Tab title="Python">
```python
# Get first page
page1 = client.documents.list(limit=20, page=1)
# Get next page
page2 = client.documents.list(limit=20, page=2)
print(f"Page 1: {len(page1.memories)} memories")
print(f"Page 2: {len(page2.memories)} memories")
```
</Tab>
<Tab title="cURL">
```bash
# Get first page
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 20, "page": 1}'
# Get next page
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 20, "page": 2}'
```
</Tab>
</Tabs>
## Loop Through Pages
<Tabs>
<Tab title="TypeScript">
```typescript
let currentPage = 1;
let hasMore = true;
while (hasMore) {
const response = await client.documents.list({
page: currentPage,
limit: 50
});
console.log(`Page ${currentPage}: ${response.memories.length} memories`);
hasMore = currentPage < response.pagination.totalPages;
currentPage++;
}
```
</Tab>
<Tab title="Python">
```python
current_page = 1
has_more = True
while has_more:
response = client.documents.list(page=current_page, limit=50)
print(f"Page {current_page}: {len(response.memories)} memories")
has_more = current_page < response.pagination.total_pages
current_page += 1
```
</Tab>
<Tab title="cURL">
```bash
# Manual pagination with bash loop
for page in {1..5}; do
echo "=== Page $page ==="
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"page\": $page, \"limit\": 20}" | \
jq '.memories | length'
done
```
</Tab>
</Tabs>
<Info>
Use larger `limit` values (50-100) for pagination to reduce the number of API calls needed.
</Info>

View file

@ -1,153 +0,0 @@
---
title: "List Memories"
description: "Retrieve paginated memories with filtering and sorting options"
sidebarTitle: "Overview"
---
Retrieve paginated memories with filtering and sorting options from your Supermemory account.
## Quick Start
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
const memories = await client.documents.list({ limit: 10 });
console.log(memories);
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
memories = client.documents.list(limit=10)
print(f"Found {len(memories.memories)} memories")
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 10}'
```
</Tab>
</Tabs>
## Response Schema
The endpoint returns a structured response containing your memories and pagination information:
```json
{
"memories": [
{
"id": "abc123",
"connectionId": null,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"customId": "ml-basics-001",
"title": "Introduction to Machine Learning",
"summary": "This document introduces machine learning as a subset of artificial intelligence...",
"status": "done",
"type": "text",
"metadata": {
"category": "education",
"priority": "high",
"source": "research-notes"
},
"containerTags": ["user_123", "ai-research"]
}
],
"pagination": {
"currentPage": 1,
"totalPages": 3,
"totalItems": 25,
"limit": 10
}
}
```
### Memory Object Fields
<Accordion title="Core Fields" defaultOpen>
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique identifier for the memory |
| `status` | ProcessingStatus | Current processing status (`queued`, `extracting`, `chunking`, `embedding`, `indexing`, `done`, `failed`) |
| `type` | MemoryType | Content type (`text`, `pdf`, `webpage`, `video`, `image`, etc.) |
| `title` | string \| null | Auto-generated or custom title |
| `summary` | string \| null | AI-generated summary of content |
| `createdAt` | string | ISO 8601 creation timestamp |
| `updatedAt` | string | ISO 8601 last update timestamp |
</Accordion>
<Accordion title="Optional Fields">
| Field | Type | Description |
|-------|------|-------------|
| `customId` | string \| null | Your custom identifier for the memory |
| `connectionId` | string \| null | ID of connector that created this memory |
| `metadata` | object \| null | Custom key-value metadata you provided |
| `containerTags` | string[] | Tags for organizing and filtering memories |
</Accordion>
## Key Parameters
All parameters are optional and sent in the request body since this endpoint uses `POST`:
<ParamField path="limit" type="number/string" default="50">
**Number of items per page.** Controls how many memories are returned in a single request. Maximum recommended: 200 for optimal performance.
</ParamField>
<ParamField path="page" type="number/string" default="1">
**Page number to fetch (1-indexed).** Use with `limit` to paginate through large result sets.
</ParamField>
<ParamField path="containerTags" type="string[]">
**Filter by tags.** Memories must match ALL provided tags. Use for filtering by user ID, project, or custom organization tags.
</ParamField>
<ParamField path="sort" type="string" default="createdAt">
**Sort field.** Options: `"createdAt"` (when memory was added) or `"updatedAt"` (when memory was last modified).
</ParamField>
<ParamField path="order" type="string" default="desc">
**Sort direction.** Use `"desc"` for newest first, `"asc"` for oldest first.
</ParamField>
<ParamField path="filters" type="string">
**Advanced filtering.** Filter based on metadata with advanced SQL logic.
</ParamField>
## Examples
<CardGroup cols={2}>
<Card title="Basic Listing" icon="list" href="/list-memories/examples/basic">
Simple memory retrieval with default settings
</Card>
<Card title="Filtering" icon="filter" href="/list-memories/examples/filtering">
Filter by tags, status, and other criteria
</Card>
<Card title="Pagination" icon="arrow-right" href="/list-memories/examples/pagination">
Handle large datasets with pagination
</Card>
<Card title="Status Monitoring" icon="chart-line" href="/list-memories/examples/monitoring">
Track processing status across memories
</Card>
</CardGroup>
<Note>
The `/v3/documents/list` endpoint uses **POST** method, not GET. This allows for complex filtering parameters in the request body.
</Note>

View file

@ -6,7 +6,7 @@ icon: "database"
---
<Info>
These v4 endpoints operate on extracted memories (not raw documents). SDK support coming soon — use fetch or cURL for now.
These v4 endpoints operate on extracted memories (not raw documents). The SDK already covers the v4 read surface — `client.search.memories` and `client.profile` — while the memory create/update/forget endpoints on this page are called with fetch or cURL for now.
For document management (list, get, update, delete), see [Document Operations](/document-operations).
For ingesting raw content (text, files, URLs) through the processing pipeline, see [Add Context](/add-memories).

View file

@ -15,7 +15,7 @@ inferred memories awaiting review, then **approve**, **decline**, or **undo** a
decision on each one.
<Info>
These endpoints are scoped to a single [container tag](/concepts/container-tags)
These endpoints are scoped to a single [container tag](/concepts/permissioning)
(space), under `/v3/container-tags/{containerTag}`.
</Info>

View file

@ -38,7 +38,7 @@ for memory in data["memories"]:
if memory.get("content"):
supermemory.memories.add(
content=memory["content"],
container_tags=["imported_from_mem0"]
container_tag="imported_from_mem0"
)
print(f"✅ {memory['content'][:50]}...")
@ -142,7 +142,7 @@ print("Migration complete!")
try:
result = client.add(
content=content,
container_tags=["imported_from_mem0"],
container_tag="imported_from_mem0",
metadata={
"source": "mem0",
"created_at": memory.get("created_at"),
@ -182,7 +182,7 @@ from supermemory import Supermemory
client = Supermemory(api_key="...")
client.add(
content="User prefers dark mode",
container_tags=["user_alice"]
container_tag="user_alice"
)
```
@ -200,9 +200,9 @@ results = client.search(
```
```python Supermemory
results = client.documents.search(
query="user preferences",
container_tags=["user_alice"]
results = client.search.memories(
q="user preferences",
container_tag="user_alice"
)
```
@ -247,6 +247,6 @@ For enterprise migrations, [contact us](mailto:support@supermemory.ai) for assis
## Next Steps
1. [Explore](/how-it-works) how Supermemory works
1. [Explore](/concepts/how-it-works) how Supermemory works
2. Read the [quickstart](/quickstart) and add and retrieve your first memories
3. [Connect](/connectors/overview) to Google Drive, Notion, and OneDrive with automatic syncing

View file

@ -9,9 +9,9 @@ sidebarTitle: "From Zep"
| Zep AI | Supermemory |
|--------|-------------|
| Sessions & Messages | Documents & Container Tags |
| `session.create()` | Use `containerTags` parameter |
| `memory.add(session_id, ...)` | `add({containerTag: [...]})` |
| `memory.search(session_id, {text: ...})` | `search.execute({q: ..., containerTags: [...]})` |
| `session.create()` | Use `containerTag` parameter |
| `memory.add(session_id, ...)` | `add({containerTag: "..."})` |
| `memory.search(session_id, {text: ...})` | `search.memories({q: ..., containerTag: "..."})` |
## Installation
@ -56,7 +56,7 @@ session = client.session.create(
```python Supermemory
# No explicit session creation - use containerTag
containerTag = ["user_123"]
containerTag = "user_123"
```
</CodeGroup>
@ -75,7 +75,7 @@ client.memory.add(
```python Supermemory
client.add({
"content": "User prefers dark mode",
"containerTag": ["user_123"]
"containerTag": "user_123"
})
```
@ -93,9 +93,9 @@ results = client.memory.search(
```
```python Supermemory
results = client.search.execute({
results = client.search.memories({
"q": "preferences",
"containerTag": ["user_123"],
"containerTag": "user_123",
"limit": 5
})
```
@ -112,7 +112,7 @@ memories = client.memory.get(session_id="user_123")
```python Supermemory
documents = client.documents.list({
"containerTag": ["user_123"],
"containerTags": ["user_123"],
"limit": 100
})
```
@ -122,8 +122,8 @@ documents = client.documents.list({
## Migration Steps
1. **Replace client initialization** - Use Supermemory client instead of Zep
2. **Map sessions to container tags** - Replace `session_id="user_123"` with `containerTag: ["user_123"]`
3. **Update method calls** - Use `add()` and `search.execute()` instead of `memory.add()` and `memory.search()`
2. **Map sessions to container tags** - Replace `session_id="user_123"` with `containerTag: "user_123"`
3. **Update method calls** - Use `add()` and `search.memories()` instead of `memory.add()` and `memory.search()`
4. **Change search parameter** - Use `q` instead of `text`
5. **Handle async processing** - Documents process asynchronously (status: `queued` → `done`)
@ -152,7 +152,7 @@ results = client.memory.search("user_123", {
from supermemory import Supermemory
client = Supermemory(api_key="...")
containerTag = ["user_123"]
containerTag = "user_123"
client.add({
"content": "I love Python",
@ -160,7 +160,7 @@ client.add({
"metadata": {"role": "user"}
})
results = client.search.execute({
results = client.search.memories({
"q": "programming",
"containerTag": containerTag,
"limit": 3
@ -203,10 +203,11 @@ for (const sessionId of sessionIds) {
if (mem.content) {
await supermemory.add({
content: mem.content,
containerTag: [`session_${sessionId}`, `user_${memory.user_id || "unknown"}`],
containerTag: `user_${memory.user_id || "unknown"}`,
metadata: {
role: mem.role,
type: "message",
session_id: sessionId,
original_uuid: mem.uuid,
...mem.metadata
}
@ -238,10 +239,11 @@ for session_id in session_ids:
if mem.content:
supermemory.add({
"content": mem.content,
"containerTag": [f"session_{session_id}", f"user_{memory.user_id or 'unknown'}"],
"containerTag": f"user_{memory.user_id or 'unknown'}",
"metadata": {
"role": mem.role,
"type": "message",
"session_id": session_id,
"original_uuid": mem.uuid,
**(mem.metadata or {})
}
@ -315,10 +317,9 @@ async function migrateFromZep(
// Import to Supermemory
let totalMemories = 0;
for (const [sessionId, data] of Object.entries(exportedData) as any) {
const containerTag = ["imported_from_zep", `session_${sessionId}`];
if (data.session.user_id) {
containerTag.push(`user_${data.session.user_id}`);
}
const containerTag = data.session.user_id
? `user_${data.session.user_id}`
: `session_${sessionId}`;
for (const memory of data.memories) {
totalMemories++;
@ -335,6 +336,7 @@ async function migrateFromZep(
source: "zep_migration",
role: memory.role,
type: "message",
session_id: sessionId,
original_uuid: memory.uuid,
...memory.metadata,
},
@ -368,5 +370,5 @@ migrateFromZep(
## Resources
- [Supermemory SDKs](/integrations/supermemory-sdk)
- [API Reference](/memory-api/overview)
- [API Reference](/add-memories)
- [Search Documentation](/search)

View file

@ -34,7 +34,7 @@ npm install @supermemory/tools@^2.0.0
// v1.4.x
import { withSupermemory } from '@supermemory/tools/ai-sdk';
const model = withSupermemory(openai('gpt-4'), 'user-123', {
const model = withSupermemory(openai('gpt-4o'), 'user-123', {
conversationId: 'conv-456',
mode: 'full',
});
@ -44,7 +44,7 @@ const model = withSupermemory(openai('gpt-4'), 'user-123', {
// v2.0.0
import { withSupermemory } from '@supermemory/tools/ai-sdk';
const model = withSupermemory(openai('gpt-4'), {
const model = withSupermemory(openai('gpt-4o'), {
containerTag: 'user-123',
customId: 'conv-456',
mode: 'full',
@ -139,7 +139,7 @@ If you were relying on `verbose: false` implicitly while passing `verbose: true`
Across all four integrations, `addMemory` now defaults to `"always"`. If your v1.4.x code relied on the old default of `"never"`, set it explicitly:
```typescript
const model = withSupermemory(openai('gpt-4'), {
const model = withSupermemory(openai('gpt-4o'), {
containerTag: 'user-123',
customId: 'conv-456',
addMemory: 'never', // preserve v1.4.x behavior

View file

@ -1,92 +0,0 @@
---
title: "n8n Integration"
description: "Automate knowledge management with Supermemory in n8n workflows"
sidebarTitle: "n8n"
---
Connect Supermemory to your n8n workflows to build intelligent automation workflows and agents that leverage your full knowledge base.
## Quick Start
### Prerequisites
- n8n instance (self-hosted or cloud)
- Supermemory API key ([get one here](https://console.supermemory.ai/settings))
- Basic understanding of n8n workflows
### Setting Up the HTTP Request Node
The Supermemory integration in n8n uses the HTTP Request node to interact with the Supermemory API. Here's how to configure it:
1. Add an **HTTP Request** node to your workflow (Core > HTTP Request)
![](/images/core-http-req.png)
2. Set the **Method** to `POST`
3. Set the **URL** to the appropriate Supermemory API endpoint:
- Add memory: `https://api.supermemory.ai/v3/documents`
- Search memories: `https://api.supermemory.ai/v4/search`
4. For authentication, select **Generic Credential Type** and then **Bearer Auth**
5. Click on **Create New Credential** and paste the Supermemory API Key in the Bearer Token field.
![](/images/bearer-auth-add-n8n.png)
6. Check **Send Body** and select **JSON** as the Body Content Type. The fields depend on what API endpoint you're sending the request to. You can find detailed step-by-step examples below.
## Step-by-Step Tutorial
In this tutorial, we'll create a workflow that automatically adds every email from Gmail to your Supermemory knowledge base. We'll use the HTTP Request node to send email data to Supermemory's API, creating a searchable archive of all your communications.
### Adding Gmail Emails to Supermemory
Follow these steps to build a workflow that captures and stores your Gmail messages:
#### Step 1: Set Up Gmail Trigger
![](/images/gmail-trigger.png)
1. **Add a Gmail Trigger node** to your workflow
2. Configure your Gmail credentials (OAuth2 recommended)
3. Set the trigger to **Message Received**
4. Optional: Add labels or filters to process specific emails only
#### Step 2: Configure HTTP Request Node
1. **Add an HTTP Request node** after the Gmail Trigger
2. **Method**: `POST`
3. **URL**: `https://api.supermemory.ai/v3/documents`
4. Select your auth credentials you created with the Supermemory API Key.
#### Step 3: Format Email Data for Supermemory
In the HTTP Request node's **Body**, select **JSON** and **Using Fields Below**
And create 2 fields:
1. name: `content`, value: `{{ $json.snippet }}`
2. name: `containerTag`, value: gmail
![](/images/gmail-content.png)
#### Step 4: Handle Attachments (Optional)
If you want to process attachments:
1. **Add a Loop node** after the Gmail Trigger
2. Loop through `{{$json.attachments}}`
3. **Add a Gmail node** to download each attachment
4. **Add another HTTP Request node** to store attachment metadata
#### Step 5: Add Error Handling
1. **Add an Error Trigger node** connected to your workflow
2. Configure it to catch errors from the HTTP Request node
3. **Add a notification node** (Email, Slack, etc.) to alert you of failures
4. Optional: Add a **Wait node** with retry logic
#### Step 6: Test Your Workflow
1. **Activate the workflow** in test mode
2. Send a test email to your Gmail account
3. Check the execution to ensure the email was captured
4. Verify in Supermemory that the email appears in search results
Refer to the API Reference tab to learn more about other supermemory API endpoints.

View file

@ -165,7 +165,7 @@ const results = await client.search.memories({
- **Array contains:** `{ filterType: "array_contains", key: "tags", value: "important" }`
- **Negate:** `{ key: "status", value: "draft", negate: true }`
See [Organizing & Filtering](/concepts/filtering) for full syntax.
See [Organizing & Filtering](/concepts/hybrid-search) for full syntax.
</Accordion>
---
@ -244,4 +244,4 @@ async function getContext(userId: string, message: string) {
- [Ingesting Content](/add-memories) — Add content to search
- [User Profiles](/user-profiles) — Get user context with search
- [Organizing & Filtering](/concepts/filtering) — Container tags and metadata
- [Organizing & Filtering](/concepts/hybrid-search) — Container tags and metadata

View file

@ -1,588 +0,0 @@
---
title: "Documents Search (/v3/search)"
description: "Full-featured search with extensive control over ranking, filtering, and results"
---
Documents search (`POST /v3/search`) provides maximum control over search behavior with extensive parameters for fine-tuning results.
## Basic Implementation
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
const results = await client.search.documents({
q: "machine learning neural networks",
limit: 5
});
console.log(`Found ${results.total} documents in ${results.timing}ms`);
// Sample output structure
results.results.forEach((doc, i) => {
console.log(`${i + 1}. ${doc.title} (Score: ${doc.score})`);
console.log(` ${doc.chunks.length} chunks found`);
});
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
results = client.search.documents(
q="machine learning neural networks",
limit=5
)
print(f"Found {results.total} documents in {results.timing}ms")
# Sample output structure
for i, doc in enumerate(results.results):
print(f"{i + 1}. {doc.title} (Score: {doc.score})")
print(f" {len(doc.chunks)} chunks found")
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning neural networks",
"limit": 5
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"documentId": "doc_ml_guide_2024",
"title": "Machine Learning with Neural Networks: A Comprehensive Guide",
"score": 0.89,
"chunks": [
{
"content": "Neural networks are computational models inspired by biological neural networks. They consist of interconnected nodes (neurons) that process information through weighted connections...",
"score": 0.92,
"isRelevant": true
},
{
"content": "Deep learning, a subset of machine learning, uses neural networks with multiple hidden layers to learn complex patterns in data...",
"score": 0.87,
"isRelevant": true
}
],
"createdAt": "2024-01-15T10:30:00Z",
"metadata": {
"category": "ai",
"difficulty": "intermediate"
}
}
],
"total": 12,
"timing": 156
}
```
## Container Tags Filtering
Container tags are the primary way to isolate search results by user, project, or organization.
**Key behaviors:**
- **Array-based**: Unlike `/v4/search`, this endpoint accepts multiple container tags as an array
- **Exact array matching**: Documents must have the EXACT same container tags array to match
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "quarterly reports",
containerTags: ["user_123"],
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="quarterly reports",
container_tags=["user_123"],
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "quarterly reports",
"containerTags": ["user_123"],
"limit": 10
}'
```
</Tab>
</Tabs>
## Metadata Filtering
Metadata filtering allows complex conditions on structured data attached to your documents. This uses SQL-like query construction in the backend, requiring explicit AND/OR structures.
**Filter structure rules:**
- **Must wrap conditions** in AND or OR arrays, even for single conditions
- **Supports string matching** (exact), numeric operators, and array contains
- **Negate any condition** with `negate: true`
- **Combines with container tags** - both filters are applied
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "machine learning",
filters: {
AND: [
{
key: "category",
value: "technology",
negate: false
},
{
filterType: "numeric",
key: "readingTime",
value: "5",
negate: false,
numericOperator: "<="
}
]
},
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="machine learning",
filters={
"AND": [
{
"key": "category",
"value": "technology",
"negate": False
},
{
"filterType": "numeric",
"key": "readingTime",
"value": "5",
"negate": False,
"numericOperator": "<="
}
]
},
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning",
"filters": {
"AND": [
{
"key": "category",
"value": "technology",
"negate": false
},
{
"filterType": "numeric",
"key": "readingTime",
"value": "5",
"negate": false,
"numericOperator": "<="
}
]
},
"limit": 10
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"documentId": "doc_tech_trends_2024",
"title": "Technology Trends in Machine Learning",
"score": 0.91,
"chunks": [
{
"content": "Machine learning continues to evolve with new architectures and optimization techniques. Reading time for this comprehensive overview is approximately 8 minutes...",
"score": 0.88,
"isRelevant": true
}
],
"metadata": {
"category": "technology",
"readingTime": 8,
"difficulty": "intermediate",
"published": true
}
}
],
"total": 6,
"timing": 189
}
```
## Array Contains Filtering
When your metadata includes arrays (like participant lists, tags, or categories), use `array_contains` to check if the array includes a specific value.
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "meeting discussion",
filters: {
AND: [
{
key: "participants",
value: "john.doe",
filterType: "array_contains"
}
]
},
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="meeting discussion",
filters={
"AND": [
{
"key": "participants",
"value": "john.doe",
"filterType": "array_contains"
}
]
},
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "meeting discussion",
"filters": {
"AND": [
{
"key": "participants",
"value": "john.doe",
"filterType": "array_contains"
}
]
},
"limit": 5
}'
```
</Tab>
</Tabs>
## Threshold Control
Control result quality with sensitivity thresholds:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "artificial intelligence",
documentThreshold: 0.7, // Higher = fewer, more relevant documents
chunkThreshold: 0.8, // Higher = fewer, more relevant chunks
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="artificial intelligence",
document_threshold=0.7, # Higher = fewer, more relevant documents
chunk_threshold=0.8, # Higher = fewer, more relevant chunks
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "artificial intelligence",
"documentThreshold": 0.7,
"chunkThreshold": 0.8,
"limit": 10
}'
```
</Tab>
</Tabs>
## Query Rewriting
Improve search accuracy with automatic query rewriting:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "What is the capital of France?",
rewriteQuery: true, // +400ms latency but better results
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="What is the capital of France?",
rewrite_query=True, # +400ms latency but better results
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "What is the capital of France?",
"rewriteQuery": true,
"limit": 5
}'
```
</Tab>
</Tabs>
<Note>
Query rewriting generates multiple query variations and searches through all of them, then merges results. No additional cost but adds ~400ms latency.
</Note>
## Reranking
Improve result quality with secondary ranking:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "machine learning applications",
rerank: true, // Apply secondary ranking algorithm
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="machine learning applications",
rerank=True, # Apply secondary ranking algorithm
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning applications",
"rerank": true,
"limit": 10
}'
```
</Tab>
</Tabs>
## Document-Specific Search
Search within a specific large document:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "neural networks",
docId: "doc_123", // Search only within this document
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="neural networks",
doc_id="doc_123", # Search only within this document
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "neural networks",
"docId": "doc_123",
"limit": 10
}'
```
</Tab>
</Tabs>
## Full Context Options
Include complete document content and summaries:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "research findings",
includeFullDocs: true, // Include complete document content
includeSummary: true, // Include document summaries
onlyMatchingChunks: false, // Include all chunks, not just matching ones
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="research findings",
include_full_docs=True, # Include complete document content
include_summary=True, # Include document summaries
only_matching_chunks=False, # Include all chunks, not just matching ones
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "research findings",
"includeFullDocs": true,
"includeSummary": true,
"onlyMatchingChunks": false,
"limit": 5
}'
```
</Tab>
</Tabs>
## Complete Advanced Example
Combining all features for maximum control:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "machine learning performance metrics",
containerTags: ["research_project"],
filters: {
AND: [
{ key: "category", value: "ai", negate: false },
{ key: "status", value: "published", negate: false }
]
},
documentThreshold: 0.6,
chunkThreshold: 0.7,
rewriteQuery: true,
rerank: true,
includeFullDocs: false,
includeSummary: true,
onlyMatchingChunks: true,
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="machine learning performance metrics",
container_tags=["research_project"],
filters={
"AND": [
{"key": "category", "value": "ai", "negate": False},
{"key": "status", "value": "published", "negate": False}
]
},
document_threshold=0.6,
chunk_threshold=0.7,
rewrite_query=True,
rerank=True,
include_full_docs=False,
include_summary=True,
only_matching_chunks=True,
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning performance metrics",
"containerTags": ["research_project"],
"filters": {
"AND": [
{"key": "category", "value": "ai", "negate": false},
{"key": "status", "value": "published", "negate": false}
]
},
"documentThreshold": 0.6,
"chunkThreshold": 0.7,
"rewriteQuery": true,
"rerank": true,
"includeFullDocs": false,
"includeSummary": true,
"onlyMatchingChunks": true,
"limit": 10
}'
```
</Tab>
</Tabs>

View file

@ -1,695 +0,0 @@
---
title: "Memories Search (/v4/search)"
description: "Minimal-latency search optimized for chatbots and conversational AI"
---
Memories search (`POST /v4/search`) provides minimal-latency search optimized for real-time interactions. This endpoint prioritizes speed over extensive control, making it perfect for chatbots, Q&A systems, and any application where users expect immediate responses.
## Basic Search
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
const results = await client.search.memories({
q: "machine learning applications",
limit: 5
});
console.log(results)
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
results = client.search.memories(
q="machine learning applications",
limit=5
)
console.log(results)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning applications",
"limit": 5
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"id": "mem_ml_apps_2024",
"memory": "Machine learning applications span numerous industries including healthcare (diagnostic imaging, drug discovery), finance (fraud detection, algorithmic trading), autonomous vehicles (computer vision, path planning), and natural language processing (chatbots, translation services).",
"similarity": 0.92,
"title": "Machine Learning Industry Applications",
"type": "text",
"metadata": {
"topic": "machine-learning",
"industry": "technology",
"created": "2024-01-10"
}
},
{
"id": "mem_ml_healthcare",
"memory": "In healthcare, machine learning enables early disease detection through medical imaging analysis, personalized treatment recommendations, and drug discovery acceleration by predicting molecular behavior.",
"similarity": 0.89,
"title": "ML in Healthcare",
"type": "text"
}
],
"total": 8,
"timing": 87
}
```
## Container Tag Filtering
Filter by user, project, or organization:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "project updates",
containerTag: "user_123", // Note: singular, not plural
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="project updates",
container_tag="user_123", # Note: singular, not plural
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "project updates",
"containerTag": "user_123",
"limit": 10
}'
```
</Tab>
</Tabs>
## Threshold Control
Control result quality with similarity threshold:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "artificial intelligence research",
threshold: 0.7, // Higher = fewer, more similar results
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="artificial intelligence research",
threshold=0.7, # Higher = fewer, more similar results
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "artificial intelligence research",
"threshold": 0.7,
"limit": 10
}'
```
</Tab>
</Tabs>
## Reranking
Improve result quality with secondary ranking:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "quantum computing breakthrough",
rerank: true, // Better relevance, slight latency increase
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="quantum computing breakthrough",
rerank=True, # Better relevance, slight latency increase
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "quantum computing breakthrough",
"rerank": true,
"limit": 5
}'
```
</Tab>
</Tabs>
## Query Rewriting
Improve search accuracy with automatic query expansion:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "How do neural networks learn?",
rewriteQuery: true, // +400ms latency but better results
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="How do neural networks learn?",
rewrite_query=True, # +400ms latency but better results
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "How do neural networks learn?",
"rewriteQuery": true,
"limit": 5
}'
```
</Tab>
</Tabs>
## Include Related Content
Include documents, related memories, and summaries:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "machine learning trends",
include: {
documents: true, // Include source documents
relatedMemories: true, // Include related memory entries
summaries: true // Include memory summaries
},
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="machine learning trends",
include={
"documents": True, # Include source documents
"relatedMemories": True, # Include related memory entries
"summaries": True # Include memory summaries
},
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning trends",
"include": {
"documents": true,
"relatedMemories": true,
"summaries": true
},
"limit": 5
}'
```
</Tab>
</Tabs>
## Metadata Filtering
Simple metadata filtering for Memories search:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "research findings",
filters: {
AND: [
{ key: "category", value: "science", negate: false },
{ key: "status", value: "published", negate: false }
]
},
limit: 10
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="research findings",
filters={
"AND": [
{"key": "category", "value": "science", "negate": False},
{"key": "status", "value": "published", "negate": False}
]
},
limit=10
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "research findings",
"filters": {
"AND": [
{"key": "category", "value": "science", "negate": false},
{"key": "status", "value": "published", "negate": false}
]
},
"limit": 10
}'
```
</Tab>
</Tabs>
## Chatbot Example
Optimal configuration for conversational AI:
<Tabs>
<Tab title="TypeScript">
```typescript
// Optimized for chatbot responses
const results = await client.search.memories({
q: userMessage,
containerTag: userId,
threshold: 0.6, // Balanced relevance
rerank: false, // Skip for speed
rewriteQuery: false, // Skip for speed
limit: 3 // Few, relevant results
});
// Quick response for chat
const context = results.results
.map(r => r.memory)
.join('\n\n');
```
</Tab>
<Tab title="Python">
```python
# Optimized for chatbot responses
results = client.search.memories(
q=user_message,
container_tag=user_id,
threshold=0.6, # Balanced relevance
rerank=False, # Skip for speed
rewrite_query=False, # Skip for speed
limit=3 # Few, relevant results
)
# Quick response for chat
context = '\n\n'.join([r.memory for r in results.results])
```
</Tab>
<Tab title="cURL">
```bash
# Optimized for chatbot responses
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "user question here",
"containerTag": "user_123",
"threshold": 0.6,
"rerank": false,
"rewriteQuery": false,
"limit": 3
}'
```
</Tab>
</Tabs>
## Complete Memories Search Example
Combining features for comprehensive results:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "machine learning model performance",
containerTag: "research_team",
filters: {
AND: [
{ key: "topic", value: "ai", negate: false }
]
},
threshold: 0.7,
rerank: true,
rewriteQuery: false, // Skip for speed
include: {
documents: true,
relatedMemories: false,
summaries: true
},
limit: 5
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="machine learning model performance",
container_tag="research_team",
filters={
"AND": [
{"key": "topic", "value": "ai", "negate": False}
]
},
threshold=0.7,
rerank=True,
rewrite_query=False, # Skip for speed
include={
"documents": True,
"relatedMemories": False,
"summaries": True
},
limit=5
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning model performance",
"containerTag": "research_team",
"filters": {
"AND": [
{"key": "topic", "value": "ai", "negate": false}
]
},
"threshold": 0.7,
"rerank": true,
"rewriteQuery": false,
"include": {
"documents": true,
"relatedMemories": false,
"summaries": true
},
"limit": 5
}'
```
</Tab>
</Tabs>
## Hybrid Search Mode
Hybrid search mode allows you to search both memories and document chunks in a single request. When `searchMode="hybrid"`, results contain objects with either a `memory` key (for memory results) or a `chunk` key (for chunk results).
### Basic Hybrid Search
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "machine learning best practices",
searchMode: "hybrid", // Search memories + chunks
limit: 10
});
// Handle mixed results
results.results.forEach(result => {
if ('memory' in result) {
console.log('Memory:', result.memory);
} else if ('chunk' in result) {
console.log('Chunk:', result.chunk);
console.log('From document:', result.documents?.[0]?.title);
}
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="machine learning best practices",
search_mode="hybrid", # Search memories + chunks
limit=10
)
# Handle mixed results
for result in results.results:
if 'memory' in result:
print('Memory:', result['memory'])
elif 'chunk' in result:
print('Chunk:', result['chunk'])
print('From document:', result.get('documents', [{}])[0].get('title'))
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning best practices",
"searchMode": "hybrid",
"limit": 10
}'
```
</Tab>
</Tabs>
### When to Use Hybrid Mode
Use hybrid mode when:
- You want comprehensive search across both memories and documents
- Memories might not exist for certain queries but document content is available
- You need flexibility to get either memory or document chunk results
- You want a single search endpoint that covers all content types
Use memories-only mode (`searchMode="memories"`) when:
- You only need user memories and preferences
- You want faster, more focused results
- You're building a personalized chatbot that relies on user context
### Handling Mixed Results
When using hybrid mode, you'll receive mixed results. Here's how to process them:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "quantum computing applications",
searchMode: "hybrid",
limit: 10
});
// Separate memory and chunk results
const memoryResults = results.results.filter(r => 'memory' in r);
const chunkResults = results.results.filter(r => 'chunk' in r);
console.log(`Found ${memoryResults.length} memories and ${chunkResults.length} chunks`);
// Process memories
memoryResults.forEach(mem => {
console.log('Memory:', mem.memory);
console.log('Similarity:', mem.similarity);
});
// Process chunks
chunkResults.forEach(chunk => {
console.log('Chunk:', chunk.chunk);
console.log('Document:', chunk.documents?.[0]?.title);
console.log('Similarity:', chunk.similarity);
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="quantum computing applications",
search_mode="hybrid",
limit=10
)
# Separate memory and chunk results
memory_results = [r for r in results.results if 'memory' in r]
chunk_results = [r for r in results.results if 'chunk' in r]
print(f"Found {len(memory_results)} memories and {len(chunk_results)} chunks")
# Process memories
for mem in memory_results:
print('Memory:', mem['memory'])
print('Similarity:', mem['similarity'])
# Process chunks
for chunk in chunk_results:
print('Chunk:', chunk['chunk'])
print('Document:', chunk.get('documents', [{}])[0].get('title'))
print('Similarity:', chunk['similarity'])
```
</Tab>
</Tabs>
### Hybrid Search with All Features
Combining hybrid mode with other features:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.memories({
q: "research findings on AI",
searchMode: "hybrid",
containerTag: "research_team",
threshold: 0.7,
rerank: true,
include: {
documents: true,
relatedMemories: true,
summaries: true
},
limit: 10
});
// Results are automatically sorted by similarity
// Memory results have 'memory' field, chunk results have 'chunk' field
results.results.forEach(result => {
if ('memory' in result) {
// Memory result
console.log('Memory:', result.memory);
console.log('Context:', result.context);
} else {
// Chunk result
console.log('Chunk:', result.chunk);
console.log('Document:', result.documents?.[0]);
}
});
```
</Tab>
<Tab title="Python">
```python
results = client.search.memories(
q="research findings on AI",
search_mode="hybrid",
container_tag="research_team",
threshold=0.7,
rerank=True,
include={
"documents": True,
"relatedMemories": True,
"summaries": True
},
limit=10
)
# Results are automatically sorted by similarity
# Memory results have 'memory' field, chunk results have 'chunk' field
for result in results.results:
if 'memory' in result:
# Memory result
print('Memory:', result['memory'])
print('Context:', result.get('context'))
else:
# Chunk result
print('Chunk:', result['chunk'])
print('Document:', result.get('documents', [{}])[0])
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "research findings on AI",
"searchMode": "hybrid",
"containerTag": "research_team",
"threshold": 0.7,
"rerank": true,
"include": {
"documents": true,
"relatedMemories": true,
"summaries": true
},
"limit": 10
}'
```
</Tab>
</Tabs>
<Note>
**Important**: In hybrid mode, results are automatically merged and sorted by similarity score. Memory results and chunk results are deduplicated - if a chunk is already associated with a memory result, it won't appear as a separate chunk result.
</Note>
## Common Use Cases
- **Chatbots**: Basic search with container tag and low threshold
- **Q&A Systems**: Add reranking for better relevance
- **Knowledge Retrieval**: Include documents and summaries
- **Real-time Search**: Skip rewriting and reranking for maximum speed
- **Hybrid Search**: Use `searchMode="hybrid"` when you need comprehensive search across both memories and documents

View file

@ -1,493 +0,0 @@
---
title: "Search with Filters & Scoring"
description: "Semantic and hybrid search with metadata filters, scoring, and precise result control"
sidebarTitle : "Overview"
---
## Prerequisites
Before searching memories, you need to set up the Supermemory client:
- **Install the SDK** for your language
- **Get your API key** from [Supermemory Console](https://console.supermemory.ai)
- **Initialize the client** with your API key
<CodeGroup>
```bash npm
npm install supermemory
```
```bash pip
pip install supermemory
```
</CodeGroup>
<CodeGroup>
```typescript TypeScript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
```
```python Python
from supermemory import Supermemory
import os
client = Supermemory(
api_key=os.environ.get("SUPERMEMORY_API_KEY")
)
```
</CodeGroup>
## Search Endpoints Overview
<CardGroup cols={2}>
<Card title="Documents Search - Fast, Advanced RAG" icon="settings" href="/search/examples/document-search">
**POST /v3/search**
Full-featured search with extensive control over ranking, filtering, thresholds, and result structure. Searches through and returns relevant documents. More flexibility.
</Card>
<Card title="Memories Search" icon="zap" href="/search/examples/memory-search">
**POST /v4/search**
Minimal-latency search optimized for chatbots and conversational AI. Searches through and returns memories. Simple parameters, fast responses, easy to use.
</Card>
</CardGroup>
## Documents vs Memories Search: What's the Difference?
The key difference between `/v3/search` and `/v4/search` is **documents vs memories**. `/v3/search` searches through the documents and returns matching chunks, whereas `/v4/search` searches through user's memories, preferences and history.
- **Documents:** Refer to the data you ingest like text, pdfs, videos, images, etc. They are sources of ground truth.
- **Memories:** They are automatically extracted from your documents by Supermemory. Smaller information chunks inferred from documents and related to each other.
Refer to the [ingestion guide](/memory-api/ingesting) to learn more about the difference between documents and memories.
### Documents Search (`/v3/search`)
**High quality documents search** - extensive parameters for fine-tuning search behavior:
- **Use cases**: Use this endpoint for use cases where "literal" document search is required.
- Looking through legal/finance documents
- Searching through items in google drive
- Chat with documentation
- With this endpoint, you get **Full Control** over
- Thresholds,
- Filtering
- Reranking
- Query rewriting
<Tabs>
<Tab title="TypeScript">
```typescript
// Documents search
const results = await client.search.documents({
q: "machine learning accuracy",
limit: 10,
documentThreshold: 0.7,
chunkThreshold: 0.8,
rerank: true,
rewriteQuery: true,
includeFullDocs: true,
includeSummary: true,
onlyMatchingChunks: false,
containerTags: ["research"],
filters: {
AND: [{ key: "category", value: "ai", negate: false }]
}
});
```
</Tab>
<Tab title="Python">
```python
# Documents search
results = client.search.documents(
q="machine learning accuracy",
limit=10,
document_threshold=0.7,
chunk_threshold=0.8,
rerank=True,
rewrite_query=True,
include_full_docs=True,
include_summary=True,
only_matching_chunks=False,
container_tags=["research"],
filters={
"AND": [{"key": "category", "value": "ai", "negate": False}]
}
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning accuracy",
"limit": 10,
"documentThreshold": 0.7,
"chunkThreshold": 0.8,
"rerank": true,
"rewriteQuery": true,
"includeFullDocs": true,
"includeSummary": true,
"onlyMatchingChunks": false,
"containerTags": ["research"],
"filters": {
"AND": [{"key": "category", "value": "ai", "negate": false}]
}
}'
```
</Tab>
</Tabs>
```json Sample Response
{
"results": [
{
"documentId": "doc_abc123",
"title": "Machine Learning Fundamentals",
"type": "pdf",
"score": 0.89,
"chunks": [
{
"content": "Machine learning is a subset of artificial intelligence...",
"score": 0.95,
"isRelevant": true
}
],
"metadata": {
"category": "education",
"author": "Dr. Smith",
"difficulty": "beginner"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-20T14:45:00Z"
}
],
"timing": 187,
"total": 1
}
```
The `/v3/search` endpoint returns the most relevant documents and chunks from those documents. Head over to the [response schema](/search/response-schema) page to understand more about the response structure.
### Memories Search (`/v4/search`)
**Search through user memories**:
- **Use cases**: Use this endpoint for use cases where understanding user context / preferences / memories is more important than literal document search.
- Personalized chatbots (AI Companions)
- Auto selecting based on what the user wants
- Setting the tone of the conversation
Companies like Composio [Rube.app](https://rube.app) use memories search for letting the MCP automate better based on the user prompts before.
<Info>
This endpoint works best for conversational AI use cases like chatbots.
</Info>
**Hybrid Search Mode:**
The `/v4/search` endpoint supports a `searchMode` parameter with two options:
- **`"memories"`** (default): Searches only memory entries. Returns results with a `memory` key containing the memory content.
- **`"hybrid"`**: Searches memories first, then falls back to document chunks if needed. Returns mixed results where each result object has either a `memory` key (for memory results) or a `chunk` key (for chunk results from documents).
<Note>
In hybrid mode, results are automatically merged by similarity score and deduplicated. Check for the presence of `memory` or `chunk` keys to distinguish result types.
</Note>
<Tabs>
<Tab title="TypeScript">
```typescript
// Memories search (default mode)
const results = await client.search.memories({
q: "machine learning accuracy",
limit: 5,
containerTag: "research",
threshold: 0.7,
rerank: true,
searchMode: "memories" // Default: only search memories
});
// Hybrid search (memories + chunks)
const hybridResults = await client.search.memories({
q: "machine learning accuracy",
limit: 5,
containerTag: "research",
threshold: 0.7,
searchMode: "hybrid" // Search memories + fallback to chunks
});
```
</Tab>
<Tab title="Python">
```python
# Memories search (default mode)
results = client.search.memories(
q="machine learning accuracy",
limit=5,
container_tag="research",
threshold=0.7,
rerank=True,
search_mode="memories" # Default: only search memories
)
# Hybrid search (memories + chunks)
hybrid_results = client.search.memories(
q="machine learning accuracy",
limit=5,
container_tag="research",
threshold=0.7,
search_mode="hybrid" # Search memories + fallback to chunks
)
```
</Tab>
<Tab title="cURL">
```bash
# Memories search (default mode)
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning accuracy",
"limit": 5,
"containerTag": "research",
"threshold": 0.7,
"rerank": true,
}'
# Hybrid search (memories + chunks)
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning accuracy",
"limit": 5,
"containerTag": "research",
"threshold": 0.7,
"rerank": true,
"searchMode": "hybrid"
}'
```
</Tab>
</Tabs>
```json Sample Response
{
"results": [
{
"id": "mem_xyz789",
"memory": "Complete memory content about quantum computing applications...",
"similarity": 0.87,
"metadata": {
"category": "research",
"topic": "quantum-computing"
},
"updatedAt": "2024-01-18T09:15:00Z",
"version": 3,
"context": {
"parents": [
{
"memory": "Earlier discussion about quantum theory basics...",
"relation": "extends",
"version": 2,
"updatedAt": "2024-01-17T16:30:00Z"
}
],
"children": [
{
"memory": "Follow-up questions about quantum algorithms...",
"relation": "derives",
"version": 4,
"updatedAt": "2024-01-19T11:20:00Z"
}
]
},
"documents": [
{
"id": "doc_quantum_paper",
"title": "Quantum Computing Applications",
"type": "pdf",
"createdAt": "2024-01-10T08:00:00Z"
}
]
}
],
"timing": 156,
"total": 1
}
```
The `/v4/search` endpoint searches through and returns memories. With `searchMode="hybrid"`, it can also return document chunks when memories aren't found, providing comprehensive search coverage.
## Direct Document Retrieval
If you don't need semantic search and just want to retrieve a specific document you've uploaded by its ID, use the GET document endpoint:
`GET /v3/documents/{id}`
This is useful when:
- You know the exact document ID
- You want to retrieve the full document content and metadata
- You need to check processing status or document details
<CodeGroup>
```typescript TypeScript
// Get a specific document by ID
const document = await client.documents.get("doc_abc123");
console.log(document.content); // Full document content
console.log(document.status); // Processing status
console.log(document.metadata); // Document metadata
console.log(document.summary); // AI-generated summary
```
```python Python
# Get a specific document by ID
document = client.documents.get("doc_abc123")
print(document.content) # Full document content
print(document.status) # Processing status
```
```bash cURL
curl -X GET "https://api.supermemory.ai/v3/documents/{YOUR-DOCUMENT-ID}" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
```
</CodeGroup>
<Note>
This endpoint returns the complete document with all fields including content, metadata, containerTags, summary, and processing status. For more details, see the API Reference tab.
</Note>
## Search Flow Architecture
### Document Search (`/v3/search`) Flow
```mermaid
graph TD
A[Query Input] --> B{Rewrite Query?}
B -->|Yes| C[Query Rewriting +400ms]
B -->|No| D[Generate Embeddings]
C --> E[Generate Rewritten Embeddings]
D --> F[Search Execution]
E --> F
F --> G[Apply Filtering<br/>metadata, categories, containerTags]
G --> H{Rerank?}
H -->|Yes| I[Apply Reranking]
H -->|No| J[Build Results with Chunks]
I --> J
J --> K[Return Documents + Chunks + Scores]
```
### Memory Search (`/v4/search`) Flow
```mermaid
graph TD
A[Query Input] --> B[Query Rewriting + Embedding]
B --> C[Parallel Search Execution]
C --> D[Apply Filtering]
D --> E[Merge Results]
E --> F[Deduplication]
F --> G{Rerank?}
G -->|Yes| H[Apply Reranking]
G -->|No| I[Return Memories + Similarity]
H --> I
```
## Key Concepts You Need to Understand
### 1. Thresholds (Sensitivity Control)
Thresholds control result quality vs quantity:
- **0.0** = Least sensitive (more results, lower quality)
- **1.0** = Most sensitive (fewer results, higher quality)
```typescript
// Different threshold strategies
const broadSearch = await client.search.documents({
q: "machine learning",
chunkThreshold: 0.2, // Return more chunks
documentThreshold: 0.1 // From more documents
});
const preciseSearch = await client.search.documents({
q: "machine learning",
chunkThreshold: 0.8, // Only highly relevant chunks
documentThreshold: 0.7 // From closely matching documents
});
```
### 2. Chunk Context vs Exact Matching
By default, Supermemory returns chunks **with context** (surrounding text):
```typescript
// Default: includes surrounding chunks for context
const contextualResults = await client.search.documents({
q: "neural networks",
onlyMatchingChunks: false // Default
});
// Precise: only the exact matching text
const exactResults = await client.search.documents({
q: "neural networks",
onlyMatchingChunks: true
});
```
### 3. Query Rewriting & Reranking
**Query Rewriting** (+400ms latency):
- Expands your query to find more relevant results
- "ML" becomes "machine learning artificial intelligence"
- Useful for abbreviations and domain-specific terms
**Reranking**:
- Re-scores results using a different algorithm
- More accurate but slower
- Recommended for critical searches
### 4. Container Tags vs Metadata Filters
Two different filtering mechanisms:
When to use container tags:
- The user understanding graph is built on top of container tags. **The graph is formed on top of container tags.**
- Container tags are used for organizational grouping and exact matching.
- They are useful for categorizing content and ensuring precise results.
When to use metadata filters:
- When you need flexible conditions beyond exact matches.
- Useful for filtering by attributes like date, author, or category.
```typescript
// Container tags: Organizational grouping (exact array matching)
const userContent = await client.search.documents({
q: "python tutorial",
containerTag "user_123" // Must match exactly
});
// Metadata filters: SQL-based queries (flexible conditions)
const filteredContent = await client.search.documents({
q: "python tutorial",
filters: JSON.stringify({
AND: [
{ key: "language", value: "python", negate: false },
{ key: "difficulty", value: "beginner", negate: false }
]
})
});
```

View file

@ -1,264 +0,0 @@
---
title: "Search Parameters"
description: "Complete reference for all search parameters and their effects"
---
Complete parameter reference for all three search endpoints: document search, memory search, and execute search.
## Common Parameters
These parameters work across all search endpoints:
<ParamField query="q" type="string" required>
**Search query string**
The text you want to search for. Can be natural language, keywords, or questions.
```typescript
q: "machine learning neural networks"
q: "What are the applications of quantum computing?"
q: "python tutorial beginner"
```
</ParamField>
<ParamField query="limit" type="number" default="10">
**Maximum number of results to return**
Controls how many results you get back. Higher limits increase response time and size.
```typescript
limit: 5 // Fast, focused results
limit: 20 // Comprehensive results
limit: 100 // Maximum recommended
```
</ParamField>
<ParamField query="containerTags" type="Array<string>">
**Filter by container tags**
Organizational tags for filtering results. Uses **exact array matching** - must match all tags in the same order.
```typescript
containerTags: ["user_123"] // Single tag
containerTags: ["user_123", "project_ai"] // Multiple tags (exact match)
```
</ParamField>
<ParamField query="filters" type="string">
**Metadata filtering with SQL-like structure**
JSON string containing AND/OR logic for filtering by metadata fields. Uses the same structure as memory listing filters.
```typescript
filters: JSON.stringify({
AND: [
{ key: "category", value: "tutorial", negate: false },
{ key: "difficulty", value: "beginner", negate: false }
]
})
```
<Note>
See [Metadata Filtering Guide](/concepts/filtering) for complete syntax and examples.
</Note>
</ParamField>
<ParamField query="rerank" type="boolean" default="false">
**Re-score results for better relevance**
Applies a secondary ranking algorithm to improve result quality. Adds ~100-200ms latency but increases accuracy.
```typescript
rerank: true // Better accuracy, slower
rerank: false // Faster, standard accuracy
```
</ParamField>
<ParamField query="rewriteQuery" type="boolean" default="false">
**Expand and improve the query**
Rewrites your query to find more relevant results. Particularly useful for abbreviations and domain-specific terms. **Adds ~400ms latency**.
```typescript
// Query rewriting examples:
"ML" → "machine learning artificial intelligence"
"JS" → "JavaScript programming language"
"API" → "application programming interface REST"
```
<Warning>
Query rewriting significantly increases latency. Only use when search quality is more important than speed.
</Warning>
</ParamField>
## Document Search Parameters (POST `/v3/search`)
These parameters are specific to `client.search.documents()`:
<ParamField query="chunkThreshold" type="number" range="0-1" default="0.5">
**Sensitivity for chunk selection**
Controls which text chunks are included in results:
- **0.0** = Least sensitive (more chunks, more results)
- **1.0** = Most sensitive (fewer chunks, higher quality)
```typescript
chunkThreshold: 0.2 // Broad search, many chunks
chunkThreshold: 0.8 // Precise search, only relevant chunks
```
</ParamField>
<ParamField query="documentThreshold" type="number" range="0-1" default="0.5">
**Sensitivity for document selection**
Controls which documents are considered for search:
- **0.0** = Search more documents (comprehensive)
- **1.0** = Search only highly relevant documents (focused)
```typescript
documentThreshold: 0.1 // Cast wide net
documentThreshold: 0.9 // Only very relevant documents
```
</ParamField>
<ParamField query="docId" type="string">
**Search within a specific document**
Limit search to chunks within a single document. Useful for finding content in large documents.
```typescript
docId: "doc_abc123" // Only search this document
```
</ParamField>
<ParamField query="onlyMatchingChunks" type="boolean" default="false">
**Return only exact matching chunks**
By default, Supermemory includes surrounding chunks for context. Set to `true` to get only the exact matching text.
```typescript
onlyMatchingChunks: false // Include context chunks (default)
onlyMatchingChunks: true // Only matching chunks
```
<Note>
Context chunks help LLMs understand the full meaning. Only disable if you need precise text extraction.
</Note>
</ParamField>
<ParamField query="includeFullDocs" type="boolean" default="false">
**Include complete document content**
Adds the full document text to each result. Useful for chatbots that need complete context.
```typescript
includeFullDocs: true // Full document in response
includeFullDocs: false // Only chunks and metadata
```
<Warning>
Including full documents can make responses very large. Use sparingly and with appropriate limits.
</Warning>
</ParamField>
<ParamField query="includeSummary" type="boolean" default="false">
**Include document summaries**
Adds AI-generated document summaries to results. Good middle-ground between chunks and full documents.
```typescript
includeSummary: true // Include document summaries
includeSummary: false // No summaries
```
</ParamField>
<ParamField query="filters" type="string">
**Filter by metadata using SQL queries**
```typescript
// Use this instead:
filters: JSON.stringify({
OR: [
{ key: "category", value: "technology", negate: false },
{ key: "category", value: "science", negate: false }
]
})
```
</ParamField>
## Memory Search Parameters (POST `/v4/search`)
These parameters are specific to `client.search.memories()`:
<ParamField query="threshold" type="number" range="0-1" default="0.5">
**Sensitivity for memory selection**
Controls which memories are returned based on similarity:
- **0.0** = Return more memories (broad search)
- **1.0** = Return only highly similar memories (precise search)
```typescript
threshold: 0.3 // Broader memory search
threshold: 0.8 // Only very similar memories
```
</ParamField>
<ParamField query="searchMode" type="string" default="memories">
**Search mode - memories only or hybrid search**
Controls whether to search only memories or also include document chunks:
- **`"memories"`** (default): Searches only memory entries. Returns results with `memory` field.
- **`"hybrid"`**: Searches memories first, then falls back to document chunks if needed. Returns mixed results with either `memory` field (for memory results) or `chunk` field (for chunk results).
<Note>
In hybrid mode, results are automatically merged and deduplicated. Results contain objects with either a `memory` key (for memory results) or a `chunk` key (for chunk results from document search).
</Note>
```typescript
searchMode: "memories" // Only search memories (default)
searchMode: "hybrid" // Search memories + fallback to chunks
```
**When to use hybrid mode:**
- When you want comprehensive search across both memories and documents
- When memories might not exist for certain queries but document content is available
- When you need the flexibility to get either memory or document chunk results
</ParamField>
<ParamField query="containerTag" type="string">
**Filter by single container tag**
Note: Memory search uses `containerTag` (singular) while document search uses `containerTags` (plural array).
```typescript
containerTag: "user_123" // Single tag for memory search
```
</ParamField>
<ParamField query="include" type="object">
**Control what additional data to include**
Object specifying what contextual information to include with memory results.
<ParamField query="include.documents" type="boolean" default="false">
Include associated documents for each memory
</ParamField>
<ParamField query="include.relatedMemories" type="boolean" default="false">
Include parent and child memories (contextual relationships)
</ParamField>
<ParamField query="include.summaries" type="boolean" default="false">
Include memory summaries
</ParamField>
```typescript
include: {
documents: true, // Show related documents
relatedMemories: true, // Show parent/child memories
summaries: true // Include summaries
}
```
</ParamField>

View file

@ -1,440 +0,0 @@
---
title: "Query Rewriting"
description: "Improve search accuracy with automatic query expansion and rewriting"
---
![query rewriting](/images/query-rewriting.png)
Query rewriting automatically generates multiple variations of your search query to improve result coverage and accuracy. Supermemory creates several rewrites, searches through all of them, then merges and deduplicates the results.
## How Query Rewriting Works
When you enable `rewriteQuery: true`, Supermemory:
1. **Analyzes your original query** for intent and key concepts
2. **Generates multiple rewrites** with different phrasings and synonyms
3. **Executes searches** for both original and rewritten queries in parallel
4. **Merges and deduplicates** results from all queries
5. **Returns unified results** ranked by relevance
This process adds ~400ms latency but significantly improves result quality, especially for:
- **Natural language questions** ("How do neural networks learn?")
- **Ambiguous terms** that could have multiple meanings
- **Complex queries** with multiple concepts
- **Domain-specific terminology** that might have synonyms
## Basic Query Rewriting
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
// Without query rewriting
const basicResults = await client.search.documents({
q: "How do transformers work in AI?",
rewriteQuery: false,
limit: 5
});
// With query rewriting - generates multiple query variations
const rewrittenResults = await client.search.documents({
q: "How do transformers work in AI?",
rewriteQuery: true,
limit: 5
});
console.log(`Basic search: ${basicResults.total} results`);
console.log(`Rewritten search: ${rewrittenResults.total} results`);
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
# Without query rewriting
basic_results = client.search.documents(
q="How do transformers work in AI?",
rewrite_query=False,
limit=5
)
# With query rewriting - generates multiple query variations
rewritten_results = client.search.documents(
q="How do transformers work in AI?",
rewrite_query=True,
limit=5
)
print(f"Basic search: {basic_results.total} results")
print(f"Rewritten search: {rewritten_results.total} results")
```
</Tab>
<Tab title="cURL">
```bash
# Without query rewriting
echo "Basic search:"
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "How do transformers work in AI?",
"rewriteQuery": false,
"limit": 5
}' | jq '.total'
# With query rewriting
echo "Rewritten search:"
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "How do transformers work in AI?",
"rewriteQuery": true,
"limit": 5
}' | jq '.total'
```
</Tab>
</Tabs>
**Sample Output Comparison:**
```json
// Without rewriting: 3 results
{
"results": [...],
"total": 3,
"timing": 120
}
// With rewriting: 8 results (found more relevant content)
{
"results": [...],
"total": 8,
"timing": 520 // +400ms for query processing
}
```
## Natural Language Questions
Query rewriting excels at converting conversational questions into effective search queries:
<Tabs>
<Tab title="TypeScript">
```typescript
// Natural language question
const results = await client.search.documents({
q: "What are the best practices for training deep learning models?",
rewriteQuery: true,
limit: 10
});
// The system might generate rewrites like:
// - "deep learning model training best practices"
// - "neural network training optimization techniques"
// - "machine learning model training guidelines"
// - "deep learning training methodology"
```
</Tab>
<Tab title="Python">
```python
# Natural language question
results = client.search.documents(
q="What are the best practices for training deep learning models?",
rewrite_query=True,
limit=10
)
# The system might generate rewrites like:
# - "deep learning model training best practices"
# - "neural network training optimization techniques"
# - "machine learning model training guidelines"
# - "deep learning training methodology"
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "What are the best practices for training deep learning models?",
"rewriteQuery": true,
"limit": 10
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"documentId": "doc_123",
"title": "Deep Learning Training Guide",
"score": 0.92,
"chunks": [
{
"content": "Best practices for training deep neural networks include proper weight initialization, learning rate scheduling, and regularization techniques...",
"score": 0.89,
"isRelevant": true
}
]
},
{
"documentId": "doc_456",
"title": "Neural Network Optimization",
"score": 0.87,
"chunks": [
{
"content": "Effective training methodologies involve batch normalization, dropout, and gradient clipping to prevent overfitting...",
"score": 0.85,
"isRelevant": true
}
]
}
],
"total": 12,
"timing": 445
}
```
## Technical Term Expansion
Query rewriting helps find content using different technical terminologies:
<Tabs>
<Tab title="TypeScript">
```typescript
// Original query with specific terminology
const results = await client.search.documents({
q: "CNN architecture patterns",
rewriteQuery: true,
containerTags: ["research"],
limit: 8
});
// System expands to include:
// - "convolutional neural network architecture"
// - "CNN design patterns"
// - "convolutional network structures"
// - "CNN architectural components"
```
</Tab>
<Tab title="Python">
```python
# Original query with specific terminology
results = client.search.documents(
q="CNN architecture patterns",
rewrite_query=True,
container_tags=["research"],
limit=8
)
# System expands to include:
# - "convolutional neural network architecture"
# - "CNN design patterns"
# - "convolutional network structures"
# - "CNN architectural components"
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "CNN architecture patterns",
"rewriteQuery": true,
"containerTags": ["research"],
"limit": 8
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"documentId": "doc_789",
"title": "Convolutional Neural Network Architectures",
"score": 0.94,
"chunks": [
{
"content": "Modern CNN architectures like ResNet and DenseNet utilize skip connections to address the vanishing gradient problem...",
"score": 0.91,
"isRelevant": true
}
]
},
{
"documentId": "doc_101",
"title": "Deep Learning Design Patterns",
"score": 0.88,
"chunks": [
{
"content": "Convolutional layers followed by pooling operations form the fundamental building blocks of CNN architectures...",
"score": 0.86,
"isRelevant": true
}
]
}
],
"total": 15,
"timing": 478
}
```
## Memory Search with Query Rewriting
Query rewriting works with both document and memory search:
<Tabs>
<Tab title="TypeScript">
```typescript
// Memory search with query rewriting
const memoryResults = await client.search.memories({
q: "explain quantum entanglement simply",
rewriteQuery: true,
containerTag: "physics_notes",
limit: 5
});
// Generates variations like:
// - "quantum entanglement explanation"
// - "what is quantum entanglement"
// - "quantum entanglement basics"
// - "simple quantum entanglement description"
```
</Tab>
<Tab title="Python">
```python
# Memory search with query rewriting
memory_results = client.search.memories(
q="explain quantum entanglement simply",
rewrite_query=True,
container_tag="physics_notes",
limit=5
)
# Generates variations like:
# - "quantum entanglement explanation"
# - "what is quantum entanglement"
# - "quantum entanglement basics"
# - "simple quantum entanglement description"
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "explain quantum entanglement simply",
"rewriteQuery": true,
"containerTag": "physics_notes",
"limit": 5
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"id": "mem_456",
"memory": "Quantum entanglement is a phenomenon where two particles become connected in such a way that measuring one instantly affects the other, regardless of distance. Think of it like having two magical coins that always land on opposite sides.",
"similarity": 0.91,
"title": "Simple Quantum Entanglement Explanation",
"metadata": {
"topic": "quantum-physics",
"difficulty": "beginner"
}
},
{
"id": "mem_789",
"memory": "Einstein called quantum entanglement 'spooky action at a distance' because entangled particles seem to communicate instantaneously across vast distances, challenging our understanding of locality in physics.",
"similarity": 0.87,
"title": "Einstein's View on Entanglement"
}
],
"total": 7,
"timing": 412
}
```
## Complex Multi-Concept Queries
Query rewriting excels at handling queries with multiple concepts:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "machine learning bias fairness algorithmic discrimination",
rewriteQuery: true,
filters: {
AND: [
{ key: "category", value: "ethics", negate: false }
]
},
limit: 10
});
// Breaks down into focused rewrites:
// - "machine learning bias detection"
// - "algorithmic fairness in AI"
// - "discrimination in machine learning algorithms"
// - "bias mitigation techniques ML"
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="machine learning bias fairness algorithmic discrimination",
rewrite_query=True,
filters={
"AND": [
{"key": "category", "value": "ethics", "negate": False}
]
},
limit=10
)
# Breaks down into focused rewrites:
# - "machine learning bias detection"
# - "algorithmic fairness in AI"
# - "discrimination in machine learning algorithms"
# - "bias mitigation techniques ML"
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "machine learning bias fairness algorithmic discrimination",
"rewriteQuery": true,
"filters": {
"AND": [
{"key": "category", "value": "ethics", "negate": false}
]
},
"limit": 10
}'
```
</Tab>
</Tabs>

View file

@ -1,387 +0,0 @@
---
title: "Reranking"
description: "Improve result relevance with secondary ranking algorithms"
---
Reranking applies a secondary ranking algorithm to improve the relevance order of search results. After the initial search returns results, the reranker analyzes the relationship between your query and each result to provide better ordering.
## How Reranking Works
Supermemory's reranking process:
1. **Initial search** returns results using standard semantic similarity
2. **Reranker model** analyzes query-result pairs
3. **Scores are recalculated** based on deeper semantic understanding
4. **Results are reordered** by the new relevance scores
5. **Final results** maintain the same structure but with improved ordering
The reranker is particularly effective at:
- **Understanding context** and nuanced relationships
- **Handling ambiguous queries** with multiple possible meanings
- **Improving precision** for complex technical topics
- **Better ranking** when results have similar initial scores
## Basic Reranking Comparison
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
// Search without reranking
const standardResults = await client.search.documents({
q: "neural network optimization techniques",
rerank: false,
limit: 5
});
// Search with reranking
const rerankedResults = await client.search.documents({
q: "neural network optimization techniques",
rerank: true,
limit: 5
});
console.log("Standard top result:", standardResults.results[0].score);
console.log("Reranked top result:", rerankedResults.results[0].score);
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
# Search without reranking
standard_results = client.search.documents(
q="neural network optimization techniques",
rerank=False,
limit=5
)
# Search with reranking
reranked_results = client.search.documents(
q="neural network optimization techniques",
rerank=True,
limit=5
)
print("Standard top result:", standard_results.results[0].score)
print("Reranked top result:", reranked_results.results[0].score)
```
</Tab>
<Tab title="cURL">
```bash
# Without reranking
echo "Standard ranking:"
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "neural network optimization techniques",
"rerank": false,
"limit": 3
}' | jq '.results[0] | {title, score}'
# With reranking
echo "Reranked results:"
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "neural network optimization techniques",
"rerank": true,
"limit": 3
}' | jq '.results[0] | {title, score}'
```
</Tab>
</Tabs>
**Sample Output Comparison:**
```json
// Without reranking - results ordered by semantic similarity
{
"results": [
{
"title": "Deep Learning Optimization Methods",
"score": 0.82,
"chunks": [
{
"content": "Various optimization algorithms like Adam, RMSprop, and SGD are used in neural network training...",
"score": 0.79
}
]
},
{
"title": "Neural Network Training Techniques",
"score": 0.81,
"chunks": [
{
"content": "Batch normalization and dropout are common regularization techniques for neural networks...",
"score": 0.78
}
]
}
],
"timing": 145
}
// With reranking - results reordered by contextual relevance
{
"results": [
{
"title": "Neural Network Training Techniques",
"score": 0.89, // Boosted by reranker
"chunks": [
{
"content": "Batch normalization and dropout are common regularization techniques for neural networks...",
"score": 0.85
}
]
},
{
"title": "Deep Learning Optimization Methods",
"score": 0.86, // Slightly adjusted
"chunks": [
{
"content": "Various optimization algorithms like Adam, RMSprop, and SGD are used in neural network training...",
"score": 0.83
}
]
}
],
"timing": 267 // Additional ~120ms for reranking
}
```
## Complex Query Reranking
Reranking excels with complex, multi-faceted queries:
<Tabs>
<Tab title="TypeScript">
```typescript
const results = await client.search.documents({
q: "sustainable machine learning carbon footprint energy efficiency",
rerank: true,
containerTags: ["research", "sustainability"],
limit: 8
});
// Reranker understands the connection between:
// - Machine learning computational costs
// - Environmental impact of AI training
// - Energy-efficient model architectures
// - Green computing practices in ML
```
</Tab>
<Tab title="Python">
```python
results = client.search.documents(
q="sustainable machine learning carbon footprint energy efficiency",
rerank=True,
container_tags=["research", "sustainability"],
limit=8
)
# Reranker understands the connection between:
# - Machine learning computational costs
# - Environmental impact of AI training
# - Energy-efficient model architectures
# - Green computing practices in ML
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "sustainable machine learning carbon footprint energy efficiency",
"rerank": true,
"containerTags": ["research", "sustainability"],
"limit": 8
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"documentId": "doc_green_ai",
"title": "Green AI: Reducing the Carbon Footprint of Machine Learning",
"score": 0.94, // Highly relevant after reranking
"chunks": [
{
"content": "Training large neural networks can consume as much energy as several cars over their lifetime. Sustainable ML practices focus on model efficiency, pruning, and quantization to reduce computational demands...",
"score": 0.92,
"isRelevant": true
}
]
},
{
"documentId": "doc_efficient_models",
"title": "Energy-Efficient Neural Network Architectures",
"score": 0.91, // Boosted for strong topical relevance
"chunks": [
{
"content": "MobileNets and EfficientNets are designed specifically for energy-constrained environments, achieving high accuracy with minimal computational overhead...",
"score": 0.88,
"isRelevant": true
}
]
}
],
"total": 12,
"timing": 298
}
```
## Memory Search Reranking
Reranking also improves memory search results:
<Tabs>
<Tab title="TypeScript">
```typescript
const memoryResults = await client.search.memories({
q: "explain transformer architecture attention mechanism",
rerank: true,
containerTag: "ai_notes",
threshold: 0.6,
limit: 5
});
// Reranker identifies memories that best explain
// the relationship between transformers and attention
```
</Tab>
<Tab title="Python">
```python
memory_results = client.search.memories(
q="explain transformer architecture attention mechanism",
rerank=True,
container_tag="ai_notes",
threshold=0.6,
limit=5
)
# Reranker identifies memories that best explain
# the relationship between transformers and attention
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "explain transformer architecture attention mechanism",
"rerank": true,
"containerTag": "ai_notes",
"threshold": 0.6,
"limit": 5
}'
```
</Tab>
</Tabs>
**Sample Output:**
```json
{
"results": [
{
"id": "mem_transformer_intro",
"memory": "The transformer architecture revolutionized NLP by replacing recurrent layers with self-attention mechanisms. The attention mechanism allows the model to focus on different parts of the input sequence when processing each token, enabling parallel processing and better long-range dependency modeling.",
"similarity": 0.93, // Reranked higher for comprehensive explanation
"title": "Transformer Architecture Overview",
"metadata": {
"topic": "deep-learning",
"subtopic": "transformers"
}
},
{
"id": "mem_attention_detail",
"memory": "Self-attention computes attention weights by taking dot products between query, key, and value vectors derived from the input embeddings. This allows each position to attend to all positions in the previous layer, capturing complex relationships in the data.",
"similarity": 0.91, // Boosted for technical detail
"title": "Self-Attention Mechanism Details"
}
],
"total": 8,
"timing": 198
}
```
## Domain-Specific Reranking
Reranking understands domain-specific relationships:
<Tabs>
<Tab title="TypeScript">
```typescript
// Medical domain query
const medicalResults = await client.search.documents({
q: "diabetes treatment insulin resistance metformin",
rerank: true,
filters: {
AND: [
{ key: "domain", value: "medical", negate: false }
]
},
limit: 10
});
// Reranker understands medical relationships:
// - Diabetes types and treatments
// - Insulin resistance mechanisms
// - Metformin's role in diabetes management
```
</Tab>
<Tab title="Python">
```python
# Medical domain query
medical_results = client.search.documents(
q="diabetes treatment insulin resistance metformin",
rerank=True,
filters={
"AND": [
{"key": "domain", "value": "medical", "negate": False}
]
},
limit=10
)
# Reranker understands medical relationships:
# - Diabetes types and treatments
# - Insulin resistance mechanisms
# - Metformin's role in diabetes management
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "diabetes treatment insulin resistance metformin",
"rerank": true,
"filters": {
"AND": [
{"key": "domain", "value": "medical", "negate": false}
]
},
"limit": 10
}'
```
</Tab>
</Tabs>

View file

@ -1,354 +0,0 @@
---
title: "Response Schema"
description: "Complete response structure for all search endpoints with scoring details"
---
## Document Search Response (POST `/v3/search`)
Response from `client.search.documents()` and `client.search.execute()`:
```json
{
"results": [
{
"documentId": "doc_abc123",
"title": "Machine Learning Fundamentals",
"type": "pdf",
"score": 0.89,
"chunks": [
{
"content": "Machine learning is a subset of artificial intelligence...",
"score": 0.95,
"isRelevant": true
}
],
"metadata": {
"category": "education",
"author": "Dr. Smith",
"difficulty": "beginner"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-20T14:45:00Z"
}
],
"timing": 187,
"total": 1
}
```
### Document Result Fields
<ResponseField name="documentId" type="string">
Unique identifier for the document containing the matching chunks.
</ResponseField>
<ResponseField name="title" type="string | null">
Document title if available. May be null for documents without titles.
</ResponseField>
<ResponseField name="type" type="string | null">
Document type (e.g., "pdf", "text", "webpage", "notion_doc"). May be null if not specified.
</ResponseField>
<ResponseField name="score" type="number" range="0-1">
**Overall document relevance score**. Combines semantic similarity, keyword matching, and metadata relevance.
- **0.9-1.0**: Extremely relevant
- **0.7-0.9**: Highly relevant
- **0.5-0.7**: Moderately relevant
- **0.3-0.5**: Somewhat relevant
- **0.0-0.3**: Marginally relevant
</ResponseField>
<ResponseField name="chunks" type="Array<Chunk>">
Array of matching text chunks from the document. Each chunk represents a portion of the document that matched your query.
<ResponseField name="chunks[].content" type="string">
The actual text content of the matching chunk. May include context from surrounding chunks unless `onlyMatchingChunks=true`.
</ResponseField>
<ResponseField name="chunks[].score" type="number" range="0-1">
**Chunk-specific similarity score**. How well this specific chunk matches your query.
</ResponseField>
<ResponseField name="chunks[].isRelevant" type="boolean">
Whether this chunk passed the `chunkThreshold`. `true` means the chunk is above the threshold, `false` means it's included for context only.
</ResponseField>
</ResponseField>
<ResponseField name="metadata" type="object | null">
Document metadata as key-value pairs. Structure depends on what was stored with the document.
```json
{
"category": "tutorial",
"language": "python",
"difficulty": "intermediate",
"tags": "web-development,backend"
}
```
</ResponseField>
<ResponseField name="createdAt" type="string">
ISO 8601 timestamp when the document was created.
</ResponseField>
<ResponseField name="updatedAt" type="string">
ISO 8601 timestamp when the document was last updated.
</ResponseField>
<ResponseField name="content" type="string | null" optional>
**Full document content**. Only included when `includeFullDocs=true`. Can be very large.
<Warning>
Full document content can make responses extremely large. Use with appropriate limits and only when necessary.
</Warning>
</ResponseField>
<ResponseField name="summary" type="string | null" optional>
**AI-generated document summary**. Only included when `includeSummary=true`. Provides a concise overview of the document.
</ResponseField>
## Memory Search Response
Response from `client.search.memories()`:
When `searchMode="memories"` (default), all results are memory entries:
```json
{
"results": [
{
"id": "mem_xyz789",
"memory": "Complete memory content about quantum computing applications...",
"similarity": 0.87,
"metadata": {
"category": "research",
"topic": "quantum-computing"
},
"updatedAt": "2024-01-18T09:15:00Z",
"version": 3,
"context": {
"parents": [
{
"memory": "Earlier discussion about quantum theory basics...",
"relation": "extends",
"version": 2,
"updatedAt": "2024-01-17T16:30:00Z"
}
],
"children": [
{
"memory": "Follow-up questions about quantum algorithms...",
"relation": "derives",
"version": 4,
"updatedAt": "2024-01-19T11:20:00Z"
}
]
},
"documents": [
{
"id": "doc_quantum_paper",
"title": "Quantum Computing Applications",
"type": "pdf",
"createdAt": "2024-01-10T08:00:00Z"
}
]
}
],
"timing": 156,
"total": 1
}
```
When `searchMode="hybrid"`, results can contain both memory entries and document chunks. **Memory results have a `memory` key, chunk results have a `chunk` key:**
```json
{
"results": [
{
"id": "mem_xyz789",
"memory": "Complete memory content about quantum computing applications...",
"similarity": 0.87,
"metadata": {
"category": "research",
"topic": "quantum-computing"
},
"updatedAt": "2024-01-18T09:15:00Z",
"version": 3,
"context": {
"parents": [],
"children": []
},
"documents": [
{
"id": "doc_quantum_paper",
"title": "Quantum Computing Applications",
"type": "pdf",
"createdAt": "2024-01-10T08:00:00Z",
"updatedAt": "2024-01-10T08:00:00Z"
}
]
},
{
"id": "chunk_abc123",
"chunk": "This is a chunk of content from a document about quantum computing...",
"similarity": 0.82,
"metadata": {
"category": "research",
"source": "document"
},
"updatedAt": "2024-01-15T10:30:00Z",
"version": 1,
"context": {
"parents": [],
"children": []
},
"documents": [
{
"id": "doc_quantum_research",
"title": "Quantum Computing Research Paper",
"type": "pdf",
"metadata": {
"author": "Dr. Smith"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
]
}
],
"timing": 198,
"total": 2
}
```
<Note>
**Distinguishing Memory vs Chunk Results:**
In hybrid mode, check which key exists on the result object:
- **Memory results**: Have a `memory` key (no `chunk` key)
- **Chunk results**: Have a `chunk` key (no `memory` key)
```typescript
// TypeScript example
results.results.forEach(result => {
if ('memory' in result) {
// This is a memory result
console.log('Memory:', result.memory);
} else if ('chunk' in result) {
// This is a chunk result
console.log('Chunk:', result.chunk);
}
});
```
</Note>
### Memory Result Fields
<ResponseField name="id" type="string">
Unique identifier for the memory entry or chunk ID. In hybrid mode, can be either a memory ID (e.g., `mem_xyz789`) or a chunk ID (e.g., `chunk_abc123`).
</ResponseField>
<ResponseField name="memory" type="string" optional>
**Complete memory content**. Only present for memory results (when `searchMode="memories"` or when a memory result is returned in hybrid mode). This field is not present for chunk results.
</ResponseField>
<ResponseField name="chunk" type="string" optional>
**Chunk content from a document**. Only present for chunk results when `searchMode="hybrid"`. This field is not present for memory results. Contains the actual text content from the document chunk.
</ResponseField>
<ResponseField name="similarity" type="number" range="0-1">
**Similarity score** between your query and this memory. Higher scores indicate better matches.
- **0.9-1.0**: Extremely similar
- **0.8-0.9**: Very similar
- **0.7-0.8**: Similar
- **0.6-0.7**: Somewhat similar
- **0.5-0.6**: Marginally similar
</ResponseField>
<ResponseField name="metadata" type="object | null">
Memory metadata as key-value pairs. Structure depends on what was stored with the memory.
</ResponseField>
<ResponseField name="updatedAt" type="string">
ISO 8601 timestamp when the memory was last updated.
</ResponseField>
<ResponseField name="version" type="number | null" optional>
Version number of this memory entry. Used for tracking memory evolution and relationships. For chunk results, this is typically `1`.
</ResponseField>
<ResponseField name="rootMemoryId" type="string | null" optional>
Root memory ID for memory entries. Only present for memory results. Always `null` for chunk results.
</ResponseField>
<ResponseField name="context" type="object" optional>
**Contextual memory relationships**. Only included when `include.relatedMemories=true`.
<ResponseField name="context.parents" type="Array<ContextMemory>" optional>
Array of parent memories that this memory extends or derives from.
</ResponseField>
<ResponseField name="context.children" type="Array<ContextMemory>" optional>
Array of child memories that extend or derive from this memory.
</ResponseField>
### Context Memory Structure
<ResponseField name="memory" type="string">
Content of the related memory.
</ResponseField>
<ResponseField name="relation" type="string">
Relationship type: `"updates"`, `"extends"`, or `"derives"`.
- **updates**: This memory updates/replaces the related memory
- **extends**: This memory builds upon the related memory
- **derives**: This memory is derived from the related memory
</ResponseField>
<ResponseField name="version" type="number | null">
Relative version distance:
- **Negative values** for parents (-1 = direct parent, -2 = grandparent)
- **Positive values** for children (+1 = direct child, +2 = grandchild)
</ResponseField>
<ResponseField name="updatedAt" type="string">
When the related memory was last updated.
</ResponseField>
<ResponseField name="metadata" type="object | null" optional>
Metadata of the related memory.
</ResponseField>
</ResponseField>
<ResponseField name="documents" type="Array<Document>" optional>
**Associated documents**. Only included when `include.documents=true`.
<ResponseField name="documents[].id" type="string">
Document identifier.
</ResponseField>
<ResponseField name="documents[].title" type="string">
Document title.
</ResponseField>
<ResponseField name="documents[].type" type="string">
Document type.
</ResponseField>
<ResponseField name="documents[].metadata" type="object">
Document metadata.
</ResponseField>
<ResponseField name="documents[].createdAt" type="string">
Document creation timestamp.
</ResponseField>
<ResponseField name="documents[].updatedAt" type="string">
Document update timestamp.
</ResponseField>
</ResponseField>

View file

@ -1,523 +0,0 @@
---
title: "Update & Delete Memories"
description: "Safely update and delete memories with upsert patterns and idempotency"
icon: "delete"
---
Choose from direct updates, idempotent upserts, single deletions, and powerful bulk operations.
## Direct Updates
Update existing memories by their ID when you know the specific memory you want to modify.
- **Content changes** — Trigger full reprocessing (reindexing) through the pipeline. Response status is `"queued"`.
- **Metadata-only changes** — Update the document row only; no reindexing. Response status stays `"done"`. Use this when updating fields like `accepted`, `version`, or other filter metadata without changing the document content.
<CodeGroup>
```typescript Typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
// Update by memory ID
const updated = await client.documents.update('memory_id_123', {
content: 'Updated content here',
metadata: { version: 2, updated: true }
});
console.log(updated.status); // "queued" when content changed; "done" when metadata-only
console.log(updated.id); // "memory_id_123"
```
```python Python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
# Update by memory ID
updated = client.documents.update(
'memory_id_123',
content='Updated content here',
metadata={'version': 2, 'updated': True}
)
print(f"Status: {updated.status}") # "queued" when content changed; "done" when metadata-only
print(f"ID: {updated.id}") # "memory_id_123"
```
```bash cURL
curl -X PATCH "https://api.supermemory.ai/v3/documents/memory_id_123" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Updated content here",
"metadata": {"version": 2, "updated": true}
}'
```
</CodeGroup>
<Note>
**Metadata-only updates:** If you omit `content` or send the same content and only change `metadata` (e.g. `accepted: false` → `accepted: true`), the document is updated in place with no reindexing. Works with both internal `id` and `customId`—no special setup required.
</Note>
## Upserts Using customId
Use `customId` for idempotent operations where the same `customId` with `add()` will update existing memory instead of creating duplicates.
<CodeGroup>
```typescript Typescript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY!
});
const customId = 'user-note-001';
// First call creates memory
const created = await client.add({
content: 'Initial content',
customId: customId,
metadata: { version: 1 }
});
console.log('Created memory:', created.id);
// Second call with same customId updates existing
const updated = await client.add({
content: 'Updated content',
customId: customId, // Same customId = upsert
metadata: { version: 2 }
});
```
```python Python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
custom_id = 'user-note-001'
# First call creates memory
created = client.add(
content='Initial content',
custom_id=custom_id,
metadata={'version': 1}
)
print(f'Created memory: {created.id}')
# Second call with same customId updates existing
updated = client.add(
content='Updated content',
custom_id=custom_id, # Same customId = upsert
metadata={'version': 2}
)
print(f'Updated memory: {updated.id}')
print(f'Same memory? {created.id == updated.id}') # True
```
```bash cURL
# First call - creates memory
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Initial content",
"customId": "user-note-001",
"metadata": {"version": 1}
}'
# Response: {"id": "mem_abc123", "status": "queued", "customId": "user-note-001"}
# Second call - updates existing (same customId)
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Updated content",
"customId": "user-note-001",
"metadata": {"version": 2}
}'
# Response: {"id": "mem_abc123", "status": "queued", "customId": "user-note-001"}
# Note: Same ID returned - memory was updated, not created
```
</CodeGroup>
<Note>
The `customId` enables idempotency across all endpoints. The `memoryId` doesn't support idempotency, only the `customId` does.
</Note>
<Warning>
The `customId` can have a maximum length of 100 characters.
</Warning>
## Single Delete
Delete individual memories by their ID. This is a permanent hard delete with no recovery mechanism.
<CodeGroup>
```typescript Typescript
// Hard delete - permanently removes memory
await client.documents.delete('memory_id_123');
console.log('Memory deleted successfully');
```
```python Python
# Hard delete - permanently removes memory
client.documents.delete('memory_id_123')
print('Memory deleted successfully')
# Error handling for single delete
try:
client.documents.delete('memory_id_123')
print('Delete successful')
except NotFoundError:
print('Memory not found or already deleted')
except AuthenticationError:
print('Authentication failed')
except Exception as e:
print(f'Delete failed: {e}')
```
```bash cURL
curl -X DELETE "https://api.supermemory.ai/v3/documents/memory_id_123" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
# Response: 204 No Content (success)
# Response: 404 Not Found (memory doesn't exist)
```
</CodeGroup>
## Bulk Delete by IDs
Delete multiple memories at once by providing an array of memory IDs. Maximum of 100 IDs per request.
<CodeGroup>
```typescript Typescript
// Bulk delete by memory IDs
const result = await client.documents.deleteBulk({
ids: [
'memory_id_1',
'memory_id_2',
'memory_id_3',
'non_existent_id' // This will be reported in errors
]
});
console.log('Bulk delete result:', result);
// Output: {
// success: true,
// deletedCount: 3,
// errors: [
// { id: "non_existent_id", error: "Memory not found" }
// ]
// }
```
```python Python
# Bulk delete by memory IDs
result = client.documents.delete_bulk(
ids=[
'memory_id_1',
'memory_id_2',
'memory_id_3',
'non_existent_id' # This will be reported in errors
]
)
print(f'Bulk delete result: {result}')
# Output: {
# 'success': True,
# 'deletedCount': 3,
# 'errors': [
# {'id': 'non_existent_id', 'error': 'Memory not found'}
# ]
# }
```
```bash cURL
curl -X DELETE "https://api.supermemory.ai/v3/documents/bulk" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
"memory_id_1",
"memory_id_2",
"memory_id_3",
"non_existent_id"
]
}'
# Response: {
# "success": true,
# "deletedCount": 3,
# "errors": [
# {"id": "non_existent_id", "error": "Memory not found"}
# ]
# }
```
</CodeGroup>
## Bulk Delete by Container Tags
Delete all memories within specific container tags. This is useful for cleaning up entire projects or user data.
<CodeGroup>
```typescript Typescript
// Delete all memories in specific container tags
const result = await client.documents.deleteBulk({
containerTags: ['user-123', 'project-old', 'archived-content']
});
console.log('Bulk delete by tags result:', result);
// Output: {
// success: true,
// deletedCount: 45,
// containerTags: ["user-123", "project-old", "archived-content"]
// }
```
```python Python
# Delete all memories in specific container tags
result = client.documents.delete_bulk(
container_tags=['user-123', 'project-old', 'archived-content']
)
print(f'Bulk delete by tags result: {result}')
# Output: {
# 'success': True,
# 'deletedCount': 45,
# 'containerTags': ['user-123', 'project-old', 'archived-content']
# }
```
```bash cURL
curl -X DELETE "https://api.supermemory.ai/v3/documents/bulk" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"containerTags": ["user-123", "project-old", "archived-content"]
}'
# Response: {
# "success": true,
# "deletedCount": 45,
# "containerTags": ["user-123", "project-old", "archived-content"]
# }
```
</CodeGroup>
## Advanced Patterns
### Soft Delete Implementation
For applications requiring audit trails or recovery mechanisms, implement soft delete patterns using metadata:
<CodeGroup>
```typescript Typescript
// Soft delete pattern using metadata
await client.documents.update('memory_id', {
metadata: {
deleted: true,
deletedAt: new Date().toISOString(),
deletedBy: 'user_123'
}
});
// Filter out deleted memories in searches
const activeMemories = await client.documents.list({
filters: {
AND: [
{ key: "deleted", value: "true", negate: true }
]
}
});
console.log('Active memories:', activeMemories.memories.length);
```
```python Python
from datetime import datetime
# Soft delete pattern using metadata
client.documents.update(
'memory_id',
metadata={
'deleted': True,
'deletedAt': datetime.now().isoformat(),
'deletedBy': 'user_123'
}
)
# Filter out deleted memories
active_memories = client.documents.list(
filters={
"AND": [
{"key": "deleted", "value": "true", "negate": True}
]
}
)
print(f'Active memories: {len(active_memories.memories)}')
```
```bash cURL
# Soft delete using metadata
curl -X PATCH "https://api.supermemory.ai/v3/documents/memory_id" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"deleted": true,
"deletedAt": "2024-01-15T10:30:00Z",
"deletedBy": "user_123"
}
}'
# Response: {"id": "memory_id", "status": "queued"}
```
</CodeGroup>
### Batch Processing for Large Operations
<CodeGroup>
```typescript Typescript
// Batch delete large numbers of memories safely
async function batchDeleteMemories(memoryIds: string[], batchSize = 100) {
const results = [];
for (let i = 0; i < memoryIds.length; i += batchSize) {
const batch = memoryIds.slice(i, i + batchSize);
console.log(`Processing batch ${Math.floor(i/batchSize) + 1} of ${Math.ceil(memoryIds.length/batchSize)}`);
try {
const result = await client.documents.deleteBulk({ ids: batch });
results.push(result);
// Brief delay between batches to avoid rate limiting
if (i + batchSize < memoryIds.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
} catch (error) {
console.error(`Batch ${Math.floor(i/batchSize) + 1} failed:`, error);
results.push({ success: false, error: error.message, batch });
}
}
// Aggregate results
const totalDeleted = results
.filter(r => r.success)
.reduce((sum, r) => sum + (r.deletedCount || 0), 0);
console.log(`Total deleted: ${totalDeleted} out of ${memoryIds.length}`);
return { totalDeleted, results };
}
```
```python Python
import time
import math
def batch_delete_memories(memory_ids, batch_size=100):
"""Batch delete large numbers of memories safely"""
results = []
for i in range(0, len(memory_ids), batch_size):
batch = memory_ids[i:i + batch_size]
batch_num = i // batch_size + 1
total_batches = math.ceil(len(memory_ids) / batch_size)
print(f'Processing batch {batch_num} of {total_batches}')
try:
result = client.documents.delete_bulk(ids=batch)
results.append(result)
# Brief delay between batches to avoid rate limiting
if i + batch_size < len(memory_ids):
time.sleep(1)
except Exception as error:
print(f'Batch {batch_num} failed: {error}')
results.append({'success': False, 'error': str(error), 'batch': batch})
# Aggregate results
total_deleted = sum(
r.get('deletedCount', 0) for r in results if r.get('success')
)
print(f'Total deleted: {total_deleted} out of {len(memory_ids)}')
return {'totalDeleted': total_deleted, 'results': results}
```
```bash cURL
# Batch processing script example
#!/bin/bash
MEMORY_IDS=("id1" "id2" "id3") # Your memory IDs array
BATCH_SIZE=100
TOTAL_DELETED=0
# Process in batches
for ((i=0; i<${#MEMORY_IDS[@]}; i+=BATCH_SIZE)); do
batch=("${MEMORY_IDS[@]:i:BATCH_SIZE}")
batch_json=$(printf '%s\n' "${batch[@]}" | jq -R . | jq -s .)
echo "Processing batch $((i/BATCH_SIZE + 1))"
response=$(curl -s -X DELETE \
"https://api.supermemory.ai/v3/documents/bulk" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"ids\": $batch_json}")
deleted_count=$(echo "$response" | jq -r '.deletedCount // 0')
TOTAL_DELETED=$((TOTAL_DELETED + deleted_count))
echo "Batch deleted: $deleted_count memories"
sleep 1 # Rate limiting protection
done
echo "Total deleted: $TOTAL_DELETED memories"
```
</CodeGroup>
## Best Practices
### Update Operations
1. **Use customId for idempotent updates** - Prevents duplicate memories and enables safe retries
2. **Monitor processing status** - Content changes trigger full reprocessing; metadata-only updates do not reindex
3. **Handle metadata carefully** - Updates replace specified metadata keys
4. **Implement proper error handling** - Memory may be deleted between operations
### Delete Operations
1. **Hard delete is permanent** - No recovery mechanism exists
2. **Use bulk operations efficiently** - Maximum 100 IDs per bulk delete request
3. **Consider soft delete patterns** - Use metadata flags for recoverable deletion
4. **Batch large operations** - Avoid rate limits with proper batching
5. **Clean up application state** - Update your UI/cache after deletions

View file

@ -367,7 +367,7 @@ a vague one. `static` and `dynamic` are reserved and can't be used as bucket key
import { openai } from "@ai-sdk/openai"
// Profiles automatically injected
const model = withSupermemory(openai("gpt-4"), {
const model = withSupermemory(openai("gpt-4o"), {
containerTag: "user-123",
customId: "conv-1",
})

View file

@ -1,226 +0,0 @@
---
title: "Profile API"
description: "Endpoint details and response structure for user profiles"
sidebarTitle: "API Reference"
icon: "code"
---
## Endpoint
**`POST /v4/profile`**
Retrieves a user's profile, optionally combined with search results.
## Request
### Headers
| Header | Required | Description |
|--------|----------|-------------|
| `Authorization` | Yes | Bearer token with your API key |
| `Content-Type` | Yes | `application/json` |
### Body Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `containerTag` | string | Yes | The container tag (usually user ID) to get profiles for |
| `threshold` | float | No | Threshold for filtering search results. Only results with a score above this threshold will be included. |
| `q` | string | No | Optional search query to include search results with the profile |
## Response
```json
{
"profile": {
"static": [
"User is a software engineer",
"User specializes in Python and React",
"User prefers dark mode interfaces"
],
"dynamic": [
"User is working on Project Alpha",
"User recently started learning Rust",
"User is debugging authentication issues"
]
},
"searchResults": {
"results": [...], // Only if 'q' parameter was provided
"total": 15,
"timing": 45.2
}
}
```
### Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `profile.static` | string[] | Long-term, stable facts about the user |
| `profile.dynamic` | string[] | Recent context and temporary information |
| `searchResults` | object | Only present if `q` parameter was provided |
| `searchResults.results` | array | Matching memory results |
| `searchResults.total` | number | Total number of matches |
| `searchResults.timing` | number | Query execution time in milliseconds |
## Basic Request
<CodeGroup>
```typescript TypeScript
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTag: 'user_123'
})
});
const data = await response.json();
console.log("Static facts:", data.profile.static);
console.log("Dynamic context:", data.profile.dynamic);
```
```python Python
import requests
import os
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'containerTag': 'user_123'
}
)
data = response.json()
print("Static facts:", data['profile']['static'])
print("Dynamic context:", data['profile']['dynamic'])
```
```bash cURL
curl -X POST https://api.supermemory.ai/v4/profile \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"containerTag": "user_123"
}'
```
</CodeGroup>
## Profile with Search
Include a search query to get both profile data and relevant memories in one call:
<CodeGroup>
```typescript TypeScript
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTag: 'user_123',
q: 'deployment errors yesterday'
})
});
const data = await response.json();
// Profile data
const profile = data.profile;
// Search results (only present because we passed 'q')
const searchResults = data.searchResults?.results || [];
```
```python Python
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'containerTag': 'user_123',
'q': 'deployment errors yesterday'
}
)
data = response.json()
profile = data['profile']
search_results = data.get('searchResults', {}).get('results', [])
```
</CodeGroup>
## Profile with Threshold
Use the optional `threshold` parameter to filter search results by relevance score:
<CodeGroup>
```typescript TypeScript
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTag: 'user_123',
threshold: 0.7, // Only include results with score > 0.7
q: 'deployment errors yesterday'
})
});
const data = await response.json();
```
```python Python
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'containerTag': 'user_123',
'threshold': 0.7, # Only include results with score > 0.7
'q': 'deployment errors yesterday'
}
)
data = response.json()
```
</CodeGroup>
## Error Responses
| Status | Description |
|--------|-------------|
| `400` | Missing or invalid `containerTag` or `threshold` |
| `401` | Invalid or missing API key |
| `404` | Container not found |
| `500` | Internal server error |
## Rate Limits
Profile requests count toward your standard API rate limits. Since profiles are cached, repeated requests for the same user are efficient.
<Card title="See Examples" icon="laptop-code" href="/user-profiles/examples">
View complete integration examples for chat apps, support systems, and more
</Card>

View file

@ -1,370 +0,0 @@
---
title: "Profile Examples"
description: "Complete code examples for integrating user profiles"
sidebarTitle: "Examples"
icon: "laptop-code"
---
## Building a Personalized Prompt
The most common use case: inject profile data into your LLM's system prompt.
<CodeGroup>
```typescript TypeScript
async function handleChatMessage(userId: string, message: string) {
// Get user profile
const profileResponse = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ containerTag: userId })
});
const { profile } = await profileResponse.json();
// Build personalized system prompt
const systemPrompt = `You are assisting a user with the following context:
ABOUT THE USER:
${profile.static?.join('\n') || 'No profile information yet.'}
CURRENT CONTEXT:
${profile.dynamic?.join('\n') || 'No recent activity.'}
Provide responses personalized to their expertise level and preferences.`;
// Send to your LLM
const response = await llm.chat({
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: message }
]
});
return response;
}
```
```python Python
import requests
import os
async def handle_chat_message(user_id: str, message: str):
# Get user profile
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={'containerTag': user_id}
)
profile = response.json()['profile']
# Build personalized system prompt
static_facts = '\n'.join(profile.get('static', ['No profile information yet.']))
dynamic_context = '\n'.join(profile.get('dynamic', ['No recent activity.']))
system_prompt = f"""You are assisting a user with the following context:
ABOUT THE USER:
{static_facts}
CURRENT CONTEXT:
{dynamic_context}
Provide responses personalized to their expertise level and preferences."""
# Send to your LLM
llm_response = await llm.chat(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": message}
]
)
return llm_response
```
</CodeGroup>
## Full Context Mode
Combine profile data with query-specific search for comprehensive context:
<CodeGroup>
```typescript TypeScript
async function getFullContext(userId: string, userQuery: string) {
// Single call gets both profile and search results
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTag: userId,
q: userQuery // Include the user's query
})
});
const data = await response.json();
return {
// Static background about the user
userBackground: data.profile.static,
// Current activities and context
currentContext: data.profile.dynamic,
// Query-specific memories
relevantMemories: data.searchResults?.results || []
};
}
// Usage
const context = await getFullContext('user_123', 'deployment error last week');
const systemPrompt = `
User Background:
${context.userBackground.join('\n')}
Current Context:
${context.currentContext.join('\n')}
Relevant Information:
${context.relevantMemories.map(m => m.content).join('\n')}
`;
```
```python Python
async def get_full_context(user_id: str, user_query: str):
# Single call gets both profile and search results
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'containerTag': user_id,
'q': user_query # Include the user's query
}
)
data = response.json()
return {
'user_background': data['profile'].get('static', []),
'current_context': data['profile'].get('dynamic', []),
'relevant_memories': data.get('searchResults', {}).get('results', [])
}
# Usage
context = await get_full_context('user_123', 'deployment error last week')
system_prompt = f"""
User Background:
{chr(10).join(context['user_background'])}
Current Context:
{chr(10).join(context['current_context'])}
Relevant Information:
{chr(10).join(m['content'] for m in context['relevant_memories'])}
"""
```
</CodeGroup>
## Filtering with Threshold
Use the optional `threshold` parameter to filter search results by relevance score:
<CodeGroup>
```typescript TypeScript
async function getHighQualityContext(userId: string, userQuery: string) {
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTag: userId,
threshold: 0.7, // Only include high-confidence results
q: userQuery
})
});
const data = await response.json();
// Only highly relevant memories are included
return data;
}
```
```python Python
async def get_high_quality_context(user_id: str, user_query: str):
response = requests.post(
'https://api.supermemory.ai/v4/profile',
headers={
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'containerTag': user_id,
'threshold': 0.7, # Only include high-confidence results
'q': user_query
}
)
data = response.json()
# Only highly relevant memories are included
return data
```
</CodeGroup>
## Separate Profile and Search
For more control, you can call profile and search endpoints separately:
```typescript TypeScript
async function advancedContext(userId: string, query: string) {
// Parallel requests for profile and search
const [profileRes, searchRes] = await Promise.all([
fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ containerTag: userId })
}),
fetch('https://api.supermemory.ai/v3/search', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
q: query,
containerTag: userId,
limit: 5
})
})
]);
const profile = await profileRes.json();
const search = await searchRes.json();
return { profile: profile.profile, searchResults: search.results };
}
```
## Express.js Middleware
Add profile context to all authenticated requests:
```typescript TypeScript
import express from 'express';
// Middleware to fetch user profile
async function withUserProfile(req, res, next) {
if (!req.user?.id) {
return next();
}
try {
const response = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ containerTag: req.user.id })
});
req.userProfile = await response.json();
} catch (error) {
console.error('Failed to fetch profile:', error);
req.userProfile = null;
}
next();
}
const app = express();
// Apply to all routes
app.use(withUserProfile);
app.post('/chat', async (req, res) => {
const { message } = req.body;
// Profile is automatically available
const profile = req.userProfile?.profile;
// Use in your LLM call...
});
```
## Next.js API Route
```typescript TypeScript
// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const { userId, message } = await req.json();
// Fetch profile
const profileRes = await fetch('https://api.supermemory.ai/v4/profile', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ containerTag: userId })
});
const { profile } = await profileRes.json();
// Build context and call your LLM...
const response = await generateResponse(message, profile);
return NextResponse.json({ response });
}
```
## AI SDK Integration
For the cleanest integration, use the Supermemory AI SDK middleware:
```typescript TypeScript
import { generateText } from "ai"
import { withSupermemory } from "@supermemory/tools/ai-sdk"
import { openai } from "@ai-sdk/openai"
// Simple setup - profiles automatically injected
const model = withSupermemory(openai("gpt-4"), {
containerTag: "user-123",
customId: "conv-1",
})
const result = await generateText({
model,
messages: [{ role: "user", content: "Help me with my current project" }]
})
// Model automatically has access to user's profile!
```
<Card title="AI SDK User Profiles" icon="triangle" href="/integrations/ai-sdk">
Learn more about automatic profile injection with the AI SDK
</Card>

View file

@ -1,135 +0,0 @@
---
title: "User Profiles"
description: "Automatically maintained user context that gives your LLMs instant, comprehensive knowledge about each user"
sidebarTitle: "Overview"
icon: "user"
---
User profiles are **automatically maintained collections of facts about your users** that Supermemory builds from all their interactions and content. Think of it as a persistent "about me" document that's always up-to-date and instantly accessible.
<CardGroup cols={2}>
<Card title="Instant Context" icon="bolt">
No search queries needed - comprehensive user information is always ready
</Card>
<Card title="Auto-Updated" icon="rotate">
Profiles update automatically as users interact with your system
</Card>
<Card title="Two-Tier Structure" icon="layer-group">
Static facts + dynamic context for perfect personalization
</Card>
<Card title="Zero Setup" icon="wand-magic-sparkles">
Just ingest content normally - profiles build themselves
</Card>
</CardGroup>
## Why Profiles?
Traditional memory systems rely entirely on search, which has fundamental limitations:
| Problem | With Search Only | With Profiles |
|---------|-----------------|---------------|
| **Context retrieval** | 3-5 search queries | 1 profile call |
| **Response time** | 200-500ms | 50-100ms |
| **Consistency** | Varies by search quality | Always comprehensive |
| **Basic user info** | Requires specific queries | Always available |
**Search is too narrow**: When you search for "project updates", you miss that the user prefers bullet points, works in PST timezone, and uses specific terminology.
**Profiles provide the foundation**: Instead of repeatedly searching for basic context, profiles give your LLM a complete picture of who the user is.
## Static vs Dynamic
Profiles intelligently separate two types of information:
![](/images/static-dynamic-profile.png)
### Static Profile
Long-term, stable facts that rarely change:
- "Sarah Chen is a senior software engineer at TechCorp"
- "Sarah specializes in distributed systems and Kubernetes"
- "Sarah has a PhD in Computer Science from MIT"
- "Sarah prefers technical documentation over video tutorials"
### Dynamic Profile
Recent context and temporary states:
- "Sarah is currently migrating the payment service to microservices"
- "Sarah recently started learning Rust for a side project"
- "Sarah is preparing for a conference talk next month"
- "Sarah is debugging a memory leak in the authentication service"
## How It Works
Profiles are **automatically built and maintained** through Supermemory's ingestion pipeline:
<Steps>
<Step title="Content Ingestion">
When users add documents, chat, or any content to Supermemory, it goes through the standard ingestion workflow.
</Step>
<Step title="Intelligence Extraction">
AI analyzes the content to extract not just memories, but also facts about the user themselves.
</Step>
<Step title="Profile Operations">
The system generates profile operations (add, update, or remove facts) based on the new information.
</Step>
<Step title="Automatic Updates">
Profiles are updated in real-time, ensuring they always reflect the latest information.
</Step>
</Steps>
<Note>
You don't need to manually manage profiles - they build themselves as users interact with your system.
</Note>
## Profiles + Search
Profiles don't replace search - they complement it:
<Steps>
<Step title="Profile provides foundation">
The user's profile gives your LLM comprehensive background context about who they are, what they know, and what they're working on.
</Step>
<Step title="Search adds specificity">
When you need specific information (like "error in deployment yesterday"), search finds those exact memories.
</Step>
<Step title="Combined for perfect context">
Your LLM gets both the broad understanding from profiles AND the specific details from search.
</Step>
</Steps>
### Example
User asks: **"Can you help me debug this?"**
**Without profiles**: The LLM has no context about the user's expertise level, current projects, or debugging preferences.
**With profiles**: The LLM knows:
- The user is a senior engineer (adjust technical level)
- They're working on a payment service migration (likely context)
- They prefer command-line tools over GUIs (tool suggestions)
- They recently had issues with memory leaks (possible connection)
## Next Steps
<CardGroup cols={2}>
<Card title="API Reference" icon="code" href="/user-profiles/api">
Learn how to fetch and use profiles via the API
</Card>
<Card title="Code Examples" icon="laptop-code" href="/user-profiles/examples">
See complete integration examples
</Card>
<Card title="AI SDK Integration" icon="triangle" href="/integrations/ai-sdk">
Use the AI SDK for automatic profile injection
</Card>
<Card title="Use Cases" icon="lightbulb" href="/user-profiles/use-cases">
Common patterns and applications
</Card>
</CardGroup>

View file

@ -1,153 +0,0 @@
---
title: "Profile Use Cases"
description: "Common patterns and applications for user profiles"
sidebarTitle: "Use Cases"
icon: "lightbulb"
---
## Personalized AI Assistants
The most common use case: building AI assistants that truly know your users.
**What profiles provide:**
- User's expertise level (adjust technical depth)
- Communication preferences (brief vs detailed, formal vs casual)
- Tools and technologies they use
- Current projects and priorities
**Example prompt enhancement:**
```typescript
const systemPrompt = `You are assisting ${userName}.
Their background:
${profile.static.join('\n')}
Current focus:
${profile.dynamic.join('\n')}
Adjust your responses to match their expertise level and preferences.`;
```
**Result:** An assistant that explains React hooks differently to a junior developer vs a senior architect.
## Customer Support Systems
Give support agents (or AI) instant context about customers.
**What profiles provide:**
- Customer's product usage history
- Previous issues and resolutions
- Preferred communication channels
- Technical proficiency level
**Benefits:**
- No more "let me look up your account"
- Agents immediately understand customer context
- AI support can reference past interactions naturally
```typescript
// Support agent dashboard
async function loadCustomerContext(customerId: string) {
const { profile } = await getProfile(customerId);
return {
summary: profile.static, // Long-term customer info
recentIssues: profile.dynamic // Current tickets, recent problems
};
}
```
## Educational Platforms
Adapt learning content to each student's level and progress.
**What profiles provide:**
- Learning style preferences
- Completed courses and topics
- Areas of strength and weakness
- Current learning goals
**Example adaptation:**
```typescript
// Profile might contain:
// static: ["Visual learner", "Strong in algebra, struggles with geometry"]
// dynamic: ["Currently studying calculus", "Preparing for AP exam"]
const tutorPrompt = `You're helping a student with:
${profile.static.join('\n')}
Current focus: ${profile.dynamic.join('\n')}
Adapt explanations to their learning style and build on their strengths.`;
```
## Development Tools
IDE assistants and coding tools that understand your codebase and habits.
**What profiles provide:**
- Preferred languages and frameworks
- Coding style and conventions
- Current project context
- Frequently used patterns
**Example:**
```typescript
// Profile for a developer:
// static: ["Prefers TypeScript", "Uses functional patterns", "Senior engineer"]
// dynamic: ["Working on auth refactor", "Recently learning Rust"]
// Code assistant knows to:
// - Suggest TypeScript solutions
// - Use functional patterns in examples
// - Provide senior-level explanations
// - Connect suggestions to the auth refactor when relevant
```
## Knowledge Base Assistants
Internal tools that understand each employee's role and responsibilities.
**What profiles provide:**
- Department and role
- Projects they're involved in
- Access level and permissions context
- Areas of expertise (for routing questions)
**Example:**
```typescript
// HR assistant that knows:
// - Employee's team and manager
// - Their location/timezone
// - Recent PTO requests
// - Benefits elections
const response = await hrAssistant.answer(
"When is my next performance review?",
{ profile: employeeProfile }
);
// Can answer with specific dates, manager name, etc.
```
## E-commerce Recommendations
Personalized shopping experiences beyond basic recommendation engines.
**What profiles provide:**
- Style preferences
- Size information
- Past purchases and returns
- Budget range
- Occasions they shop for
**Example conversation:**
```
User: "I need something for a wedding next month"
// Profile knows: prefers classic styles, size M, budget-conscious,
// previously bought navy suits

View file

@ -171,17 +171,17 @@ import { supermemoryTools } from '@supermemory/tools/ai-sdk'
// Option 1: Agent tools (recommended for agentic flows)
const result = await streamText({
model: anthropic('claude-3-5-sonnet-20241022'),
model: anthropic('claude-sonnet-4-5'),
prompt: userMessage,
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY, {
containerTag: userId // singular string — never an array
containerTags: [userId] // the tools config takes an array; API bodies use singular containerTag
})
})
// Agent gets searchMemories, addMemory, fetchMemory tools
// Option 2: Profile middleware (automatic context injection)
import { withSupermemory } from '@supermemory/tools/ai-sdk'
const modelWithMemory = withSupermemory(anthropic('claude-3-5-sonnet-20241022'), {
const modelWithMemory = withSupermemory(anthropic('claude-sonnet-4-5'), {
containerTag: userId,
customId: 'conversation-1',
})
@ -236,15 +236,14 @@ import Supermemory from 'supermemory'
const client = new Supermemory()
// Search for relevant memories
const results = await client.search({
const results = await client.search.memories({
q: userMessage,
containerTag: userId,
searchMode: 'hybrid', // Searches memories + document chunks
limit: 5
})
// Build context
const context = results.results.map(r => r.memory || r.chunk).join('\n')
const context = results.results.map(r => r.memory).join('\n')
// Send to LLM with context
const messages = [

View file

@ -1,64 +0,0 @@
---
title: "Integrate supermemory in your Zapier workflows"
sidebarTitle: "Zapier"
description: "Learn how to use the code block to integrate supermemory with Zapier and add memory to your automations."
---
With Supermemory you can now easily add memory to your Zapier workflow steps. Here's how:
## Prerequisites
- A Supermemory API Key. Get yours [here](https://console.supermemory.ai)
## Step-by-step tutorial
For this tutorial, we're building a simple flow that adds incoming emails in Gmail to Supermemory.
<Steps>
<Step title="Make a flow">
Open your Zapier account and click on 'Zap' to make a new automation.
![make a zap - annotated](/images/make-zap.png)
</Step>
<Step title="Add Gmail node">
Add a new Gmail node that gets triggered on every new email. Connect to your Google account.
![add gmail](/images/add-gmail-node-zapier.png)
</Step>
<Step title="Add code block">
Now, add a new 'Code by Zapier' block. Set it up to run Python.
In the **Input Data** section, map the content field to the Gmail raw snippet.
![](/images/map-content-to-gmail.png)
</Step>
<Step title="Integrate Supermemory">
Since we're ingesting data here, we'll use the add documents endpoint.
Add the following code block:
```python
import requests
url = "https://api.supermemory.ai/v3/documents"
payload = { "content": inputData['content'], "containerTag": "gmail" }
headers = {
"Authorization": "Bearer YOUR_SM_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
The `inputData['content']` field maps to the Gmail content fetched from Zapier.
![](/images/zapier-output.png)
</Step>
</Steps>
<Note>
Sometimes Zapier might show an error on the first test run. It usually works right after. Weird bug, we know.
</Note>
You can perform other operations like search, filtering, user profiles, etc., by using other Supermemory API endpoints which can be found in our API Reference tab.