docs: restructure documentation site and update integration UI (#1331)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
26
README.md
|
|
@ -134,13 +134,23 @@ You can find them here:
|
|||
- OpenCode plugin: https://github.com/supermemoryai/opencode-supermemory
|
||||
- Hermes agent (Supermemory memory provider): https://github.com/NousResearch/hermes-agent
|
||||
|
||||
### MCP - Quick install
|
||||
### MCP
|
||||
|
||||
```bash
|
||||
npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client claude --oauth=yes
|
||||
Server URL:
|
||||
|
||||
```text
|
||||
https://mcp.supermemory.ai/mcp
|
||||
```
|
||||
|
||||
Replace `claude` with your client: `cursor`, `windsurf`, `vscode`, etc.
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory": {
|
||||
"url": "https://mcp.supermemory.ai/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Read more about our MCP here - https://supermemory.ai/docs/supermemory-mcp/mcp
|
||||
|
||||
|
|
@ -271,7 +281,7 @@ const agent = new Agent(withSupermemory(config, "user-123", { mode: "full" }));
|
|||
|
||||
```typescript
|
||||
// Hybrid (default) — RAG + Memory in one query
|
||||
const results = await client.search.memories({
|
||||
const results = await client.search({
|
||||
q: "how do I deploy?",
|
||||
containerTag: "user_123",
|
||||
searchMode: "hybrid",
|
||||
|
|
@ -279,7 +289,7 @@ const results = await client.search.memories({
|
|||
// Returns deployment docs (RAG) + user's deploy preferences (Memory)
|
||||
|
||||
// Memories only
|
||||
const results = await client.search.memories({
|
||||
const results = await client.search({
|
||||
q: "user preferences",
|
||||
containerTag: "user_123",
|
||||
searchMode: "memories",
|
||||
|
|
@ -313,8 +323,8 @@ Real-time webhooks. Documents automatically processed, chunked, and searchable.
|
|||
|---|---|
|
||||
| `client.add()` | Store content — text, conversations, URLs, HTML |
|
||||
| `client.profile()` | User profile + optional search in one call |
|
||||
| `client.search.memories()` | Hybrid search across memories and documents |
|
||||
| `client.search.documents()` | Document search with metadata filters |
|
||||
| `client.search()` | Hybrid search across memories and documents (`searchMode`) |
|
||||
| `client.search.documents()` | Document search with metadata filters (legacy v3 response shape) |
|
||||
| `client.documents.uploadFile()` | Upload PDFs, images, videos, code |
|
||||
| `client.documents.list()` | List and filter documents |
|
||||
| `client.settings.update()` | Configure memory extraction and chunking |
|
||||
|
|
|
|||
|
|
@ -110,13 +110,23 @@ Supermemory 已经为 Claude Code、OpenCode、OpenClaw、Hermes 提供了开箱
|
|||
- OpenCode 插件:https://github.com/supermemoryai/opencode-supermemory
|
||||
- Hermes agent(Supermemory 作为记忆 provider):https://github.com/NousResearch/hermes-agent
|
||||
|
||||
### MCP——一键安装
|
||||
### MCP
|
||||
|
||||
```bash
|
||||
npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client claude --oauth=yes
|
||||
服务地址:
|
||||
|
||||
```text
|
||||
https://mcp.supermemory.ai/mcp
|
||||
```
|
||||
|
||||
把 `claude` 换成你用的客户端即可:`cursor`、`windsurf`、`vscode` 等等。
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory": {
|
||||
"url": "https://mcp.supermemory.ai/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多 MCP 细节见:https://supermemory.ai/docs/supermemory-mcp/mcp
|
||||
|
||||
|
|
@ -247,7 +257,7 @@ const agent = new Agent(withSupermemory(config, "user-123", { mode: "full" }));
|
|||
|
||||
```typescript
|
||||
// 混合检索(默认)——一次查询同时跑 RAG 和记忆
|
||||
const results = await client.search.memories({
|
||||
const results = await client.search({
|
||||
q: "how do I deploy?",
|
||||
containerTag: "user_123",
|
||||
searchMode: "hybrid",
|
||||
|
|
@ -255,7 +265,7 @@ const results = await client.search.memories({
|
|||
// 返回部署文档(RAG)+ 该用户的部署偏好(记忆)
|
||||
|
||||
// 只查记忆
|
||||
const results = await client.search.memories({
|
||||
const results = await client.search({
|
||||
q: "user preferences",
|
||||
containerTag: "user_123",
|
||||
searchMode: "memories",
|
||||
|
|
@ -289,8 +299,8 @@ const { profile } = await client.profile({ containerTag: "user_123" });
|
|||
|---|---|
|
||||
| `client.add()` | 存储内容——文本、对话、URL、HTML |
|
||||
| `client.profile()` | 一次调用返回用户画像 + 可选检索 |
|
||||
| `client.search.memories()` | 跨记忆和文档的混合检索 |
|
||||
| `client.search.documents()` | 带元数据过滤的文档检索 |
|
||||
| `client.search()` | 跨记忆和文档的混合检索(`searchMode`) |
|
||||
| `client.search.documents()` | 带元数据过滤的文档检索(旧版 v3 响应格式) |
|
||||
| `client.documents.uploadFile()` | 上传 PDF、图片、视频、代码 |
|
||||
| `client.documents.list()` | 列出和筛选文档 |
|
||||
| `client.settings.update()` | 配置记忆抽取与切分策略 |
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"] }
|
||||
```
|
||||
248
apps/docs/agents-and-mcp.mdx
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
---
|
||||
title: "Agents, skills and MCP"
|
||||
description: "Set up coding agents to integrate Supermemory — CLI, skill, and docs MCP."
|
||||
sidebarTitle: "Agents, skills and MCP"
|
||||
icon: "bot"
|
||||
---
|
||||
|
||||
This page is for **building with Supermemory** using coding agents: scaffolding a project, following the real API, and searching product docs.
|
||||
|
||||
It is **not** the consumer Memory MCP (give Claude/Cursor long-term memory about *you*). That is a separate product surface — see [Supermemory MCP](/supermemory-mcp/mcp).
|
||||
|
||||
| Path | How | For |
|
||||
|---|---|---|
|
||||
| **CLI** | `npx supermemory` | Setup, smoke tests, agent-driven integration |
|
||||
| **Skill** | `npx skills add … --skill supermemory` | Teach the agent the real API surface |
|
||||
| **Docs MCP** | `https://supermemory.ai/docs/mcp` | Search these docs while the agent codes |
|
||||
|
||||
## CLI
|
||||
|
||||
Agents (and humans) can set things up from the terminal easily using our CLI
|
||||
|
||||
```bash
|
||||
npx supermemory
|
||||
```
|
||||
|
||||
Useful for coding agents:
|
||||
|
||||
```bash
|
||||
npx supermemory setup # detect project, launch/print integration flow
|
||||
npx supermemory setup --prompt # print integration prompt only
|
||||
npx supermemory setup --json # machine-readable output
|
||||
npx supermemory help --json # agent-readable command catalog
|
||||
npx supermemory help --all
|
||||
```
|
||||
|
||||
Also available for smoke tests against your key: `add`, `search`, `profile`, `docs`, `tags`, `config`, `whoami`. Auth via first-run credentials or `SUPERMEMORY_API_KEY`.
|
||||
|
||||
```bash
|
||||
npx supermemory add "User prefers TypeScript" --tag user_123
|
||||
npx supermemory search "language preference" --tag user_123
|
||||
npx supermemory profile --tag user_123
|
||||
```
|
||||
|
||||
## Skill
|
||||
|
||||
Install the official skill so the agent uses the real endpoints, auth, and `containerTag` rules instead of hallucinating APIs:
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/supermemoryai/skills --skill supermemory
|
||||
```
|
||||
|
||||
Source: [github.com/supermemoryai/skills](https://github.com/supermemoryai/skills).
|
||||
|
||||
<Tip>
|
||||
Best combo for coding agents: **skill** + **docs MCP** + **`npx supermemory setup`**.
|
||||
</Tip>
|
||||
|
||||
## Docs MCP
|
||||
|
||||
Remote MCP that lets the agent **search Supermemory documentation** while it implements an integration.
|
||||
|
||||
Server URL:
|
||||
|
||||
```text
|
||||
https://supermemory.ai/docs/mcp
|
||||
```
|
||||
|
||||
### Setup by client
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Cursor">
|
||||
Add to `~/.cursor/mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory-docs": {
|
||||
"url": "https://supermemory.ai/docs/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Claude Code">
|
||||
```bash
|
||||
claude mcp add --transport http supermemory-docs https://supermemory.ai/docs/mcp
|
||||
```
|
||||
|
||||
Or project `.mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory-docs": {
|
||||
"type": "http",
|
||||
"url": "https://supermemory.ai/docs/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Codex">
|
||||
```bash
|
||||
codex mcp add supermemory-docs --url https://supermemory.ai/docs/mcp
|
||||
```
|
||||
|
||||
Or `~/.codex/config.toml`:
|
||||
|
||||
```toml
|
||||
[mcp_servers.supermemory-docs]
|
||||
url = "https://supermemory.ai/docs/mcp"
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="OpenCode">
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"supermemory-docs": {
|
||||
"type": "remote",
|
||||
"url": "https://supermemory.ai/docs/mcp",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="VS Code">
|
||||
Add to `.vscode/mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"supermemory-docs": {
|
||||
"type": "http",
|
||||
"url": "https://supermemory.ai/docs/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Other">
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory-docs": {
|
||||
"url": "https://supermemory.ai/docs/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Stdio-only clients can proxy:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"supermemory-docs": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-remote", "https://supermemory.ai/docs/mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Starter prompt (docs + setup)
|
||||
|
||||
```text
|
||||
You are integrating Supermemory into my app.
|
||||
|
||||
- Use the supermemory-docs MCP (or https://supermemory.ai/docs/llms.txt) before inventing endpoints.
|
||||
- Prefer `npx supermemory setup` / the supermemory skill for correct auth, containerTag, and SDK usage.
|
||||
- Canonical writes: POST /v3/documents · search: POST /v4/search · profile: POST /v4/profile
|
||||
- Auth: Authorization: Bearer $SUPERMEMORY_API_KEY only
|
||||
- Always scope with containerTag (singular) on write and search
|
||||
- For demos use dreaming: "instant" when memories must be ready right after status done
|
||||
```
|
||||
|
||||
### Integrate prompt (optional)
|
||||
|
||||
If the skill is not installed, paste a fuller prompt so the agent asks the right product questions:
|
||||
|
||||
<Accordion title="Copy full integration prompt" icon="copy">
|
||||
````
|
||||
You are integrating Supermemory into my application. Supermemory provides user memory, semantic search, and automatic knowledge extraction for AI applications.
|
||||
|
||||
Note: You can always reference the documentation by using the **supermemory-docs MCP** or content on **supermemory.ai/docs**. Prefer `npx supermemory setup` / `npx supermemory help --json` when scaffolding.
|
||||
|
||||
CANONICAL API SURFACE (use these, nothing else):
|
||||
|
||||
- Auth header: `Authorization: Bearer $SUPERMEMORY_API_KEY` — the only supported auth header
|
||||
- Write content: POST https://api.supermemory.ai/v3/documents
|
||||
- Search: POST https://api.supermemory.ai/v4/search
|
||||
- Profile + search: POST https://api.supermemory.ai/v4/profile
|
||||
- Settings: PATCH https://api.supermemory.ai/v3/settings
|
||||
- Scoping: `containerTag` (singular string) in the JSON body — never in a header
|
||||
- SDK: `client.add()`, `client.search()`, `client.profile()`
|
||||
|
||||
DO NOT USE — deprecated, undocumented, or fabricated:
|
||||
|
||||
- Endpoints: /v1/anything, /v3/memories, /v3/search (use /v3/documents and /v4/search)
|
||||
- Headers: x-supermemory-api-key, x-api-key, x-sm-user-id (for API auth)
|
||||
- Body keys: containerTags (plural) on writes as the only scope, userId, spaces
|
||||
- Mixing: `rerank` and `rewriteQuery` on /v4/search only — never on /v3/search
|
||||
|
||||
SCOPING IS LOAD-BEARING. Every write and every search MUST include `containerTag`.
|
||||
|
||||
Prefer for tutorials:
|
||||
- Ingest conversations with customId + dreaming: "instant" when you need memories immediately
|
||||
- Wait until document status is done before search
|
||||
- search with searchMode: "documents" for RAG, search (+ relatedMemories) for the graph, profile for always-on context
|
||||
|
||||
STEP 1: Ask what I'm building, integration style (AI SDK / OpenAI / Direct SDK / API), data model (user/org/both), profiles yes/no.
|
||||
STEP 2: Install supermemory (npm/pip), set SUPERMEMORY_API_KEY from https://console.supermemory.ai
|
||||
STEP 3: Generate complete working code.
|
||||
|
||||
DOCS: https://supermemory.ai/docs
|
||||
````
|
||||
</Accordion>
|
||||
|
||||
## Memory MCP (different product)
|
||||
|
||||
Want your **assistant** to remember you across chats (save/recall/profile in Claude, Cursor, etc.)? That is the **Memory MCP**, not the docs MCP:
|
||||
|
||||
→ [Supermemory MCP](/supermemory-mcp/mcp)
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstart" icon="play" href="/quickstart">
|
||||
Conversation + document ingest, RAG, graph, profile, harness.
|
||||
</Card>
|
||||
<Card title="Memory MCP" icon="brain-circuit" href="/supermemory-mcp/mcp">
|
||||
Persistent memory for assistants — separate from docs setup.
|
||||
</Card>
|
||||
<Card title="Plugins" icon="puzzle" href="/integrations/openclaw">
|
||||
Claude Code, OpenClaw, Codex, Hermes, and more.
|
||||
</Card>
|
||||
<Card title="AI SDK" icon="triangle" href="/integrations/ai-sdk">
|
||||
withSupermemory and memory tools in app code.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,357 +0,0 @@
|
|||
---
|
||||
title: "AI SDK Examples"
|
||||
description: "Complete examples showing how to use Supermemory with Vercel AI SDK"
|
||||
sidebarTitle: "Examples"
|
||||
---
|
||||
|
||||
This page provides comprehensive examples of using Supermemory with the Vercel AI SDK, covering Memory Tools and User Profiles approaches.
|
||||
|
||||
## Personal Assistant with Memory Tools
|
||||
|
||||
Build an AI assistant that remembers user preferences and past interactions:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Next.js API Route
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
|
||||
system: `You are a helpful personal assistant. When users share information about themselves,
|
||||
remember it using the addMemory tool. When they ask questions, search your memories to provide
|
||||
personalized responses. Always be proactive about remembering important details.`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Client Component
|
||||
'use client'
|
||||
|
||||
import { useChat } from 'ai/react'
|
||||
|
||||
export default function PersonalAssistant() {
|
||||
const { messages, input, handleInputChange, handleSubmit } = useChat()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen max-w-2xl mx-auto p-4">
|
||||
<div className="flex-1 overflow-y-auto space-y-4">
|
||||
{messages.map((message) => (
|
||||
<div
|
||||
key={message.id}
|
||||
className={`p-4 rounded-lg ${
|
||||
message.role === 'user' ? 'bg-blue-100 ml-auto' : 'bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<p>{message.content}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="mt-4">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Tell me about yourself or ask me anything..."
|
||||
className="w-full p-2 border rounded"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
**Example conversation:**
|
||||
- User: "I'm allergic to peanuts and I love Italian food"
|
||||
- AI: *Uses addMemory tool* "I've remembered that you're allergic to peanuts and love Italian food!"
|
||||
- User: "Suggest a restaurant for dinner"
|
||||
- AI: *Uses searchMemories tool* "Based on what I know about you, I'd recommend an Italian restaurant that's peanut-free..."
|
||||
|
||||
## Customer Support with Context
|
||||
|
||||
Build a customer support system that remembers customer history:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, customerId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [customerId]
|
||||
}),
|
||||
system: `You are a customer support agent. Before responding to any query:
|
||||
1. Search for the customer's previous interactions and issues
|
||||
2. Remember any new information shared in this conversation
|
||||
3. Provide personalized help based on their history
|
||||
4. Always be empathetic and solution-focused`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Multi-User Learning Assistant
|
||||
|
||||
Build an assistant that learns from multiple users but keeps data separate:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, userId, courseId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-haiku-20240307'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [userId]
|
||||
}),
|
||||
system: `You are a learning assistant. Help students with their coursework by:
|
||||
1. Remembering their learning progress and struggles
|
||||
2. Searching for relevant information from their past sessions
|
||||
3. Providing personalized explanations based on their learning style
|
||||
4. Tracking topics they've mastered vs topics they need more help with`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Research Assistant with File Processing
|
||||
|
||||
Combine file upload with memory tools for research assistance:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript API Route
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, projectId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [projectId]
|
||||
}),
|
||||
system: `You are a research assistant. You can:
|
||||
1. Search through uploaded research papers and documents
|
||||
2. Remember key findings and insights from conversations
|
||||
3. Help synthesize information across multiple sources
|
||||
4. Track research progress and important discoveries`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
```typescript File Upload Handler
|
||||
import { addMemory } from '@supermemory/tools'
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const formData = await request.formData()
|
||||
const file = formData.get('file') as File
|
||||
const projectId = formData.get('projectId') as string
|
||||
|
||||
// Upload file and add to memory
|
||||
const memory = await addMemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!,
|
||||
content: file, // Supermemory handles file processing
|
||||
title: file.name,
|
||||
headers: {
|
||||
'x-sm-conversation-id': projectId
|
||||
}
|
||||
})
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "Document uploaded and processed for research",
|
||||
memoryId: memory.id
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Code Assistant with Project Memory
|
||||
|
||||
Create a coding assistant that remembers your codebase and preferences:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import {
|
||||
supermemoryTools,
|
||||
searchMemoriesTool,
|
||||
addMemoryTool
|
||||
} from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, repositoryId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
messages,
|
||||
tools: {
|
||||
// Use individual tools for more control
|
||||
searchMemories: searchMemoriesTool(process.env.SUPERMEMORY_API_KEY!, {
|
||||
headers: {
|
||||
'x-sm-conversation-id': `repo-${repositoryId}`
|
||||
}
|
||||
}),
|
||||
addMemory: addMemoryTool(process.env.SUPERMEMORY_API_KEY!, {
|
||||
headers: {
|
||||
'x-sm-conversation-id': `repo-${repositoryId}`
|
||||
}
|
||||
}),
|
||||
// Add custom tools
|
||||
executeCode: {
|
||||
description: 'Execute code in a sandbox environment',
|
||||
parameters: z.object({
|
||||
code: z.string(),
|
||||
language: z.string()
|
||||
}),
|
||||
execute: async ({ code, language }) => {
|
||||
// Your code execution logic
|
||||
return { result: "Code executed successfully" }
|
||||
}
|
||||
}
|
||||
},
|
||||
system: `You are a coding assistant with memory. You can:
|
||||
1. Remember coding patterns and preferences from past conversations
|
||||
2. Search through previous code examples and solutions
|
||||
3. Track project architecture and design decisions
|
||||
4. Learn from debugging sessions and common issues`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced: Custom Tool Integration
|
||||
|
||||
Combine Supermemory tools with your own custom tools:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
import { z } from 'zod'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
// Custom tool for calendar integration
|
||||
const calendarTool = {
|
||||
description: 'Create calendar events',
|
||||
parameters: z.object({
|
||||
title: z.string(),
|
||||
date: z.string(),
|
||||
duration: z.number()
|
||||
}),
|
||||
execute: async ({ title, date, duration }) => {
|
||||
// Your calendar API integration
|
||||
return { eventId: "cal_123", message: "Event created" }
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: {
|
||||
// Spread Supermemory tools
|
||||
...supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
|
||||
// Add custom tools
|
||||
createEvent: calendarTool,
|
||||
},
|
||||
system: `You are a personal assistant that can remember information and
|
||||
manage calendars. When users mention events or appointments:
|
||||
1. Remember the details using addMemory
|
||||
2. Create calendar events using createEvent
|
||||
3. Search for conflicts using searchMemories`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
For all examples, ensure you have these environment variables:
|
||||
|
||||
```bash .env.local
|
||||
SUPERMEMORY_API_KEY=your_supermemory_key
|
||||
OPENAI_API_KEY=your_openai_key
|
||||
ANTHROPIC_API_KEY=your_anthropic_key
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Memory Tools
|
||||
- Use descriptive memory content for better search results
|
||||
- Include context in your system prompts about when to use each tool
|
||||
- Use project headers to separate different use cases
|
||||
- Implement error handling for tool failures
|
||||
|
||||
### General Tips
|
||||
- Start with simple examples and gradually add complexity
|
||||
- Use the search functionality to avoid duplicate memories
|
||||
- Implement proper authentication for production use
|
||||
- Consider rate limiting for high-volume applications
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory API" icon="database" href="/memory-api/overview">
|
||||
Advanced memory management with full API control
|
||||
</Card>
|
||||
|
||||
<Card title="User Profiles" icon="user" href="/user-profiles">
|
||||
Automatic personalization with user profiles
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: "NPM link"
|
||||
url: "https://www.npmjs.com/package/@supermemory/tools"
|
||||
icon: npm
|
||||
---
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
17
apps/docs/api-reference/connections.mdx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
title: "Connections"
|
||||
sidebarTitle: "Overview"
|
||||
description: "External connectors — create, configure, sync, and manage resources."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
Connections pull content from Notion, Google Drive, Gmail, OneDrive, S3, GitHub, and more.
|
||||
|
||||
| Area | Endpoints |
|
||||
| --- | --- |
|
||||
| Create / delete | `POST/DELETE /v3/connections/{provider}` |
|
||||
| List / get | `POST /v3/connections/list`, `GET …/{connectionId}` |
|
||||
| Configure / resources | `POST …/configure`, `GET …/resources` |
|
||||
| Sync / documents | `POST …/import`, `POST …/documents` |
|
||||
|
||||
**Guides:** [Connectors overview](/connectors/overview) · provider pages under Connectors
|
||||
18
apps/docs/api-reference/container-tags.mdx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "Container tags"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Multi-tenant containers — settings, merge, and delete."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
`containerTag` is the primary multi-tenant key (user id, workspace id, etc.). These endpoints manage settings and lifecycle for a tag.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `GET /v3/container-tags/{containerTag}` | Read tag settings |
|
||||
| `PATCH /v3/container-tags/{containerTag}` | Update tag settings |
|
||||
| `DELETE /v3/container-tags/{containerTag}` | Delete a container and its data |
|
||||
| `POST /v3/container-tags/merge` | Merge one tag into another |
|
||||
| `GET /v3/container-tags/merge/{mergeId}` | Poll merge status |
|
||||
|
||||
**Guide:** [Container tags](/concepts/container-tags) · [Filtering](/concepts/filtering)
|
||||
21
apps/docs/api-reference/documents.mdx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: "Documents"
|
||||
sidebarTitle: "Overview"
|
||||
description: "List, get status, update, delete, and inspect ingested documents."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
Documents are the unit of ingestion. Adds return immediately with `status: "queued"`; poll until `done` before relying on search or profiles.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `GET /v3/documents/{id}` | Status + metadata for one document |
|
||||
| `POST /v3/documents/list` | Filter and paginate documents |
|
||||
| `GET /v3/documents/processing` | Currently processing items |
|
||||
| `PATCH /v3/documents/{id}` | Update content or metadata |
|
||||
| `DELETE /v3/documents/{id}` | Delete by id or customId |
|
||||
| `DELETE /v3/documents/bulk` | Bulk delete |
|
||||
| `GET /v3/documents/{id}/chunks` | Inspect RAG chunks |
|
||||
| `GET /v3/documents/{id}/file-url` | Presigned URL for uploaded files |
|
||||
|
||||
**Guide:** [Document operations](/ingestion/document-operations)
|
||||
21
apps/docs/api-reference/ingest.mdx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: "Ingest"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Add documents, files, batches, and conversations to Supermemory."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
Send raw content into the processing pipeline. Supermemory extracts memories, chunks for RAG, and updates profiles asynchronously.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `POST /v3/documents` | Text, URLs, or structured content |
|
||||
| `POST /v3/documents/file` | Binary file upload |
|
||||
| `POST /v3/documents/batch` | Many documents in one request |
|
||||
| `POST /v4/conversations` | Chat sessions with turn-aware ingest |
|
||||
|
||||
**Guides:** [Add memories](/ingestion/add-memories) · [Quickstart](/quickstart)
|
||||
|
||||
<Tip>
|
||||
Use a stable `customId` (conversation id, doc id) so re-sends upsert instead of duplicating. Pass `dreaming: "instant"` when the next step is memory search or profiles.
|
||||
</Tip>
|
||||
20
apps/docs/api-reference/memories.mdx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
title: "Memories"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Create, list, update, and forget extracted memory entries (v4)."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
These endpoints operate on **extracted memories**, not raw documents.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `POST /v4/memories` | Write memories directly (skip document pipeline) |
|
||||
| `POST /v4/memories/list` | List with history / versions |
|
||||
| `PATCH /v4/memories` | Update (creates a new version) |
|
||||
| `DELETE /v4/memories` | Forget a specific memory |
|
||||
| `POST /v4/memories/forget-matching` | Forget by natural-language match |
|
||||
|
||||
For document-level CRUD, use [Documents](/api-reference/documents). For pipeline ingest, use [Ingest](/api-reference/ingest).
|
||||
|
||||
**Guide:** [Memory operations](/recall/memory-operations)
|
||||
68
apps/docs/api-reference/overview.mdx
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
title: "API Reference"
|
||||
description: "Interactive reference for the Supermemory HTTP API — ingest, search, profiles, memories, connectors, and settings."
|
||||
icon: "unplug"
|
||||
---
|
||||
|
||||
This is the **contract-level** reference for Supermemory: methods, paths, parameters, and the playground.
|
||||
|
||||
For narrative guides (when to use what, patterns, SDKs), start with the [Quickstart](/quickstart) and [Using supermemory](/ingestion/add-memories).
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://api.supermemory.ai
|
||||
```
|
||||
|
||||
Self-hosted: use your instance URL (for example `http://localhost:6767`). See [Self-hosting](/self-hosting/overview).
|
||||
|
||||
## Authentication
|
||||
|
||||
All endpoints use a Bearer API key. Create one in the [developer console](https://console.supermemory.ai).
|
||||
|
||||
```bash
|
||||
Authorization: Bearer sm_...
|
||||
```
|
||||
|
||||
Details: [API keys & auth](/authentication).
|
||||
|
||||
## Mental model
|
||||
|
||||
| Group | What it does |
|
||||
| --- | --- |
|
||||
| **Ingest** | Add documents, files, batches, and conversations into the pipeline |
|
||||
| **Documents** | Get status, list, update, delete, chunks, and file URLs |
|
||||
| **Search** | Semantic recall — memories, documents, or hybrid |
|
||||
| **Profiles** | Static + dynamic facts for a container (user / entity) |
|
||||
| **Memories** | Create, list, update, and forget extracted memory entries |
|
||||
| **Container tags** | Multi-tenant settings, merge, and delete for a container |
|
||||
| **Connections** | OAuth connectors (Drive, Notion, Gmail, …) and sync |
|
||||
| **Settings** | Org-level customization, buckets, and reset |
|
||||
|
||||
Same `containerTag` scopes ingest, search, and profiles — one engine, multiple ways out.
|
||||
|
||||
## Suggested order
|
||||
|
||||
1. **Ingest** — `POST /v3/documents` (SDK: `client.add`)
|
||||
2. **Documents** — `GET /v3/documents/{id}` until `status: "done"`
|
||||
3. **Search** — `POST /v4/search`
|
||||
4. **Profiles** — `POST /v4/profile`
|
||||
|
||||
Full walkthrough with conversation + document examples: [Quickstart](/quickstart).
|
||||
|
||||
## SDKs
|
||||
|
||||
Official clients wrap this API:
|
||||
|
||||
- TypeScript: `npm install supermemory`
|
||||
- Python: `pip install supermemory`
|
||||
|
||||
See [Supermemory SDK](/integrations/supermemory-sdk).
|
||||
|
||||
Playground snippets come from the OpenAPI spec: official **TypeScript / Python SDK** samples via `x-codeSamples`, plus cURL. (After API deploy — until then you may still see generic HTTP snippets.)
|
||||
|
||||
SDK generation is migrating off Stainless SaaS to **stlc** soon; documented OpenAPI samples will then be produced by the SDK build instead of a hand-maintained map.
|
||||
|
||||
## OpenAPI
|
||||
|
||||
Spec (live): [https://api.supermemory.ai/v3/openapi](https://api.supermemory.ai/v3/openapi)
|
||||
15
apps/docs/api-reference/profiles.mdx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: "Profiles"
|
||||
sidebarTitle: "Profiles overview"
|
||||
description: "Entity profiles — static and dynamic facts for a container."
|
||||
icon: "id-card"
|
||||
---
|
||||
|
||||
Profiles summarize what Supermemory knows about a user or entity in a `containerTag`.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `POST /v4/profile` | Fetch static + dynamic profile for a container |
|
||||
| `POST /v4/profile/buckets` | Profile organized by custom buckets |
|
||||
|
||||
**Guides:** [User profiles API](/recall/user-profiles) · [Concepts](/concepts/user-profiles) · [Buckets](/user-profiles/buckets)
|
||||
19
apps/docs/api-reference/search.mdx
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
title: "Recall"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Semantic search over memories, document chunks, or both — plus user profiles."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
Get context back out of Supermemory: search extracted memories / documents, or fetch a user profile.
|
||||
|
||||
| Endpoint | Role |
|
||||
| --- | --- |
|
||||
| `POST /v4/search` | Primary recall — `searchMode`: `memories`, `documents`, or `hybrid` |
|
||||
| `POST /v3/search` | Document / SuperRAG-oriented search |
|
||||
| `POST /v4/profile` | Static + dynamic profile for a container |
|
||||
| `POST /v4/profile/buckets` | Profile organized by custom buckets |
|
||||
|
||||
Prefer **v4** with `searchMode: "hybrid"` unless you only need document chunks or only extracted memories.
|
||||
|
||||
**Guides:** [Search](/recall/search) · [User profiles](/recall/user-profiles) · [SuperRAG](/concepts/super-rag) · [Memory vs RAG](/concepts/memory-vs-rag)
|
||||
17
apps/docs/api-reference/settings.mdx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
title: "Settings"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Organization settings, profile buckets, and data reset."
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
Org-level configuration for extraction, customization, and profile buckets.
|
||||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `GET /v3/settings` | Read org settings |
|
||||
| `PATCH /v3/settings` | Update org settings |
|
||||
| `POST /v3/settings/suggest-buckets` | Suggest profile buckets |
|
||||
| `POST /v3/settings/reset` | Reset organization data (destructive) |
|
||||
|
||||
**Guide:** [Customization](/concepts/customization)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: "Authentication"
|
||||
description: "API keys, scoped keys, and connector branding."
|
||||
title: "API keys & auth"
|
||||
description: "Org API keys, container-scoped keys, and connector branding."
|
||||
sidebarTitle: "API keys"
|
||||
icon: "key"
|
||||
---
|
||||
|
||||
|
|
@ -55,65 +56,65 @@ This works for Google Drive, Notion, and OneDrive. See the full setup in [Custom
|
|||
|
||||
---
|
||||
|
||||
## Scoped API Keys
|
||||
## Scoped API keys
|
||||
|
||||
<Accordion title="Container-scoped keys" icon="lock">
|
||||
Scoped keys are restricted to a single `containerTag`. They can only access documents and search within that container — useful for giving limited access to specific projects, users, or tenants without exposing your full API key.
|
||||
Scoped keys are restricted to one or more `containerTag`s. They can only access documents and search within those containers — use them to give a client, session, or tenant limited access without shipping your org master key.
|
||||
|
||||
**Allowed endpoints:** `/v3/documents`, `/v3/memories`, `/v4/memories`, `/v3/search`, `/v4/search`, `/v4/profile`
|
||||
Pairs with [container tags](/concepts/container-tags) for multi-tenant isolation.
|
||||
|
||||
### Create a scoped key
|
||||
**Allowed endpoints:** `/v3/documents`, `/v3/memories`, `/v4/memories`, `/v3/search`, `/v4/search`, `/v4/profile`
|
||||
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key \
|
||||
--request POST \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY' \
|
||||
-d '{
|
||||
"containerTag": "my-project",
|
||||
"name": "my-key-name",
|
||||
"expiresInDays": 30
|
||||
}'
|
||||
```
|
||||
Scoped keys **cannot** read billing, manage org settings, or mint further keys.
|
||||
|
||||
### Parameters
|
||||
### Create a scoped key
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
| --------------------- | -------- | ----------------------- | ------------------------------------------------ |
|
||||
| `containerTag` | Yes | — | Alphanumeric, hyphens, underscores, colons, dots |
|
||||
| `name` | No | `scoped_{containerTag}` | Display name for the key |
|
||||
| `expiresInDays` | No | — | 1–365 days |
|
||||
| `rateLimitMax` | No | `500` | Max requests per window (1–10,000) |
|
||||
| `rateLimitTimeWindow` | No | `60000` | Window in milliseconds (1–3,600,000) |
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "sm_orgId_...",
|
||||
"id": "key-id",
|
||||
"name": "scoped_my-project",
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key \
|
||||
--request POST \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY' \
|
||||
-d '{
|
||||
"containerTag": "my-project",
|
||||
"expiresAt": "2026-03-08T00:00:00.000Z",
|
||||
"allowedEndpoints": ["/v3/documents", "/v3/memories", "/v4/memories", "/v3/search", "/v4/search", "/v4/profile"]
|
||||
}
|
||||
```
|
||||
"name": "my-key-name",
|
||||
"expiresInDays": 30
|
||||
}'
|
||||
```
|
||||
|
||||
Use the returned key exactly like a normal API key — it just won't work outside its container scope.
|
||||
### Parameters
|
||||
|
||||
### Disable a scoped key
|
||||
| Parameter | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `containerTag` | Yes | — | Alphanumeric, hyphens, underscores, colons, dots |
|
||||
| `name` | No | `scoped_{containerTag}` | Display name for the key |
|
||||
| `expiresInDays` | No | — | 1–365 days |
|
||||
| `rateLimitMax` | No | `500` | Max requests per window (1–10,000) |
|
||||
| `rateLimitTimeWindow` | No | `60000` | Window in milliseconds (1–3,600,000) |
|
||||
|
||||
To revoke a scoped key, send a `DELETE` request with the `id` returned at creation time. This disables the key immediately — any subsequent requests using it will get a `401`. Memories and container tags are **not** affected.
|
||||
### Response
|
||||
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key/KEY_ID \
|
||||
--request DELETE \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY'
|
||||
```
|
||||
```json
|
||||
{
|
||||
"key": "sm_orgId_...",
|
||||
"id": "key-id",
|
||||
"name": "scoped_my-project",
|
||||
"containerTag": "my-project",
|
||||
"expiresAt": "2026-03-08T00:00:00.000Z",
|
||||
"allowedEndpoints": ["/v3/documents", "/v3/memories", "/v4/memories", "/v3/search", "/v4/search", "/v4/profile"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
Use the returned key like a normal API key — it just will not work outside its container scope.
|
||||
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
</Accordion>
|
||||
### Disable a scoped key
|
||||
|
||||
Revoke with the `id` from creation. Subsequent requests get `401`. Memories and container tags are **not** deleted.
|
||||
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key/KEY_ID \
|
||||
--request DELETE \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY'
|
||||
```
|
||||
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
---
|
||||
title: "Developer Platform"
|
||||
description: "API updates, new endpoints, and SDK releases"
|
||||
---
|
||||
|
||||
|
||||
API updates, new endpoints, SDK releases, and developer-focused features.
|
||||
|
||||
## April 13, 2026
|
||||
|
||||
- **Google Drive scoped sync:** New connections default to a **hosted folder/file picker** after OAuth; only chosen items sync. Use `metadata.syncScope: "full"` to sync the whole Drive. Import jobs **skip** scoped connections until a selection exists.
|
||||
|
||||
## March 18, 2026
|
||||
|
||||
- **Supermemory CLI:** New command-line tool for managing memories, documents, profiles, tags, connectors, and API keys directly from the terminal.
|
||||
- **PPTX Support:** PowerPoint files (`.pptx`) are now a supported content type for ingestion.
|
||||
- **Multiple containerTags on Scoped API Keys:** Scoped API keys can now be assigned to multiple container tags, allowing a single key to access several spaces.
|
||||
- **Documents Page in Console:** New dedicated documents browser in the console for viewing, filtering, and managing all ingested content.
|
||||
- **`@supermemory/tools` v1.4.1:** Now exposes raw `searchResults` in `MemoryPromptData`, giving full control over how retrieved memories are formatted in prompts.
|
||||
|
||||
## March 12, 2026
|
||||
|
||||
- **Audio Extraction:** Ingest audio files with automatic transcription powered by Gemini 2.5 Flash. Audio content is transcribed, chunked, and indexed like any other document.
|
||||
- **Delete Connection Without Documents:** Disconnect an external source (Google Drive, Notion, etc.) without deleting the documents it synced.
|
||||
- **Org-Level Overage Toggle:** Control overage billing per-organization with a new toggle in the billing settings.
|
||||
- **Retry Failed Documents:** Documents that previously failed ingestion can now be retried by re-submitting with the same `customId`.
|
||||
- **Copyable Team Invite Link:** Team management page now includes a shareable invite link.
|
||||
|
||||
## March 9, 2026
|
||||
|
||||
- **Delete Scoped API Keys:** New `DELETE` endpoint to disable scoped API keys programmatically.
|
||||
- **`supermemory-agent-framework` Python Package:** Official Python package for using Supermemory with Microsoft's Agent Framework — memory tools and middleware out of the box.
|
||||
- **OpenAI SDK Backfill:** Improved compatibility across `supermemory-openai-sdk` (Python) and `@supermemory/tools` (TypeScript) OpenAI integrations.
|
||||
- **Bulk Delete in Nova:** Bulk document deletion now available in the Nova app interface.
|
||||
|
||||
## March 5, 2026
|
||||
|
||||
- **`extends` Relation Type:** Memory graph now supports `extends` as a relation type, enabling richer knowledge graph connections between documents.
|
||||
- **Interactive Memory Graph in MCP:** The MCP server now includes an interactive graph visualization app for exploring memory connections from any MCP-compatible client.
|
||||
- **Plugin Auth Connect Page:** New OAuth-style connect page for plugin integrations (Claude Code, OpenCode, OpenClaw).
|
||||
- **ViaSocket Integration:** New integration guide for connecting Supermemory with ViaSocket automation workflows.
|
||||
|
||||
## March 2, 2026
|
||||
|
||||
- **Configurable Vector Stores:** Bring your own vector store — Supermemory now supports pluggable vector backends beyond the default.
|
||||
- **List Memories Endpoint:** New `GET /v3/documents` endpoint with pagination, filtering by container tag, status, and metadata.
|
||||
|
||||
## February 26, 2026
|
||||
|
||||
- **Self-Hostable Supermemory:** Run the full Supermemory stack on your own infrastructure with Docker.
|
||||
- **Console v2:** Complete redesign of the developer console with new navigation, improved billing, and a unified project view.
|
||||
- **No More 120 Memory Limit:** The previous cap of 120 memories per container tag has been removed. Store unlimited memories.
|
||||
|
||||
## February 22, 2026
|
||||
|
||||
- **Supermemory Skill for Claude Code:** Install with `npx skills add supermemoryai/skills` — teaches Claude to proactively recommend and implement Supermemory when building AI apps that need persistent memory, user profiles, or semantic search. Includes ready-to-use TypeScript and Python examples.
|
||||
- **Metadata Filtering for Profiles:** User profile search now supports metadata-based filtering for more targeted profile queries.
|
||||
- **List Documents with Multiple Container Tags:** New `operator` parameter to query documents spanning multiple container tags.
|
||||
- **Deprecate `include: chunks`:** The `include: chunks` parameter in `/v4/search` is deprecated in favor of the `hybrid` search mode.
|
||||
|
||||
## February 9, 2026
|
||||
|
||||
- **Unified Organizations:** Consumer and developer organizations merged into a single org type. All orgs can now access both Nova and the developer API.
|
||||
- **Credits-Based Usage Display:** Billing now shows token usage in a credits-based format.
|
||||
- **Nova Spaces with Multi-Select:** Spaces in Nova now support multi-select, replacing "All Spaces" with scoped "Nova Spaces."
|
||||
|
||||
## February 6, 2026
|
||||
|
||||
- **Scoped API Keys for Container Tags:** Create API keys scoped to specific container tags for fine-grained access control per space.
|
||||
- **DELETE Endpoint for Container Tags:** New endpoint to delete container tags and their associated document relationships.
|
||||
- **Container Tag-Level Context Prompts:** Set custom context prompts per container tag to control how memories are extracted and summarized within each space.
|
||||
|
||||
## February 3, 2026
|
||||
|
||||
- **New Integration Docs:** Added guides for LangGraph, OpenAI Agents SDK, CrewAI, Agno, Mastra, and LangChain — covering all major AI agent frameworks.
|
||||
- **Claude Code Integration:** Official integration page for using Supermemory as persistent memory in Claude Code.
|
||||
- **Entity Context Documentation:** New docs on how entity extraction and context enrichment work in the memory pipeline.
|
||||
- **Authentication Docs:** Comprehensive authentication page with code examples for API key auth, OAuth, and scoped keys.
|
||||
|
||||
## January 25, 2026
|
||||
|
||||
- **Plugin Authentication System:** New auth system for external tool integrations, enabling secure plugin-to-API connections.
|
||||
- **Enterprise Plan Support:** Enterprise tier now available in the console with dedicated billing and support options.
|
||||
- **Plugin Catalog:** Dedicated plugin page with auth flows for Claude Code, OpenCode, and OpenClaw integrations.
|
||||
- **`@supermemory/tools` — Strict Mode:** Strict mode support for OpenAI function calling, ensuring schema-validated tool calls.
|
||||
|
||||
## January 14, 2026
|
||||
|
||||
- **Hybrid PDF Pipeline:** PDF extraction now uses Mistral OCR 3 with Gemini fallback for significantly improved accuracy on scanned documents and complex layouts.
|
||||
- **Halfvec Embeddings:** Embedding storage optimized with half-precision vectors, reducing storage costs while maintaining search quality.
|
||||
- **Spaces Creation with Emoji:** Create and customize spaces with emoji identifiers in Nova.
|
||||
|
||||
## January 8, 2026
|
||||
|
||||
- **Gmail Connector:** New connector to sync Gmail threads into Supermemory. Threads are stored in R2 for reliable processing of large mailboxes.
|
||||
- **Container Tag Filters:** Filter documents by container tag in list and search endpoints.
|
||||
- **Pagination Improvements:** Improved pagination and document view across the console.
|
||||
- **`supermemory-pipecat` Python Package:** New SDK for integrating Supermemory with Pipecat voice AI pipelines, including Gemini Live speech-to-speech support.
|
||||
- **`@supermemory/tools` — Prompt Templates:** Customize how memory context is formatted in AI SDK integrations with the new `promptTemplate` option.
|
||||
|
||||
## December 30, 2025
|
||||
|
||||
- **MCP 4.0:** Major MCP server update with session configuration, project-aware tools on every init, and backward-compatible 3.0 support. Includes the new `context` prompt for automatic user profile injection.
|
||||
- **S3 Connector:** New connector to sync documents from Amazon S3 buckets, with console UI for bucket configuration.
|
||||
- **Memory Graph Revamp:** Complete rewrite of `@supermemory/memory-graph` with improved visualization and performance.
|
||||
|
||||
## December 24, 2025
|
||||
|
||||
- **`@supermemory/tools` — Vercel AI SDK v5/v6:** Now supports both Vercel AI SDK v5 and v6, with automatic version detection.
|
||||
- **Conversation Support in SDKs:** `supermemory` (TypeScript) and `supermemory-openai-sdk` (Python) now support the conversations API for multi-turn chat with memory.
|
||||
- **MemoryBench:** New open-source benchmark suite for evaluating memory systems, with documentation and CLI.
|
||||
|
||||
## December 17, 2025
|
||||
|
||||
- **Hybrid Search Mode:** New `hybrid` search mode in `/v4/search` combining semantic and keyword search for better recall on technical queries.
|
||||
|
||||
## December 9, 2025
|
||||
|
||||
- **Firecrawl Integration:** Web crawling powered by Firecrawl for more reliable extraction of website content, with fallback support.
|
||||
- **Custom GitHub Credentials:** Bring your own GitHub OAuth app credentials for the GitHub connector, enabling private repo access.
|
||||
- **API Key Expiration Emails:** API keys now trigger email notifications before expiration.
|
||||
- **Connector Sync Logs:** Connection syncs now produce detailed logs visible in the console.
|
||||
|
||||
## December 2, 2025
|
||||
|
||||
- **Organization Deletion:** Organizations can now be fully deleted from the console, including all associated data.
|
||||
- **Billing Page Redesign:** New billing layout with invoicing support and improved usage visibility.
|
||||
- **Console Onboarding Improvements:** Streamlined onboarding flow for new users.
|
||||
|
||||
## December 5, 2025
|
||||
|
||||
- **`@supermemory/tools` — Browser API Key Support:** `apiKey` can now be passed via options instead of relying on `process.env`, enabling browser-based usage of the tools package.
|
||||
|
||||
## November 17, 2025
|
||||
|
||||
- **Web Crawler Connector:** New connector to crawl and index entire websites with configurable depth and URL patterns.
|
||||
- **`@supermemory/memory-graph` Package:** New package for building interactive graph visualizations of memory connections, with a standalone playground.
|
||||
- **OpenAI Responses API Support:** `@supermemory/tools` OpenAI integration now supports the Responses API.
|
||||
- **`supermemory-openai-sdk` — Python Middleware:** New `withSupermemory` middleware for the Python OpenAI SDK, enabling transparent memory injection into OpenAI API calls.
|
||||
- **Browser Extension Webpage Capture:** Chrome extension can now capture full webpage content with markdown conversion, not just bookmarks.
|
||||
- **Bulk Memory Optimization:** Memory creation now uses bulk inserts for significantly faster batch ingestion.
|
||||
|
||||
## October 27, 2025
|
||||
|
||||
- **Enhanced Filtering Capabilities:** Major improvements to the search filtering API with new `string_contains` filter type for partial string matching, `ignoreCase` option for case-insensitive string operations, and improved negation support across all filter types including proper numeric equality negation. The implementation also includes enhanced SQL injection protection and wildcard escaping for improved security.
|
||||
|
||||
## September 17, 2025
|
||||
|
||||
- **Forgotten Memories Search:** New `include.forgottenMemories` parameter in v4 search API allows searching through memories that have been explicitly forgotten or expired. Set to `true` to include forgotten memories in search results, helping recover previously archived information.
|
||||
|
||||
## September 14, 2025
|
||||
|
||||
- **Enhanced Delete API:** `DELETE /v3/documents/:id` endpoint now supports both internal document ID and customId for flexible document deletion. Developers can now delete documents using the same customId provided during creation, improving API consistency with other endpoints.
|
||||
- **API Terminology Clarification:** Refined API terminology from "memories" to "documents" for improved developer clarity. New `/v3/documents/*` endpoints provide more intuitive naming while maintaining full backward compatibility via automatic redirects from `/v3/memories/*`. No action required from existing integrations.
|
||||
|
||||
## September 13, 2025
|
||||
|
||||
- **Documentation v2.0:** Complete rewrite with comprehensive API references, cookbook recipes, and production-ready examples for TypeScript, Python, and cURL
|
||||
- **AI SDK Integration:** New `@supermemory/tools/ai-sdk` package for native Vercel AI SDK integration with memory tools and infinite chat capabilities
|
||||
- **Bulk Delete Endpoint:** New `DELETE /v3/documents/bulk` endpoint for efficient memory management
|
||||
|
||||
## September 5, 2025
|
||||
|
||||
- **Memory Search Endpoint:** New `/v4/search` endpoint optimized for conversational AI and memory retrieval (vs document search)
|
||||
- **Advanced Memory Management:** Enhanced update/delete operations with better filtering and batch processing capabilities
|
||||
|
||||
## August 30, 2025
|
||||
|
||||
- **MCP (Model Context Protocol) Server:** Launch of supermemory MCP server for AI model integrations with full project support and auto-detection
|
||||
- **Enhanced Filtering API:** Improved SQL-based filtering with array_contains, numeric operators, and complex AND/OR logic
|
||||
|
||||
## August 15, 2025
|
||||
|
||||
- **Memory Router Proxy:** Enhanced proxy functionality for LLM requests with automatic context management and token optimization
|
||||
- **Search Algorithm Updates:** Configurable similarity thresholds, reranking, and query rewriting for better result quality
|
||||
|
||||
## April 30, 2025
|
||||
|
||||
- **Comprehensive API Documentation:** New interactive API references with detailed parameter explanations and response schemas
|
||||
- **Container Tags System:** Enhanced organizational grouping for better memory isolation and user-scoped content
|
||||
- **Auto Content Type Detection:** Automatic processing of PDFs, images, videos, and web content regardless of URL extensions
|
||||
|
||||
## April 28, 2025
|
||||
|
||||
- **Google Drive Connector API:** New endpoints for programmatic Google Drive integration and file syncing
|
||||
|
||||
## April 25, 2025
|
||||
|
||||
- **Search Threshold Controls:** New `documentThreshold` and `chunkThreshold` parameters for fine-tuning search sensitivity
|
||||
- **Document-Specific Search:** New `docId` parameter to search within specific large documents
|
||||
- **Enhanced Chunk Control:** `onlyMatchingChunks` parameter for precise result filtering
|
||||
|
||||
## April 24, 2025
|
||||
|
||||
- **Query Rewriting API:** Automatic query expansion and intent matching for better search results
|
||||
- **Search Context Options:** New `includeFullDocs` and `includeSummary` parameters for comprehensive document retrieval
|
||||
|
||||
## April 18, 2025
|
||||
|
||||
- **Enhanced Content Processing:** Improved ingestion pipeline supporting direct URL processing for images, videos, and PDFs
|
||||
- **Stable Web Ingestion:** More reliable processing of website URLs with better content extraction
|
||||
|
||||
## April 14, 2025
|
||||
|
||||
- **Team API Endpoints:** New endpoints for team management and permission control
|
||||
- **Enhanced Analytics API:** Better observability with detailed usage metrics and performance data
|
||||
|
||||
## February 1, 2025
|
||||
|
||||
- **Multi-Space Search:** Search across multiple container tags simultaneously with array parameter support
|
||||
- **API Versioning:** Migration to `/v1` endpoints with improved versioning strategy
|
||||
- **Interactive API Playground:** New testing interface for all endpoints with live examples
|
||||
|
|
@ -1,779 +0,0 @@
|
|||
---
|
||||
title: "Changelog"
|
||||
sidebarTitle: "Supermemory"
|
||||
description: "New updates and improvements to Supermemory"
|
||||
---
|
||||
|
||||
<Update label="May 27, 2026" tags={["API"]}>
|
||||
|
||||
### Instant dreaming
|
||||
|
||||
New `dreaming` parameter on `POST /v3/documents` and `POST /v3/documents/batch`. Default `"dynamic"` groups related documents together so memories form from coherent, logical units. Set `"dreaming": "instant"` to process a single document on its own — bills one extra operation per document. Omit the parameter and behavior is unchanged.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 13, 2026" tags={["Integrations", "API"]}>
|
||||
|
||||
### Google Drive: scoped sync by default
|
||||
|
||||
New Google Drive connections default to **folder and file** scope: after OAuth, users complete a hosted picker; only selected items sync. Set `metadata.syncScope` to `"full"` on connection creation to sync the entire Drive without the picker. Scoped connections without a saved selection are skipped by import jobs until setup is finished.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="March 18, 2026" tags={["API", "SDK", "Console", "CLI"]}>
|
||||
|
||||
### Supermemory CLI
|
||||
|
||||
New command-line tool for managing memories, documents, profiles, tags, connectors, and API keys directly from the terminal.
|
||||
|
||||
### `@supermemory/tools` v1.4.1
|
||||
|
||||
Now exposes raw `searchResults` in `MemoryPromptData`, giving full control over how retrieved memories are formatted in prompts.
|
||||
|
||||
### PPTX & Audio Ingestion
|
||||
|
||||
PowerPoint files (`.pptx`) are now a supported content type. Audio files are automatically transcribed via Gemini 2.5 Flash, chunked, and indexed.
|
||||
|
||||
### Multi-containerTag Scoped API Keys
|
||||
|
||||
Scoped API keys can now be assigned to multiple container tags — one key, multiple spaces.
|
||||
|
||||
### Console: Documents Page
|
||||
|
||||
New dedicated documents browser in the console for viewing, filtering, and managing all ingested content.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="March 9, 2026" tags={["API", "SDK", "MCP", "Integrations"]}>
|
||||
|
||||
### Delete Scoped API Keys
|
||||
|
||||
New `DELETE` endpoint to disable scoped API keys programmatically.
|
||||
|
||||
### `supermemory-agent-framework` Python Package
|
||||
|
||||
Official Python package for using Supermemory with Microsoft's Agent Framework — memory tools and middleware out of the box.
|
||||
|
||||
### Interactive Memory Graph in MCP
|
||||
|
||||
The MCP server now includes an interactive graph visualization app for exploring memory connections from any MCP-compatible client.
|
||||
|
||||
### More Integrations
|
||||
|
||||
- **ViaSocket** — new integration guide for automation workflows.
|
||||
- **Plugin Auth Connect Page** — OAuth-style connect page for Claude Code, OpenCode, and OpenClaw.
|
||||
- **OpenAI SDK Backfill** — improved compatibility across TypeScript and Python SDKs.
|
||||
|
||||
### Other
|
||||
|
||||
- **Retry failed documents** by re-submitting with the same `customId`.
|
||||
- **Delete connection without documents** — disconnect a source without deleting synced content.
|
||||
- **Org-level overage toggle** in billing settings.
|
||||
- **Copyable team invite link** on the team management page.
|
||||
- **`extends` relation type** in memory graph for richer knowledge graph connections.
|
||||
- **Bulk delete** in the Nova app interface.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="March 2, 2026" tags={["API"]}>
|
||||
|
||||
### Configurable Vector Stores
|
||||
|
||||
Bring your own vector store — Supermemory now supports pluggable vector backends beyond the default.
|
||||
|
||||
### List Memories Endpoint
|
||||
|
||||
New `GET /v3/documents` endpoint with pagination, filtering by container tag, status, and metadata.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 26, 2026" tags={["API", "Console"]}>
|
||||
|
||||
### Self-Hostable Supermemory
|
||||
|
||||
Run the full Supermemory stack on your own infrastructure with Docker.
|
||||
|
||||
### Console v2
|
||||
|
||||
Complete redesign of the developer console with new navigation, improved billing, and a unified project view that merges consumer and developer organizations.
|
||||
|
||||
### No More 120 Memory Limit
|
||||
|
||||
The previous cap of 120 memories per container tag has been removed. Store unlimited memories.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 22, 2026" tags={["API", "SDK", "CLI"]}>
|
||||
|
||||
### Supermemory Skill for Claude Code
|
||||
|
||||
Install with `npx skills add supermemoryai/skills` — teaches Claude to proactively recommend and implement Supermemory when building AI apps. Includes TypeScript and Python examples.
|
||||
|
||||
### API Improvements
|
||||
|
||||
- **Metadata filtering for profiles** — target profile queries by metadata fields.
|
||||
- **List documents with multiple container tags** — new `operator` parameter.
|
||||
- **Deprecate `include: chunks`** in `/v4/search` in favor of the `hybrid` search mode.
|
||||
- **Content deduplication** in search results to reduce token usage.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 9, 2026" tags={["API", "Console"]}>
|
||||
|
||||
### Unified Organizations
|
||||
|
||||
Consumer and developer organizations merged into a single org type. All orgs can now access both Nova and the developer API.
|
||||
|
||||
### Credits-Based Usage Display
|
||||
|
||||
Billing now shows token usage in a credits-based format.
|
||||
|
||||
### Nova Spaces with Multi-Select
|
||||
|
||||
Spaces in Nova support multi-select, replacing "All Spaces" with scoped "Nova Spaces."
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 6, 2026" tags={["API"]}>
|
||||
|
||||
### Scoped API Keys for Container Tags
|
||||
|
||||
Create API keys scoped to specific container tags for fine-grained access control per space.
|
||||
|
||||
### DELETE Endpoint for Container Tags
|
||||
|
||||
New endpoint to delete container tags and their associated document relationships.
|
||||
|
||||
### Container Tag-Level Context Prompts
|
||||
|
||||
Set custom context prompts per container tag to control how memories are extracted and summarized within each space.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 3, 2026" tags={["Integrations", "SDK"]}>
|
||||
|
||||
### New Framework Integration Docs
|
||||
|
||||
Added guides for LangGraph, OpenAI Agents SDK, CrewAI, Agno, Mastra, LangChain, and Claude Code — covering all major AI agent frameworks.
|
||||
|
||||
### Entity Context & Authentication Docs
|
||||
|
||||
New docs on entity extraction, context enrichment, and comprehensive authentication examples (API key, OAuth, scoped keys).
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="January 25, 2026" tags={["API", "Console", "SDK"]}>
|
||||
|
||||
### Plugin Authentication System
|
||||
|
||||
New auth system for external tool integrations, enabling secure plugin-to-API connections. Dedicated plugin page with auth flows for Claude Code, OpenCode, and OpenClaw.
|
||||
|
||||
### Enterprise Plan Support
|
||||
|
||||
Enterprise tier now available in the console.
|
||||
|
||||
### `@supermemory/tools` — Strict Mode
|
||||
|
||||
Strict mode support for OpenAI function calling, ensuring schema-validated tool calls.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="January 14, 2026" tags={["API"]}>
|
||||
|
||||
### Hybrid PDF Pipeline
|
||||
|
||||
PDF extraction now uses Mistral OCR 3 with Gemini fallback for significantly improved accuracy on scanned documents and complex layouts.
|
||||
|
||||
### Halfvec Embeddings
|
||||
|
||||
Embedding storage optimized with half-precision vectors, reducing storage costs while maintaining search quality.
|
||||
|
||||
### Spaces Creation with Emoji
|
||||
|
||||
Create and customize spaces with emoji identifiers in Nova.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="January 8, 2026" tags={["API", "SDK", "Integrations"]}>
|
||||
|
||||
### Gmail Connector
|
||||
|
||||
New connector to sync Gmail threads into Supermemory. Threads are stored in R2 for reliable processing of large mailboxes.
|
||||
|
||||
### `supermemory-pipecat` Python Package
|
||||
|
||||
New SDK for Pipecat voice AI pipelines, including Gemini Live speech-to-speech support.
|
||||
|
||||
### `@supermemory/tools` — Prompt Templates
|
||||
|
||||
Customize how memory context is formatted in AI SDK integrations with the new `promptTemplate` option.
|
||||
|
||||
### Other
|
||||
|
||||
- **Container tag filters** in list and search endpoints.
|
||||
- **Pagination improvements** across the console.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 30, 2025" tags={["MCP", "SDK", "API"]}>
|
||||
|
||||
### MCP 4.0
|
||||
|
||||
Major MCP server update with session configuration, project-aware tools on every init, and backward-compatible 3.0 support. New `context` prompt for automatic user profile injection into AI conversations.
|
||||
|
||||
### S3 Connector
|
||||
|
||||
New connector to sync documents from Amazon S3 buckets, with console UI for bucket configuration.
|
||||
|
||||
### Memory Graph Revamp
|
||||
|
||||
Complete rewrite of `@supermemory/memory-graph` with improved visualization and performance.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 24, 2025" tags={["SDK"]}>
|
||||
|
||||
### `@supermemory/tools` — AI SDK v5/v6
|
||||
|
||||
Now supports both Vercel AI SDK v5 and v6 with automatic version detection.
|
||||
|
||||
### Conversation Support in SDKs
|
||||
|
||||
`supermemory` (TypeScript) and `supermemory-openai-sdk` (Python) now support the conversations API for multi-turn chat with memory.
|
||||
|
||||
### MemoryBench
|
||||
|
||||
New open-source benchmark suite for evaluating memory systems, with documentation and CLI.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 17, 2025" tags={["API"]}>
|
||||
|
||||
### Hybrid Search Mode
|
||||
|
||||
New `hybrid` search mode in `/v4/search` combining semantic and keyword search for better recall on technical queries.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 9, 2025" tags={["API", "Console"]}>
|
||||
|
||||
### Firecrawl Integration
|
||||
|
||||
Web crawling powered by Firecrawl for more reliable extraction of website content, with fallback support.
|
||||
|
||||
### Custom GitHub Credentials
|
||||
|
||||
Bring your own GitHub OAuth app credentials for the GitHub connector, enabling private repo access.
|
||||
|
||||
### API Key Expiration Emails
|
||||
|
||||
API keys now trigger email notifications before expiration.
|
||||
|
||||
### Connector Sync Logs
|
||||
|
||||
Connection syncs now produce detailed logs visible in the console.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 5, 2025" tags={["SDK"]}>
|
||||
|
||||
### `@supermemory/tools` — Browser API Key Support
|
||||
|
||||
`apiKey` can now be passed via options instead of relying on `process.env`, enabling browser-based usage.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="December 2, 2025" tags={["Console"]}>
|
||||
|
||||
### Organization Deletion
|
||||
|
||||
Organizations can now be fully deleted from the console, including all associated data.
|
||||
|
||||
### Billing Page Redesign
|
||||
|
||||
New billing layout with invoicing support and improved usage visibility.
|
||||
|
||||
### Console Onboarding Improvements
|
||||
|
||||
Streamlined onboarding flow for new users.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="November 17, 2025" tags={["API", "SDK"]}>
|
||||
|
||||
### Web Crawler Connector
|
||||
|
||||
New connector to crawl and index entire websites with configurable depth and URL patterns.
|
||||
|
||||
### `@supermemory/memory-graph` Package
|
||||
|
||||
New package for building interactive graph visualizations of memory connections, with a standalone playground.
|
||||
|
||||
### OpenAI Responses API Support
|
||||
|
||||
`@supermemory/tools` OpenAI integration now supports the Responses API.
|
||||
|
||||
### `supermemory-openai-sdk` — Python Middleware
|
||||
|
||||
New `withSupermemory` middleware for the Python OpenAI SDK, enabling transparent memory injection into OpenAI API calls.
|
||||
|
||||
### Browser Extension Webpage Capture
|
||||
|
||||
Chrome extension can now capture full webpage content with markdown conversion.
|
||||
|
||||
### Bulk Memory Optimization
|
||||
|
||||
Memory creation now uses bulk inserts for significantly faster batch ingestion.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="October 27, 2025" tags={["API", "SDK"]}>
|
||||
|
||||
### Enhanced Filtering
|
||||
|
||||
New `string_contains` filter type for partial string matching, `ignoreCase` option for case-insensitive operations, and improved negation support. Enhanced SQL injection protection.
|
||||
|
||||
### `withSupermemory` for OpenAI SDK
|
||||
|
||||
New `withSupermemory` wrapper for the OpenAI TypeScript SDK — transparent memory injection with automatic assistant response capture.
|
||||
|
||||
### Zapier & n8n Integration Pages
|
||||
|
||||
New integration guides for connecting Supermemory with Zapier and n8n automation workflows.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="October 10, 2025" tags={["SDK", "API", "Console"]}>
|
||||
|
||||
### `@supermemory/tools` — AI SDK `withSupermemory`
|
||||
|
||||
New `withSupermemory` language model wrapper for Vercel AI SDK that automatically injects memory context and captures assistant responses.
|
||||
|
||||
### Raycast Extension
|
||||
|
||||
New Raycast extension for quick memory access and addition from the macOS launcher.
|
||||
|
||||
### User Profiles API
|
||||
|
||||
New `/v4/profile` endpoint for retrieving AI-generated user profiles derived from memory interactions, with container tag scoping.
|
||||
|
||||
### Other
|
||||
|
||||
- **DOCX support** — Word documents can now be ingested.
|
||||
- **Project selection for connectors** — assign Google Drive, Notion, and OneDrive connections to specific projects.
|
||||
- **Multiple models in consumer chat** — model switcher with system prompt improvements.
|
||||
- **Organization settings** — configure Supermemory behavior (chunking, extraction, memory limits) per org.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="September 17, 2025" tags={["API", "Console"]}>
|
||||
|
||||
### Forgotten Memories Search
|
||||
|
||||
New `include.forgottenMemories` parameter in v4 search API to search through memories that have been explicitly forgotten or expired.
|
||||
|
||||
### Enhanced Delete API
|
||||
|
||||
`DELETE /v3/documents/:id` now supports both internal document ID and `customId`.
|
||||
|
||||
### API Terminology Update
|
||||
|
||||
Renamed "memories" to "documents" for developer clarity. New `/v3/documents/*` endpoints with full backward compatibility via automatic redirects from `/v3/memories/*`.
|
||||
|
||||
### Console Revamp
|
||||
|
||||
New console design with dark/light mode, org switcher, billing invoices, space selector with search, and memory list with multi-delete.
|
||||
|
||||
### Other
|
||||
|
||||
- **New filters** — revamped filtering UI in the console.
|
||||
- **Onboarding redesign** — new step-based onboarding with code samples.
|
||||
- **Configurable chunking** — set chunk size and algorithm per org.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="September 12, 2025" tags={["API", "SDK"]}>
|
||||
|
||||
### Documentation v2.0
|
||||
|
||||
Complete rewrite with comprehensive API references, cookbook recipes, and production-ready examples for TypeScript, Python, and cURL.
|
||||
|
||||
### `@supermemory/tools` Package
|
||||
|
||||
New tools package for native Vercel AI SDK and OpenAI integration with memory tools and infinite chat. Plus `openai-python-sdk` for Python middleware.
|
||||
|
||||
### Batch Add & Bulk Delete
|
||||
|
||||
New `POST /v3/documents/batch` for batch ingestion and `DELETE /v3/documents/bulk` for bulk deletion.
|
||||
|
||||
### Memory Forgetfulness System
|
||||
|
||||
Full lifecycle management with `forgetAfter` dates and forgotten memory filtering.
|
||||
|
||||
### Video Uploads
|
||||
|
||||
Video files can now be ingested with automatic content extraction.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="September 1, 2025" tags={["MCP", "Console"]}>
|
||||
|
||||
### MCP Connection Flow Redesign
|
||||
|
||||
Step-based UI for connecting MCP clients with v1 migration support. One-click install for Cursor.
|
||||
|
||||
### Claude.ai & t3.chat Extension Support
|
||||
|
||||
Browser extension now integrates directly with Claude.ai and t3.chat for automatic memory search during conversations.
|
||||
|
||||
### Waitlist Removed
|
||||
|
||||
Supermemory is now open to all users — no more waitlist.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="August 24, 2025" tags={["API", "Console"]}>
|
||||
|
||||
### New Landing Page & Developer Page
|
||||
|
||||
Redesigned marketing pages with developer-focused content, SEO improvements, and mobile responsiveness.
|
||||
|
||||
### Direct Webpage Ingestion
|
||||
|
||||
Ingest web content with `<sm-highlight>` tags for targeted extraction.
|
||||
|
||||
### Usage Limits Dashboard
|
||||
|
||||
Billing usage and limits now visible directly in the console dashboard.
|
||||
|
||||
### Other
|
||||
|
||||
- **Allow all CORS origins** for easier API integration.
|
||||
- **Single `containerTag` in add memory** — simpler API for basic use cases.
|
||||
- **Improved MCP project handling** — better project scoping in the MCP server.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="August 16, 2025" tags={["Console"]}>
|
||||
|
||||
### New Consumer App
|
||||
|
||||
Complete rewrite of the consumer-facing app — new chat experience with slide-out window, masonry memory grid with infinite scroll, PWA support, and mobile-responsive menu bar.
|
||||
|
||||
### Memory Graph with WebGL
|
||||
|
||||
Graph rendering now uses WebGL for smooth visualization of thousands of memory connections. Search highlights relevant nodes with zoom.
|
||||
|
||||
### Chat Rewrite
|
||||
|
||||
New chat system with memory-aware conversations, regeneration, copy buttons, and the ability to add memories through chat.
|
||||
|
||||
### Dynamic Node Relations
|
||||
|
||||
Memory graph now supports `update`, `extend`, and `derive` relation types. Memories can be inferred from multiple parent documents.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="August 12, 2025" tags={["API"]}>
|
||||
|
||||
### PDF Support for Google Drive
|
||||
|
||||
Google Drive connector now processes PDF files alongside Docs, Sheets, and Slides.
|
||||
|
||||
### Encrypted Connector Credentials
|
||||
|
||||
Google Drive, OneDrive, and Notion client secrets are now encrypted at rest.
|
||||
|
||||
### Bulk Memory Delete
|
||||
|
||||
New endpoint for deleting multiple memories at once.
|
||||
|
||||
### Self-Host Support
|
||||
|
||||
Initial self-hosting support — run Supermemory on your own infrastructure.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="August 1, 2025" tags={["Console", "API"]}>
|
||||
|
||||
### Console Migrated to Cloudflare
|
||||
|
||||
Console app moved from Vercel to Cloudflare Workers for improved performance and lower latency.
|
||||
|
||||
### Autumn Payments Integration
|
||||
|
||||
Billing system integrated with Autumn for subscription management, waitlist early access, and usage tracking.
|
||||
|
||||
### New Developer Dashboard
|
||||
|
||||
Redesigned developer dashboard with API key display in code snippets, limits visualization, and MCP installation instructions.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="July 25, 2025" tags={["Console", "MCP"]}>
|
||||
|
||||
### Consumer App v0
|
||||
|
||||
First version of the consumer app with chat, memory browsing, project management, and profile view. New consumer-oriented landing page.
|
||||
|
||||
### MCP → Agents SDK
|
||||
|
||||
MCP server migrated to the Agents SDK architecture for better reliability and project support.
|
||||
|
||||
### New Billing
|
||||
|
||||
Revamped billing page with upgrade buttons and plan management.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="July 16, 2025" tags={["Console", "API"]}>
|
||||
|
||||
### Memory Graph Rewrite
|
||||
|
||||
Complete rewrite of the graph visualization — faster rendering, better layout, and interactive exploration.
|
||||
|
||||
### Onboarding
|
||||
|
||||
New guided onboarding flow for first-time console users.
|
||||
|
||||
### Notion Webhooks
|
||||
|
||||
Real-time sync for Notion connections via webhook integration.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="July 5, 2025" tags={["Console"]}>
|
||||
|
||||
### Landing Page Rewrite
|
||||
|
||||
New marketing site with glass UI design, rewritten pricing page, and dedicated MCP page.
|
||||
|
||||
### Billing Page
|
||||
|
||||
New billing page with upgrade buttons and plan comparison.
|
||||
|
||||
### PostHog Analytics
|
||||
|
||||
Analytics tracking added across the console and landing page.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 21, 2025" tags={["API"]}>
|
||||
|
||||
### OneDrive Connector
|
||||
|
||||
New connector for syncing OneDrive files with webhook-based real-time updates.
|
||||
|
||||
### Connectors BYOK
|
||||
|
||||
Bring your own API keys for connector integrations (Google Drive, OneDrive, Notion).
|
||||
|
||||
### Google Sheets & Slides
|
||||
|
||||
Google Drive connector now supports Sheets and Slides alongside Docs.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 12, 2025" tags={["Console", "API"]}>
|
||||
|
||||
### Console Dashboard
|
||||
|
||||
First version of the dashboard overview page with memory analytics, container tag distribution charts, and usage metrics.
|
||||
|
||||
### Google Drive Webhooks
|
||||
|
||||
Real-time sync — Google Drive changes are automatically detected and processed.
|
||||
|
||||
### Sentry Integration
|
||||
|
||||
Error monitoring added across the console and API.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 28, 2025" tags={["API", "Console"]}>
|
||||
|
||||
### Launch-Ready API
|
||||
|
||||
Console reached launchable state with login page improvements, auth fixes, and the first version of the new dashboard with React Query.
|
||||
|
||||
### Infinite Chat
|
||||
|
||||
Memory Router proxy with automatic context compression for infinite-length conversations with LLMs.
|
||||
|
||||
### Container Tags in Search
|
||||
|
||||
Filter search results by container tags for scoped memory retrieval.
|
||||
|
||||
### Google Docs MD Export
|
||||
|
||||
Google Drive connector switched from PDF to Markdown export for better content fidelity.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 8, 2025" tags={["API"]}>
|
||||
|
||||
### API v3
|
||||
|
||||
New `/v3/` endpoints replacing v2 — cleaner routes, updated memory endpoint, and new update/delete operations.
|
||||
|
||||
### OneDrive Connector
|
||||
|
||||
Initial OneDrive integration for syncing files into Supermemory.
|
||||
|
||||
### Connections Architecture
|
||||
|
||||
New connection-document relationship model for tracking which connector synced which document.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 30, 2025" tags={["API"]}>
|
||||
|
||||
### Comprehensive API Documentation
|
||||
|
||||
New interactive API references on Mintlify with detailed parameter explanations, response schemas, and bearer auth.
|
||||
|
||||
### Container Tags System
|
||||
|
||||
Enhanced organizational grouping for better memory isolation and user-scoped content.
|
||||
|
||||
### Auto Content Type Detection
|
||||
|
||||
Automatic processing of PDFs, images, videos, and web content regardless of URL extensions.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 28, 2025" tags={["API"]}>
|
||||
|
||||
### Google Drive Connector
|
||||
|
||||
New endpoints for programmatic Google Drive integration and file syncing.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 25, 2025" tags={["API"]}>
|
||||
|
||||
### Search Improvements
|
||||
|
||||
- **`documentThreshold` and `chunkThreshold`** — fine-tune search sensitivity.
|
||||
- **`docId` parameter** — search within specific large documents.
|
||||
- **`onlyMatchingChunks`** — precise result filtering.
|
||||
- **`endUserId` filtering** — scope search to specific users.
|
||||
- **Reranking** — improved result quality with a reranking step.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 22, 2025" tags={["API", "MCP"]}>
|
||||
|
||||
### Supermemory MCP Server
|
||||
|
||||
First version of the MCP server for AI model integrations.
|
||||
|
||||
### Personalisation
|
||||
|
||||
AI-generated personalization based on user memory patterns.
|
||||
|
||||
### List Memories Endpoint
|
||||
|
||||
First version of the list memories API with pagination.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 14, 2025" tags={["API"]}>
|
||||
|
||||
### Team API
|
||||
|
||||
Organization invites and user management endpoints.
|
||||
|
||||
### Analytics API
|
||||
|
||||
Hourly analytics tracking with detailed usage metrics.
|
||||
|
||||
### Content Processing Pipeline
|
||||
|
||||
New ingestion workflow with status tracking: `queued` → `extracting` → `chunking` → `embedding` → `done`.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="March 27, 2025" tags={["API"]}>
|
||||
|
||||
### Connections System
|
||||
|
||||
First version of the connectors architecture — sync external data sources into Supermemory.
|
||||
|
||||
### Tag-Based Filtering
|
||||
|
||||
Filter memories by tags in search and list operations.
|
||||
|
||||
### Advanced Analytics
|
||||
|
||||
Request tracking, error counts, and usage metrics per organization.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="March 18, 2025" tags={["API"]}>
|
||||
|
||||
### Supermemory API v2
|
||||
|
||||
The platform begins — Cloudflare Workers API with auth, ingestion workflows, vector search, and organization support. Built on Hono, Drizzle ORM, and Cloudflare D1/Hyperdrive.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="January 20, 2025" tags={["Console"]}>
|
||||
|
||||
### Supermemory v2 Release
|
||||
|
||||
Major release of the consumer web app with new import tools (CSV, Markdown/Obsidian), improved hybrid search with date relevancy, batch delete, and space management (edit/delete names).
|
||||
|
||||
### Docs Site Launch
|
||||
|
||||
First version of the documentation site with API reference, getting started guide, and pricing page.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="August 16, 2024" tags={["Console"]}>
|
||||
|
||||
### Supermemory v1 — Major Update
|
||||
|
||||
New consumer app version with canvas/note editor, text-to-speech on AI answers, PWA support, improved Telegram bot with Markdown, and memory queue processing. Extension gets drag-and-dismiss features.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="July 21, 2024" tags={["Console"]}>
|
||||
|
||||
### ProductHunt Launch
|
||||
|
||||
Supermemory launches on ProductHunt. Features at launch: shareable spaces, Twitter thread import, AI chat with citations, onboarding flow, recommended items, chat history, and keyboard shortcuts.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 23, 2024" tags={["Console"]}>
|
||||
|
||||
### Multi-Turn Chat & Canvas
|
||||
|
||||
Added multi-turn conversations, canvas with drag-and-drop, Telegram bot, vector lookup 2x speedup, and the first version of the Chrome extension.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 18, 2024" tags={["API"]}>
|
||||
|
||||
### Backend Rewrite to Hono
|
||||
|
||||
Backend migrated from Next.js API routes to Hono on Cloudflare Workers. Landing page redesign, browser rendering for web content extraction.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="April 11, 2024" tags={["Console"]}>
|
||||
|
||||
### Supermemory v1 Launch
|
||||
|
||||
First public release — spaces, chat with AI, Twitter bookmarks import, Chrome extension with save-from-page, notes editor, and search across all saved content.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="February 21, 2024" tags={["Console"]}>
|
||||
|
||||
### Supermemory is Born
|
||||
|
||||
Initial monorepo setup with auth, Chrome extension, AI chat with citations using OpenAI embeddings, and the first version of the web app.
|
||||
|
||||
</Update>
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
---
|
||||
title: "Plugin changelog"
|
||||
sidebarTitle: "Plugins"
|
||||
description: "Recent updates and improvements to Supermemory plugins"
|
||||
---
|
||||
|
||||
<Update label="June 20, 2026" tags={["OpenCode", "Cursor"]}>
|
||||
|
||||
### OpenCode entity context
|
||||
|
||||
OpenCode now sends entity context with memory operations, so saved context can stay tied to the active project and conversation. The entity-context prompt was also moved out of the API client for cleaner reuse across capture and compaction flows.
|
||||
|
||||
### Cursor session auth
|
||||
|
||||
Cursor now starts the auth flow from the session hook when needed, and the OAuth success screen uses the Cursor-branded callback path.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 18, 2026" tags={["Claude Code", "OpenCode"]}>
|
||||
|
||||
### Claude Code update notices
|
||||
|
||||
Claude Code now surfaces plugin update notices during sessions and includes the latest package/version metadata.
|
||||
|
||||
### OpenCode context prompt
|
||||
|
||||
OpenCode gained an entity-context prompt so memory recall and capture can carry more precise source context.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 13, 2026" tags={["Claude Code", "Codex"]}>
|
||||
|
||||
### Claude Code marketplace polish
|
||||
|
||||
The Claude Code plugin manifest was polished for the official marketplace listing, including refreshed metadata and naming.
|
||||
|
||||
### Codex update notices
|
||||
|
||||
Codex now checks for plugin updates during session start and shows a user-visible notice when a newer version is available.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 11, 2026" tags={["Claude Code", "Cursor"]}>
|
||||
|
||||
### Claude Code rename migration
|
||||
|
||||
Claude Code completed the rename to the `supermemory` plugin while keeping migration safe for users already on the new plugin name. Configuration also supports custom `baseUrl` values for local or self-hosted Supermemory installs.
|
||||
|
||||
### Cursor web OAuth
|
||||
|
||||
Cursor OAuth now routes through the Supermemory web app, keeping the plugin auth flow consistent with the rest of the integrations.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 10, 2026" tags={["Codex", "OpenCode"]}>
|
||||
|
||||
### Codex auth and status tooling
|
||||
|
||||
Codex added status, logout, and web-auth flows, plus Windows-safe auth URL opening and entity context for saved memories. The installer now includes a `supermemory-status` skill so Codex can report connection, hook, config, and installed-skill health from inside a session.
|
||||
|
||||
### OAuth status refinements
|
||||
|
||||
Codex and OpenCode integration status now renders more clearly in the Supermemory app during OAuth connection and setup.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="June 6, 2026" tags={["Claude Code", "Cursor", "OpenClaw", "Hermes"]}>
|
||||
|
||||
### Claude Code recall reasoning
|
||||
|
||||
Claude Code gained reasoned per-turn memory recall with auto-approve support, refreshed bundled scripts, and updated skill names for `supermemory-save` and `supermemory-search`.
|
||||
|
||||
### Cursor session hooks
|
||||
|
||||
Cursor session hooks now load reliably and persist real project sessions into the correct container.
|
||||
|
||||
### OpenClaw and Hermes memory attribution
|
||||
|
||||
Saved plugin memories now parse source attribution more accurately, and the dashboard shows the correct plugin logos and recent-memory rows for OpenClaw and Hermes.
|
||||
|
||||
</Update>
|
||||
97
apps/docs/company-brain/automations.mdx
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
title: "Automations and Proactiveness"
|
||||
sidebarTitle: "Automations"
|
||||
description: "Scheduled work Company Brain runs on its own, and when it speaks without being asked"
|
||||
icon: "bot"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention, ChannelRef } from "/snippets/slack-message.mdx";
|
||||
|
||||
Company Brain doesn't only answer when you @mention it. It can run recurring work on a schedule, and it can speak in a thread on its own when it has something genuinely worth saying. Both are opt-in, both are rate-limited, and both read from exactly the same [permissions graph](/company-brain/permissions) as a normal question — neither is a backdoor around it.
|
||||
|
||||
## Automations
|
||||
|
||||
An automation is a prompt that runs on a schedule and posts the result somewhere. You write it once, in plain language:
|
||||
|
||||
<SlackThread channel="#product">
|
||||
<SlackMessage self time="9:03 AM">
|
||||
<Mention>supermemory</Mention> every Monday at 9am, post a digest of what shipped last week and what's still open, to <ChannelRef>product</ChannelRef>.
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="9:03 AM">
|
||||
Got it — scheduled. First digest posts Monday, 9:00 AM, to <ChannelRef>product</ChannelRef>.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
<Steps>
|
||||
<Step title="Schedule fires">
|
||||
The automation wakes up at its set time — no one has to trigger it.
|
||||
</Step>
|
||||
<Step title="Gathers context">
|
||||
It reads using only **org-shared** connections and channel memory — never a person's personal credentials, even if the person who created the automation has better personal access. This is what keeps a scheduled post from silently acting as a specific teammate.
|
||||
</Step>
|
||||
<Step title="Checks visibility">
|
||||
Before posting, it re-confirms it can still see the destination channel.
|
||||
</Step>
|
||||
<Step title="Posts, or fails closed">
|
||||
If anything above is unclear — a connection broke, visibility can't be verified — it skips that run rather than posting a guess. Silence beats a wrong digest.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
**Who can target what:**
|
||||
|
||||
| Destination | Who can create it | Reads from |
|
||||
|---|---|---|
|
||||
| Public channel | Any member | Org-shared connections, public channel memory |
|
||||
| Private channel | Admins only | Org-shared connections, that channel's memory |
|
||||
| DM to yourself | The owner of that DM | Your personal + org connections, your employee memory |
|
||||
|
||||
Common shapes worth stealing:
|
||||
|
||||
- A Monday-morning digest of open items and unanswered questions
|
||||
- A daily Sentry error recap in `#eng`
|
||||
- A weekly "what changed across our connected tools" summary
|
||||
|
||||
Anyone can create and manage their own automations; admins can manage everyone's. Ask Company Brain in Slack to set one up, or manage the full list from the web app.
|
||||
|
||||
## Proactiveness (chime-in)
|
||||
|
||||
Chime-in is different from an automation: there's no schedule, and no one asked. Company Brain is simply present in a channel — because an admin invited it — and it speaks up when staying quiet would waste someone's time.
|
||||
|
||||
**What actually earns a chime-in:**
|
||||
|
||||
- It has to add something the room doesn't already have — a fact, a correction, a next step — not agreement or a restatement of what's already visible.
|
||||
- It has to come from somewhere it's genuinely allowed to look: [connected tools](/company-brain/connectors) or that room's own memory, same as any other answer.
|
||||
- If it isn't confident the answer is actually correct, it says nothing. A wrong guess is worse than silence, so uncertainty resolves to silence, not a hedge.
|
||||
|
||||
<CodeGroup>
|
||||
```text Worth chiming in
|
||||
"is prod down? customers are pinging me"
|
||||
→ correlates against Sentry, replies with what's actually elevated right now
|
||||
```
|
||||
|
||||
```text Not worth it
|
||||
"finally shipped this 🎉" (screenshot, no question)
|
||||
→ stays quiet — there's nothing to add
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Guardrails that keep it from becoming noise:**
|
||||
|
||||
- **Rate-limited.** It won't speak repeatedly in the same thread or channel in a short window, even if it technically could add something each time.
|
||||
- **Invite-only rooms.** It never joins a channel on its own — only places an admin already invited it into.
|
||||
- **Same graph as a normal answer.** A private channel's chime-in only ever draws on that channel's memory and public channel memory — never another private channel, never someone else's employee memory.
|
||||
|
||||
An explicit @mention always skips this judgment call entirely — naming it is you deciding it should speak, so it does.
|
||||
|
||||
<Note>
|
||||
Automations and chime-in both write back to memory the same way a normal conversation does: a public channel's automation output lands in public channel memory, a private channel's chime-in stays scoped to that channel's memory.
|
||||
</Note>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="What you can do" icon="sparkles" href="/company-brain/use-cases/overview">
|
||||
Real scenarios — support, incidents, digests, and more.
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Wire up the tools automations and chime-in draw from.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
64
apps/docs/company-brain/connectors.mdx
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
title: "Connectors"
|
||||
sidebarTitle: "Connectors"
|
||||
description: "Bring knowledge in with data connectors, and act in live tools with tool connectors"
|
||||
icon: "plug"
|
||||
---
|
||||
|
||||
Company Brain has two kinds of connectors. They look similar on the connections page, but they do different jobs:
|
||||
|
||||
| | Data connectors | Tool connectors |
|
||||
|---|---|---|
|
||||
| **What they do** | Bring knowledge *in* | Let the agent *act* in the tool |
|
||||
| **Examples** | Google Drive, Notion, OneDrive | GitHub, Linear, Sentry, Plain, PostHog, Granola |
|
||||
| **Result** | Docs land in public channel memory and stay searchable | Live reads and writes (list PRs, create issues, check errors) |
|
||||
| **When it runs** | Background sync on a schedule | In the moment you ask |
|
||||
|
||||
## Data connectors
|
||||
|
||||
Data connectors sync existing files and docs into **public channel memory** so answers are grounded in real material — roadmaps, specs, handbooks, design docs.
|
||||
|
||||
How it works:
|
||||
|
||||
1. An admin connects a source (Drive, Notion workspace, OneDrive, and similar).
|
||||
2. Company Brain fetches, chunks, embeds, and indexes the content in the background.
|
||||
3. It re-syncs on a schedule automatically — you don't re-upload when a doc changes.
|
||||
|
||||
Connecting a data source is a **team-level action**. What comes in is visible org-wide, same as anything from a public channel — see the [permissions graph](/company-brain/permissions) for exactly who can read what.
|
||||
|
||||
<Note>
|
||||
A data connector is only as useful as the docs you point it at. Start with the handful of sources people actually re-read — product specs, the handbook, the latest roadmap — rather than every folder in Drive.
|
||||
</Note>
|
||||
|
||||
## Tool connectors
|
||||
|
||||
Tool connectors are live integrations (MCP-based under the hood). They don't just index past content — they read and act in the tool *right now*:
|
||||
|
||||
- **GitHub** — open PRs, recent commits, repo context
|
||||
- **Linear** — find or create issues, check status
|
||||
- **Sentry** — what's actually erroring in prod
|
||||
- **Plain** — customer support tickets and history
|
||||
- **PostHog** — product analytics
|
||||
- **Granola** — meeting notes and decisions
|
||||
- **Custom servers** — wire up your own MCP endpoint when the catalog doesn't cover a tool
|
||||
|
||||
You can also connect tools at two scopes — **Organization (shared)** or **Personal (yours)**. The full rule of thumb lives on [The permissions graph](/company-brain/permissions): reads prefer your personal connection and fall back to the org one; writes always run under your own account so the action is attributed to you.
|
||||
|
||||
If neither you nor the org has a tool connected, but a teammate does, Company Brain can ask them to **lease** temporary access for that one request — see [Leasing](/company-brain/permissions#leasing-borrowing-access-for-one-request).
|
||||
|
||||
## Which one do I need?
|
||||
|
||||
- **"What's in our Q2 roadmap?"** → data connector (Drive/Notion/OneDrive already synced)
|
||||
- **"What are my open PRs?"** or **"Create a Linear issue"** → tool connector (GitHub / Linear)
|
||||
- **"What did we decide in the Acme call?"** → tool connector that also brings knowledge in (Granola), or a data connector if notes live in Drive/Notion
|
||||
|
||||
You almost always want both: data connectors for the long-lived knowledge base, tool connectors for the live work happening this week.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Automations & proactiveness" icon="wand-magic-sparkles" href="/company-brain/automations">
|
||||
Scheduled digests and unprompted replies that use these connections.
|
||||
</Card>
|
||||
<Card title="What you can do" icon="sparkles" href="/company-brain/use-cases/overview">
|
||||
Walkthroughs of support, incidents, PRs, meetings, and more.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
52
apps/docs/company-brain/outside-slack.mdx
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
title: "Using Outside Slack"
|
||||
sidebarTitle: "Outside Slack"
|
||||
description: "Reach the same permissions graph from Claude Code, ChatGPT, Cursor, or any MCP client"
|
||||
icon: "globe"
|
||||
---
|
||||
|
||||
Slack is the default surface, not the only one. Company Brain speaks MCP, so the same graph — your employee memory, the private channels you're in, public channel memory — is reachable from any MCP client: Claude Code, ChatGPT, Cursor, or anything else that speaks the protocol.
|
||||
|
||||
## Connect
|
||||
|
||||
Same endpoint as [Supermemory MCP](/supermemory-mcp/mcp) — there's no separate Company Brain server to point at:
|
||||
|
||||
```text
|
||||
https://mcp.supermemory.ai/mcp
|
||||
```
|
||||
|
||||
OAuth by default — your client discovers the authorization server and prompts you to sign in. Prefer an API key instead? Any key starting with `sm_` skips OAuth entirely.
|
||||
|
||||
<Note>
|
||||
What changes isn't the URL, it's what shows up once you're connected. If your account belongs to an org with Company Brain, you get more than your own project spaces — your employee memory, the private channels you're in, and public channel memory all become available as workspaces, carrying your role and the exact same read/write access Slack already enforces.
|
||||
</Note>
|
||||
|
||||
## Pick a workspace
|
||||
|
||||
Once connected, ask it what's available — it returns every container tag you have access to: your employee memory, each private channel memory you belong to, and public channel memory. Select one to make it the active workspace for the session; everything after that scopes to it automatically.
|
||||
|
||||
**Example:** from Claude Code, "what can I access in Acme's Company Brain?" surfaces your options as a picker — your employee memory, `#eng`'s private channel memory if you're in it, public channel memory. Pick one, and every search or save for the rest of the session happens inside it — the same as asking from that room in Slack.
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | What it does |
|
||||
|---|---|
|
||||
| `listContainerTags` | Everything you're allowed to read, with names and counts |
|
||||
| `select-workspace` / `set-active-tag` | Pick which one is active for this session |
|
||||
| `recall` | Search the active workspace, plus a profile summary when you're in your employee memory |
|
||||
| `save-memory` | Write back to the active workspace |
|
||||
| `memory-graph` | An interactive, visual map of a workspace's memories |
|
||||
| `whoAmI` | Your role, access type, and active workspace — useful for sanity-checking what a client can actually see |
|
||||
|
||||
## Same graph, same guardrails
|
||||
|
||||
Nothing here is a side door. What you can reach follows the exact same [permissions graph](/company-brain/permissions) as Slack — an admin can restrict a member's connection to specific container tags the same way they'd scope a Slack channel invite, and every read or write is checked against that before it runs.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="The permissions graph" icon="shield-check" href="/company-brain/permissions">
|
||||
What each container tag actually is, and who can read it.
|
||||
</Card>
|
||||
<Card title="Supermemory MCP" icon="brain-circuit" href="/supermemory-mcp/mcp">
|
||||
Base setup, auth, and personal project spaces on the same server.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
94
apps/docs/company-brain/overview.mdx
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
title: "What is Supermemory Company Brain?"
|
||||
sidebarTitle: "Overview"
|
||||
description: "A super agent, with all the knowledge and tools of your team"
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention, ChannelRef, AgentLink } from "/snippets/slack-message.mdx";
|
||||
|
||||
Supermemory Company Brain is a super agent with shared memory for your team that you can **ask questions** and that can **act in your tools**. It pulls from the work you already do - Slack threads, docs, GitHub, Linear - And can pretty much act as a real employee in your team.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Remembers" icon="brain">
|
||||
Meetings, decisions, projects, and who owns what — kept current as your connected sources sync.
|
||||
</Card>
|
||||
<Card title="Acts" icon="bolt">
|
||||
Pulls your open PRs, finds a Linear issue, or answers in a Slack channel — not just recites text back.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## A quick example of its capabilities
|
||||
|
||||
It'll answer a question, actually go do the work, or just jump into a conversation on its own when it's got something worth saying — like a coworker would, not a search bar. You can configure how funny and unhinged it is, or how of it you want.
|
||||
|
||||
### Ask it anything
|
||||
|
||||
<SlackThread channel="#product">
|
||||
<SlackMessage self time="10:42 AM">
|
||||
<Mention>supermemory</Mention> what did we decide about pricing for the company brain
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="10:42 AM">
|
||||
You and mahesh decided yesterday that it stays at **$400/mo**, usage based only. we landed on that in a <ChannelRef>product</ChannelRef> huddle
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
### Put it to work
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage self time="3:24 PM">
|
||||
<Mention>supermemory</Mention> is the Stripe webhook timeout from Sentry already tracked anywhere?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="3:25 PM">
|
||||
nope, nothing yet — just opened **ENG-847** for it, added the sentry issue to it, and put it on <Mention>Sam</Mention> since they were the last one in `webhooks/stripe.ts` and their beautiful code broke it ☠️. <AgentLink href="https://linear.app">here you go</AgentLink>, should probably fix it asap.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
### Let it speak up on its own
|
||||
|
||||
<SlackThread channel="#eng" members={48}>
|
||||
<SlackMessage name="Alex" color="#E01E5A" time="11:03 AM">
|
||||
is prod down? a couple of customers are pinging me
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="11:03 AM">
|
||||
not fully down — `api/search` is just elevated, 42 errors in the last 15 min (SM-2041), and <Mention>Kush</Mention> is on it. probably that deploy from this morning. Only one user has complained on support and i already replied to them saying it's being investigated.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
You don't need to mention it. It speaks up when it has something to add. It's smart and proactive!
|
||||
|
||||
## Same knowledge, useful everywhere
|
||||
|
||||
It's your team's knowledge — it doesn't have to stay in Slack. Take it wherever you're actually working:
|
||||
|
||||
- **Your coding agent** — ask Claude Code or Cursor mid-session what the team decided, why a file looks the way it does, or who to ping about it, without tabbing over to Slack.
|
||||
- **Your own tools, via MCP** — Company Brain speaks MCP, so if whatever you're building can speak MCP too, it can ask. Plug it into an internal tool, a script, whatever you need.
|
||||
|
||||
Same permissions graph everywhere, no exceptions — asking from Claude Code doesn't get you anything asking from Slack wouldn't.
|
||||
|
||||
```text
|
||||
> is the stripe webhook thing from earlier actually fixed?
|
||||
yep — Sam shipped it in ENG-847 about an hour ago, Sentry's been quiet since
|
||||
```
|
||||
|
||||
This knowledge can be used wherever you and your teammates go — see [Using outside Slack](/company-brain/outside-slack) for how to connect.
|
||||
|
||||
## Use it your way
|
||||
|
||||
Company Brain isn't locked to one model or one voice. Two things you control directly:
|
||||
|
||||
- **Any model, no markup** — bring your own LLM and pay nothing extra for inference.
|
||||
- **Its tonality** — configure how it talks, from buttoned-up professional to fully unhinged. Make it sound like your team, not a generic chatbot.
|
||||
|
||||
## Where to go next
|
||||
|
||||
Company Brain has a handful of ideas worth understanding before you set it up: Our permissioning setup, how to configure it, proactiveness, automations, and more.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="The permissions graph" icon="shield-check" href="/company-brain/permissions">
|
||||
What's remembered where, and who can read it.
|
||||
</Card>
|
||||
<Card title="Setup and onboarding" icon="rocket" href="/company-brain/setup">
|
||||
Get your team's workspace running.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
91
apps/docs/company-brain/permissions.mdx
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
title: "The Permissions Graph"
|
||||
sidebarTitle: "Permissions"
|
||||
description: "What Company Brain remembers, who it's visible to, and how tool access is scoped"
|
||||
icon: "shield-check"
|
||||
---
|
||||
|
||||
Company Brain isn't split into "a shared brain" and "a private brain." It's a graph: memory is written to the narrowest room a conversation happened in, and what a given conversation can *read* depends on where it's happening and who's asking. Nothing here is silent — every install, channel read, and temporary access grant requires an explicit accept from a real person.
|
||||
|
||||
## Three memories, not two
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Employee memory" icon="user">
|
||||
One per person. Built from your DMs with the bot and what it learns about you over time. Only visible from your own DM.
|
||||
</Card>
|
||||
<Card title="Private channel memory" icon="lock">
|
||||
One per private channel. Scoped to that room — visible to anyone in it, to no one outside it.
|
||||
</Card>
|
||||
<Card title="Public channel memory" icon="hash">
|
||||
One per organization. Anything durable from a public channel lands here. The whole org can draw on it.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
A message writes to exactly one of these — whichever room it happened in.
|
||||
|
||||
## What a conversation can read
|
||||
|
||||
Writing is narrow; reading is broader, and it widens the more private the room is:
|
||||
|
||||
| Asking from | Can read |
|
||||
|---|---|
|
||||
| A public channel | Public channel memory |
|
||||
| A private channel | That channel's memory + public channel memory |
|
||||
| A DM with the bot | Your employee memory + public channel memory + every private channel memory you belong to |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Pub["Public channel memory<br/>(the whole org)"]
|
||||
Priv["Private channel memory<br/>(that room's members)"]
|
||||
Emp["Employee memory<br/>(you, in DM)"]
|
||||
|
||||
Priv -.reads.-> Pub
|
||||
Emp -.reads.-> Pub
|
||||
Emp -.reads.-> Priv
|
||||
```
|
||||
|
||||
A DM is the widest seat in the room precisely because it's the most private one — the bot answers you there with everything *you* could see, stitched together. A public channel is the opposite: the whole org can read it, so it only ever draws on what the whole org is allowed to know.
|
||||
|
||||
<Note>
|
||||
If you're not in a private channel, its memory doesn't exist for you — not even by inference in a DM. The bot only ever reads with the asker's own access, so it can't surface something you couldn't otherwise see.
|
||||
</Note>
|
||||
|
||||
**Example:** you DM the bot asking "what did we decide about the Acme deal?" It can draw on the public `#sales` channel, the private `#acme-deal` channel if you're in it, and anything it's learned about you directly — and it'll cite which one the answer came from. Ask the same question in `#general`, a public channel, and it can only answer from what `#general` and other public channels already know — the private `#acme-deal` context simply isn't in scope there.
|
||||
|
||||
## Tool access follows you, not the connection
|
||||
|
||||
Tools like GitHub and Linear can be connected two ways — **Organization (shared)**, set up once by an admin as a fallback the whole team can read from, or **Personal (yours)**, your own connection for your own reads and actions. Both show up on the same connections page; it's one tool catalog, connected at two possible scopes.
|
||||
|
||||
Whichever scope answered, the result is still bounded by what *you* could already see or do in that tool yourself — Company Brain never gets a standing key to "everything Linear knows." If you're not on a private Linear team, the bot can't surface those issues to you either, even through the org-shared connection.
|
||||
|
||||
| | Reads | Writes |
|
||||
|---|---|---|
|
||||
| **Behavior** | Try your personal connection first, then fall back to org-shared | Always run under your own connection |
|
||||
| **Why** | Gives you the fullest access you're entitled to | Attributes the action to a real person, never a shared service account |
|
||||
|
||||
Admins can also act through the org-shared connection directly, for the cases where that's the point.
|
||||
|
||||
## Leasing: borrowing access for one request
|
||||
|
||||
Sometimes a request needs a tool neither you nor the org has connected — but a teammate has it connected personally. Rather than failing, Company Brain can ask that teammate directly: it posts a card in Slack asking them to approve or deny lending access for that one request.
|
||||
|
||||
- Nothing is granted silently — a real person has to accept the card.
|
||||
- Access is short-lived and scoped to the single request that triggered it, not standing access to your account.
|
||||
- The teammate can say no, and the request simply doesn't go through.
|
||||
|
||||
<Note>
|
||||
Leasing is a fallback of last resort — it only comes up when nobody's connected the tool at the org level yet. See [Connectors](/company-brain/connectors) to close that gap for good.
|
||||
</Note>
|
||||
|
||||
## API keys inherit the same graph
|
||||
|
||||
A scoped or agent API key can only reach what its owner could already reach by asking directly. A member can't mint a key that reads another member's employee memory or a private channel they're not in — the graph above applies identically whether a person is asking or a key is.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Set up the data and tool connections this page describes.
|
||||
</Card>
|
||||
<Card title="Automations & proactiveness" icon="wand-magic-sparkles" href="/company-brain/automations">
|
||||
How scheduled runs and unprompted replies respect the same graph.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
87
apps/docs/company-brain/setup.mdx
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
title: "Setup and Onboarding"
|
||||
sidebarTitle: "Setup"
|
||||
description: "Creating a team workspace and installing it into Slack"
|
||||
icon: "rocket"
|
||||
---
|
||||
|
||||
Setting up Company Brain is two admin steps: create the workspace, then install it into Slack. Everyone else joins on their own after that — see [Greeting new teammates](/company-brain/use-cases/greeting).
|
||||
|
||||
## 1. Create your team workspace
|
||||
|
||||
Creating a workspace sets up your shared **Team Brain** and your private **My Brain** in one step.
|
||||
|
||||
<Steps>
|
||||
<Step title="Sign up">
|
||||
Head to [app.supermemory.ai](https://app.supermemory.ai) and create an account.
|
||||
</Step>
|
||||
<Step title="Choose Team">
|
||||
On the **About** step, switch from **Personal** to **Team**.
|
||||
|
||||
<Note>
|
||||
Team workspaces are invite-only during the private beta. Not invited yet? Email **support@supermemory.com**, or start Personal and invite your team once you're in.
|
||||
</Note>
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Add your company domain and confirm">
|
||||
Enter your domain (for example `acme.com`) and confirm. Supermemory researches the company from there and seeds a starting profile, before any source finishes syncing.
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Add to Slack, connect apps, and invite your team">
|
||||
All three run in parallel with research, and none of them block it:
|
||||
|
||||
- **Add to Slack** — kicks off the install flow below.
|
||||
- **Connect apps** — Linear, Granola, Sentry, and more.
|
||||
- **Invite teammates** — now, not later. No per-seat pricing, so invite everyone in your Slack.
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="You're ready">
|
||||
Supermemory's already learned a real amount about your company by the time research finishes. Watch Slack for a DM from it walking you through what it can do.
|
||||
|
||||

|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
**Try it:** ask `What does {your company} do?` — you should get a real answer from the seeded profile.
|
||||
</Note>
|
||||
|
||||
## 2. Install into Slack (admin)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Don't have a Slack workspace yet?">
|
||||
Go to [app.slack.com](https://app.slack.com) to create one first — Company Brain installs into an existing workspace, it doesn't create one for you.
|
||||
|
||||

|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Steps>
|
||||
<Step title="Confirm company and domain">
|
||||
Click **Install to Slack**. Not an admin? This triggers Slack's own request-to-install flow instead.
|
||||
</Step>
|
||||
<Step title="Hand off to Slack">
|
||||
The web app hands off immediately — "we've DM'd you in Slack."
|
||||
</Step>
|
||||
<Step title="Home channel">
|
||||
The agent creates `#company-brain`, posts an intro there, and announces itself once in `#general`.
|
||||
</Step>
|
||||
<Step title="Approve channels to read">
|
||||
You approve each channel with a tap — it never joins one silently.
|
||||
</Step>
|
||||
<Step title="Add your team">
|
||||
Invite people with a picker, a workspace-wide toggle, or email.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Greeting new teammates" icon="user-plus" href="/company-brain/use-cases/greeting">
|
||||
What member join looks like from a new hire's side.
|
||||
</Card>
|
||||
<Card title="The permissions graph" icon="shield-check" href="/company-brain/permissions">
|
||||
What each person can see once they're in.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
54
apps/docs/company-brain/use-cases/acting-in-tools.mdx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: "Acting in Tools"
|
||||
sidebarTitle: "Acting in Tools"
|
||||
description: "List open PRs, create Linear issues — actions run under your own account"
|
||||
icon: "wrench"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention, AgentLink } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
You don't just want to *know* something — you want Company Brain to do the next step in GitHub or Linear for you.
|
||||
|
||||
## What happens
|
||||
|
||||
### Read from a tool
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage self time="3:22 PM">
|
||||
<Mention>supermemory</Mention> what are my open PRs in the web repo?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="3:22 PM">
|
||||
You have **3 open PRs** on `supermemory/web`:
|
||||
- `#1199` staff custom MCP connection cards — review requested
|
||||
- `#1197` company brain onboarding research UI — changes requested
|
||||
- `#1181` brain connections board — approved, not merged
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
### Write to a tool
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage self time="3:24 PM">
|
||||
<Mention>supermemory</Mention> create a Linear issue: fix the onboarding redirect
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="3:24 PM">
|
||||
Created **ENG-842** — *Fix the onboarding redirect* in Engineering, assigned to you. <AgentLink href="https://linear.app">Open in Linear</AgentLink>
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
Both turns use [tool connectors](/company-brain/connectors) (GitHub, Linear). Reads try your **personal** connection first and fall back to the org-shared one. **Writes always run under your own account** — so the Linear issue is attributed to you, never silently as "the org."
|
||||
|
||||
If you haven't connected the tool and neither has the org, Company Brain can ask a teammate to [lease](/company-brain/permissions#leasing-borrowing-access-for-one-request) temporary access for that one request.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Permissions" icon="shield-check" href="/company-brain/permissions">
|
||||
Personal vs org tools, and how leasing works.
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Connect GitHub, Linear, and the rest.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
50
apps/docs/company-brain/use-cases/greeting.mdx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
title: "Greeting New Teammates"
|
||||
sidebarTitle: "Greeting Teammates"
|
||||
description: "Connect card, welcome DM, and first answer — activation on day one"
|
||||
icon: "user-plus"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, BOT_AVATAR } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
A new hire joins the Slack workspace. They shouldn't need a web signup form or a long handbook read before Company Brain is useful — the whole first experience happens in Slack.
|
||||
|
||||
## What happens
|
||||
|
||||
They get a connect card, tap **Connect me**, and receive a welcome DM:
|
||||
|
||||
<SlackThread type="dm" dmWith={{ name: "supermemory", avatar: BOT_AVATAR }}>
|
||||
<SlackMessage bot time="9:02 AM">
|
||||
Welcome to **Acme**. Here's what I know, what I can access, and what I keep private.
|
||||
|
||||
Try one of these:
|
||||
1. What does Acme do?
|
||||
2. Who owns onboarding?
|
||||
3. Where do we track bugs?
|
||||
</SlackMessage>
|
||||
<SlackMessage name="Sam" color="#36C5F0" time="9:03 AM">
|
||||
What does Acme do?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="9:03 AM">
|
||||
Acme builds memory infrastructure for AI apps — shared context for teams and agents. *(from the company profile your admin seeded at setup)*
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
Right after the first answer, they're prompted to connect personal tools (Linear, Notion) so day-two questions can hit live data.
|
||||
|
||||
## What's really going on
|
||||
|
||||
This is the [member join flow](/company-brain/setup) told as a scenario. Tapping **Connect me** creates a passwordless account from their Slack email, provisions their private [employee memory](/company-brain/permissions), and consumes a seat. The three starter questions are seeded so the first useful answer happens on the first tap — that's the activation moment.
|
||||
|
||||
No web app required for the new hire. Admins still do the one-time workspace + Slack install on the web.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Setup and onboarding" icon="rocket" href="/company-brain/setup">
|
||||
The full admin + member flow.
|
||||
</Card>
|
||||
<Card title="Permissions" icon="shield-check" href="/company-brain/permissions">
|
||||
Employee memory vs. public and private channel memory.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
46
apps/docs/company-brain/use-cases/incidents.mdx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
title: "Incidents & Downtime Chatter"
|
||||
sidebarTitle: "Incidents"
|
||||
description: "Answer 'is prod down?' from live Sentry, and post scheduled error digests"
|
||||
icon: "triangle-alert"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, AgentLink } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
Someone drops a vague "is prod down?" in `#eng`. Company Brain correlates it with what's actually failing right now — and a separate automation keeps a daily error digest flowing without anyone asking.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#eng" members={48}>
|
||||
<SlackMessage name="Alex" color="#E01E5A" time="11:03 AM">
|
||||
is prod down? a couple of customers are pinging me
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="11:03 AM">
|
||||
Not a full outage — **`api/search` is elevated** (42 errors in the last 15m, mostly `timeout on vectorize`). Sentry issue <AgentLink href="https://example.com">SM-2041</AgentLink>. Deploy from this morning is the likely culprit; rollback candidate is `af61880`.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
Or, without anyone asking, a scheduled automation posts every morning:
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage bot time="9:00 AM">
|
||||
**Daily error digest** — 3 issues new since yesterday, 1 still spiking (`api/search` timeout). Full list in Sentry.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
The first exchange is a [chime-in](/company-brain/automations) (or an @mention — either works) that hits the **Sentry** [tool connector](/company-brain/connectors) for live error data. The second is an [automation](/company-brain/automations): a recurring prompt on a cron that posts to a channel using org-shared connections only, so it never runs as a specific person.
|
||||
|
||||
If the channel is private, only an admin can target it with an automation, and the bot fails closed if it can't verify visibility.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Connect Sentry (and friends) for live incident context.
|
||||
</Card>
|
||||
<Card title="Automations" icon="wand-magic-sparkles" href="/company-brain/automations">
|
||||
Schedule digests and understand chime-in.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
43
apps/docs/company-brain/use-cases/knowledge-recall.mdx
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
title: "Answering from Your Docs"
|
||||
sidebarTitle: "From Docs"
|
||||
description: "Ask about roadmaps, specs, and handbooks in plain language"
|
||||
icon: "book"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
The Q2 roadmap lives in Notion. Nobody wants to dig for the link mid-conversation — they just ask.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#product">
|
||||
<SlackMessage self time="10:18 AM">
|
||||
<Mention>supermemory</Mention> what's in our Q2 roadmap?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="10:18 AM">
|
||||
Three themes for Q2:
|
||||
1. **Company Brain GA** — Slack bot, connectors, automations
|
||||
2. **Memory Router v2** — lower latency, better multi-tenant isolation
|
||||
3. **Enterprise SSO + audit log**
|
||||
|
||||
Full doc: *Q2 Roadmap* in Notion (last updated Jun 3).
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
This is a [data connector](/company-brain/connectors) (Notion, Google Drive, or OneDrive) feeding [public channel memory](/company-brain/permissions). Content is fetched, chunked, embedded, and re-synced on a schedule — so when the roadmap changes in Notion, answers stay current without anyone re-uploading.
|
||||
|
||||
Same pattern works for handbooks, design docs, RFCs, and "where do we document X?" style questions. If it doesn't know, it says so rather than guessing.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Bring Drive, Notion, and OneDrive into public channel memory.
|
||||
</Card>
|
||||
<Card title="Permissions" icon="shield-check" href="/company-brain/permissions">
|
||||
Who can see what once it's indexed.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
47
apps/docs/company-brain/use-cases/long-horizon-research.mdx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: "Long-Horizon Research"
|
||||
sidebarTitle: "Long-Horizon Research"
|
||||
description: "Questions that need many sources synthesized into one answer"
|
||||
icon: "telescope"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
Some questions aren't a quick lookup. They need pulling information from a lot of distinct places — docs, tickets, meetings, code, past Slack threads — and synthesizing it into one coherent answer. Closer to a research project than "what's the pricing?"
|
||||
|
||||
## What it will look like
|
||||
|
||||
<SlackThread channel="#product">
|
||||
<SlackMessage self time="11:10 AM">
|
||||
<Mention>supermemory</Mention> prepare a brief on how we've handled enterprise SSO requests over the last two quarters — who asked, what we promised, what's still open, and what engineering thinks the real effort is
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="11:14 AM">
|
||||
**Enterprise SSO — two-quarter brief**
|
||||
|
||||
- **Demand:** 6 serious asks (Acme, Globex, Initech, …). Three converted to paid pilots.
|
||||
- **Promises made:** Okta + Azure AD for pilots; custom SAML called "roadmap" in two decks.
|
||||
- **Still open:** Globex blocked on SCIM; Initech waiting on audit-log export.
|
||||
- **Eng view:** ~6 weeks for Okta/Azure path (from `#eng` thread Mar 18 + Linear ENG-610); SCIM is the long pole.
|
||||
|
||||
Sources: Q1/Q2 enterprise notes, Linear ENG-610, Granola "SSO planning", `#sales` threads. Want this as a Linear doc?
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
Today, a single turn can already hit multiple [connectors](/company-brain/connectors) and channel memory in one answer. Long-horizon research is for the cases where that isn't enough — the work needs more time, more parallel digging, and a structured synthesis step before it replies.
|
||||
|
||||
We're deliberately not documenting an internal "spawn N children" mechanism here. What matters for you: ask a research-shaped question, get a sourced brief back, without you having to run six separate searches.
|
||||
|
||||
Until it ships, break big questions into smaller ones (docs, then tickets, then "summarize what we have") — Company Brain already handles each of those well.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="From docs" icon="book" href="/company-brain/use-cases/knowledge-recall">
|
||||
What single-turn knowledge recall looks like today.
|
||||
</Card>
|
||||
<Card title="Meeting recall" icon="calendar-check" href="/company-brain/use-cases/meeting-recall">
|
||||
Pulling decisions out of synced notes.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
38
apps/docs/company-brain/use-cases/meeting-recall.mdx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: "Meeting Recall"
|
||||
sidebarTitle: "Meeting Recall"
|
||||
description: "Ask what was decided in a meeting and get the answer from synced notes"
|
||||
icon: "calendar-check"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
Someone missed the Acme call — or was there and forgot the outcome. They ask in Slack and get the decision, with a path back to the source notes.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#sales">
|
||||
<SlackMessage self time="4:05 PM">
|
||||
<Mention>supermemory</Mention> what did we decide in the meeting with Acme?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="4:05 PM">
|
||||
Acme is moving to annual billing at the current rate, with a 90-day pilot on the enterprise SSO add-on. Follow-up owned by **Priya**, due Friday. *(from Granola notes, Acme QBR — Jun 11)*
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
Meeting notes come in through a [connector](/company-brain/connectors) — Granola for live meeting notes, or Drive/Notion if notes land there. Once synced, they live in [public channel memory](/company-brain/permissions), so anyone on the team can ask about them. The answer cites the source so you can open the original notes and verify.
|
||||
|
||||
Ask about a decision, an owner, a date, or "what did we promise them" — plain language is fine.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Permissions" icon="shield-check" href="/company-brain/permissions">
|
||||
Why meeting notes land in public channel memory.
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Connect Granola, Drive, or Notion.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
42
apps/docs/company-brain/use-cases/meeting-scheduling.mdx
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: "Meeting Scheduling"
|
||||
sidebarTitle: "Scheduling"
|
||||
description: "Find free time and send a calendar invite from Slack"
|
||||
icon: "calendar-plus"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention } from "/snippets/slack-message.mdx";
|
||||
|
||||
<Note>
|
||||
**Coming soon.** Calendar scheduling isn't in Company Brain yet — there's no calendar connector in the catalog today. This page shows the experience we're building toward, using a real exchange from our own team.
|
||||
</Note>
|
||||
|
||||
## The scenario
|
||||
|
||||
A teammate needs help and doesn't want to play calendar ping-pong. They ask in Slack; Company Brain checks availability and offers to book the slot.
|
||||
|
||||
## What it will look like
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage name="Sam" color="#36C5F0" time="1:12 PM">
|
||||
Dhravya are you free this afternoon? need some help with dev setup
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="1:12 PM">
|
||||
Dhravya is free at **2:00 PM**. Sending an invite to block **20 mins** on both your calendars.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
When this ships, it will be a [tool connector](/company-brain/connectors) against the calendar — same personal-vs-org rules and [write-under-your-account](/company-brain/permissions) attribution as Linear or GitHub. Creating an invite is a write, so it runs as the person who has the calendar connected (or via an explicit [lease](/company-brain/permissions#leasing-borrowing-access-for-one-request) if someone else is lending access for that one request).
|
||||
|
||||
Until then: ask Company Brain for *context* around scheduling ("who's the right person for dev setup?" / "when did we last pair on this?") and book the time the usual way.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Permissions" icon="shield-check" href="/company-brain/permissions">
|
||||
How personal tools and leasing will apply to calendar.
|
||||
</Card>
|
||||
<Card title="What you can do" icon="sparkles" href="/company-brain/use-cases/overview">
|
||||
Back to all scenarios — including what's shipped today.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
47
apps/docs/company-brain/use-cases/overview.mdx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: "What You Can Do"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Real scenarios for Company Brain — from Slack answers to sandbox debugging"
|
||||
icon: "sparkles"
|
||||
---
|
||||
|
||||
Company Brain is most useful when it shows up in the work you already do. These walkthroughs are short, concrete scenarios — each one is a real exchange, what the bot is actually doing under the hood, and which concept page to read if you want the full picture.
|
||||
|
||||
## Shipped today
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Automatic support" icon="headset" href="/company-brain/use-cases/support">
|
||||
Customer question in Slack; Company Brain chimes in with the answer.
|
||||
</Card>
|
||||
<Card title="Incidents & downtime" icon="triangle-alert" href="/company-brain/use-cases/incidents">
|
||||
"Is prod down?" answered from live Sentry, plus scheduled digests.
|
||||
</Card>
|
||||
<Card title="Meeting recall" icon="calendar-check" href="/company-brain/use-cases/meeting-recall">
|
||||
"What did we decide with Acme?" from synced meeting notes.
|
||||
</Card>
|
||||
<Card title="Answering from docs" icon="book" href="/company-brain/use-cases/knowledge-recall">
|
||||
Roadmaps, specs, and handbooks — asked in plain language.
|
||||
</Card>
|
||||
<Card title="Acting in tools" icon="wrench" href="/company-brain/use-cases/acting-in-tools">
|
||||
List open PRs, create a Linear issue — under your own account.
|
||||
</Card>
|
||||
<Card title="Greeting new teammates" icon="user-plus" href="/company-brain/use-cases/greeting">
|
||||
Connect card, welcome DM, first answer — activation on day one.
|
||||
</Card>
|
||||
<Card title="Sandbox debugging" icon="terminal" href="/company-brain/use-cases/sandbox-debugging">
|
||||
Actually run the failing test in an isolated workspace.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Coming soon
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Long-horizon research" icon="telescope" href="/company-brain/use-cases/long-horizon-research">
|
||||
Questions that need many sources synthesized into one answer.
|
||||
</Card>
|
||||
<Card title="Meeting scheduling" icon="calendar-plus" href="/company-brain/use-cases/meeting-scheduling">
|
||||
Find free time and send a calendar invite from Slack.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
If you're still setting things up, start with [What is Company Brain?](/company-brain/overview) and work through the Concepts section first — the walkthroughs assume those ideas.
|
||||
49
apps/docs/company-brain/use-cases/sandbox-debugging.mdx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
title: "Sandbox Debugging"
|
||||
sidebarTitle: "Sandbox"
|
||||
description: "Hand it a failing test — it runs the code in an isolated workspace and reports back"
|
||||
icon: "terminal"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
A test is failing and the stack trace alone isn't enough. You want Company Brain to actually run the code, not just describe what it *would* do.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#eng">
|
||||
<SlackMessage self time="5:41 PM">
|
||||
<Mention>supermemory</Mention> the `permissions.lease` unit test is failing on main — can you reproduce and tell me why?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="5:42 PM">
|
||||
Reproduced in a sandbox against `main`.
|
||||
|
||||
**Failure:** `permissions.lease` expects temporary access to expire in 15 minutes, but the fixture still asserts 30.
|
||||
**Cause:** the default was shortened in `#1188`; the unit test wasn't updated.
|
||||
**Fix:** point the assertion at the shared default so it can't drift again.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
Company Brain spins up an **isolated workspace**, checks out what it needs, runs the command, and reads the output. It's not guessing from static code alone — it's executing.
|
||||
|
||||
Guardrails are intentional, so it's safe to hand real tasks to:
|
||||
|
||||
- No `git push`, no deploys
|
||||
- No elevated privileges (`sudo` and similar are blocked)
|
||||
- No reaching arbitrary internal network addresses
|
||||
- No long-running dev servers
|
||||
|
||||
Think of it as a sealed workbench: useful for reproduce / inspect / explain loops, not for shipping changes on your behalf.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Acting in tools" icon="wrench" href="/company-brain/use-cases/acting-in-tools">
|
||||
When the next step is a Linear issue or a PR lookup.
|
||||
</Card>
|
||||
<Card title="What you can do" icon="sparkles" href="/company-brain/use-cases/overview">
|
||||
All the scenario walkthroughs.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
81
apps/docs/company-brain/use-cases/support-escalation.mdx
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
title: "From Support Ticket to Code Fix"
|
||||
sidebarTitle: "Escalation"
|
||||
description: "A Plain ticket gets triaged in Slack, and an @mention hands the fix to Cursor"
|
||||
icon: "bug"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage, Mention, FileAttachment, AgentLink, SlackUnfurl, SlackButton } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
A customer files a ticket through Plain. It lands in `#support`, gets triaged with context Company Brain already has lying around, and — instead of someone manually filing a bug and waiting — an @mention hands the whole thing straight to Cursor.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#support" members={24}>
|
||||
<SlackMessage name="Plain" badges={["APP"]} avatar="/images/company-brain/plain-icon.png" time="10:12 AM">
|
||||
New conversation: <AgentLink href="#">rewriteQuery param not working</AgentLink>
|
||||
<br />
|
||||
**Jordan Alvarez** (acme-corp.io) sent a **new message**.
|
||||
<SlackUnfurl footer="Added by Plain">
|
||||
hi team, just tried the `rewriteQuery` param on the v3 search endpoint and it doesn't seem to actually do anything — tried a few different values, results look identical either way. can someone take a look
|
||||
</SlackUnfurl>
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="10:13 AM">
|
||||
Confirmed, this is a real one — a couple of people have also flagged it on GitHub over the last week.
|
||||
<br />
|
||||
<br />
|
||||
Quick context: v3 search is deprecated, but we've committed to legacy support through end of year, so it's still worth fixing rather than telling people to migrate. Most likely cause is a change <Mention>Adam</Mention> shipped last week to cut down query-rewrite costs — looks like it short-circuits before `rewriteQuery` gets applied in some cases.
|
||||
<br />
|
||||
<br />
|
||||
<Mention>cursor</Mention> can you take this one? Full context attached.
|
||||
<br />
|
||||
<br />
|
||||
<FileAttachment name="Context.md" />
|
||||
</SlackMessage>
|
||||
<SlackMessage name="Cursor" badges={["AGENT"]} avatar="/images/company-brain/cursor-icon.png" time="10:14 AM">
|
||||
<AgentLink href="#">Agent thread started</AgentLink>
|
||||
<br />
|
||||
Reproducing against the v3 search test suite now.
|
||||
</SlackMessage>
|
||||
<SlackMessage name="Cursor" badges={["AGENT"]} avatar="/images/company-brain/cursor-icon.png" time="10:19 AM">
|
||||
Fixed — `rewriteQuery` was getting skipped by the new cost short-circuit whenever a query was already cached. Pushed on <AgentLink href="#">#2312</AgentLink>.
|
||||
<br />
|
||||
<br />
|
||||
**Resolution:**
|
||||
<br />
|
||||
• Scoped the short-circuit to skip only the rewrite step, not the whole `rewriteQuery` path
|
||||
<br />
|
||||
• Added a regression test covering `rewriteQuery` against a cache hit
|
||||
<br />
|
||||
<br />
|
||||
**Repository:** `supermemoryai/mono`
|
||||
<br />
|
||||
<br />
|
||||
<SlackButton variant="primary">Open in Web</SlackButton>
|
||||
<SlackButton>Open in Desktop</SlackButton>
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="10:20 AM">
|
||||
<Mention self>Dhravya</Mention> I'll let you review that and let the customer know we have a fix ready.
|
||||
<br />
|
||||
Please do it ASAP — it's an enterprise customer!
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
The first two turns are the same pattern as [Automatic Support](/company-brain/use-cases/support): the bot is already a member of `#support`, so it [chimes in](/company-brain/automations) unprompted, correlating the ticket against known GitHub issues and whatever it knows about the codebase and the v3 deprecation timeline.
|
||||
|
||||
The handoff to Cursor is different. That's not a chime-in — it's an explicit `@mention`, and Cursor is wired in as a [tool connector](/company-brain/connectors) (a custom MCP server, same as GitHub or Linear under the hood) that can act, not just answer. Naming it by name is what triggers the write: Company Brain hands off the attached context and Cursor opens its own agent thread against the repo, the same way a mention of GitHub or Linear in [Acting in Tools](/company-brain/use-cases/acting-in-tools) triggers a write rather than a read. Nothing happens in the codebase without that explicit ask.
|
||||
|
||||
Whether that handoff is even possible follows the same [permissions](/company-brain/permissions) rules as any other tool: it runs under whichever connection — personal or org-shared — is actually wired up for Cursor, and it's scoped to what that connection can see.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Acting in Tools" icon="wrench" href="/company-brain/use-cases/acting-in-tools">
|
||||
How @mentions trigger writes instead of reads.
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Wire up Plain, GitHub, and custom MCP servers like Cursor.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
38
apps/docs/company-brain/use-cases/support.mdx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: "Automatic Support"
|
||||
sidebarTitle: "Support"
|
||||
description: "Company Brain chimes in on customer questions with answers from docs and tickets"
|
||||
icon: "headset"
|
||||
---
|
||||
|
||||
import { SlackThread, SlackMessage } from "/snippets/slack-message.mdx";
|
||||
|
||||
## The scenario
|
||||
|
||||
A customer question lands in `#support`. Nobody has to @mention the bot — it already has the answer from past tickets and the help docs.
|
||||
|
||||
## What happens
|
||||
|
||||
<SlackThread channel="#support" members={24}>
|
||||
<SlackMessage name="Maya" color="#2BAC76" time="2:14 PM">
|
||||
customer on the Pro plan is asking if they can export their full memory graph as CSV — do we support that?
|
||||
</SlackMessage>
|
||||
<SlackMessage bot time="2:14 PM">
|
||||
Yes — **Settings → Export → Full graph (CSV)**. Available on Pro and above. Same answer went out on ticket PLN-1842 last week if you want the exact wording.
|
||||
</SlackMessage>
|
||||
</SlackThread>
|
||||
|
||||
## What's really going on
|
||||
|
||||
This is [proactiveness (chime-in)](/company-brain/automations) plus a connected support tool (Plain) and public channel memory. The bot is already a member of `#support` (an admin invited it — it never joins on its own). It decided the answer was clear enough to speak without being asked, pulled the export path from docs in public channel memory, and cited a recent ticket from Plain.
|
||||
|
||||
Same channel scope rules apply: a public support channel writes durable learnings back to public channel memory; a private support channel keeps them scoped to that room's own memory. See [Permissions](/company-brain/permissions).
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Automations & proactiveness" icon="wand-magic-sparkles" href="/company-brain/automations">
|
||||
How chime-in decides when to speak.
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/company-brain/connectors">
|
||||
Wire up Plain and your help docs.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: "Container Tags"
|
||||
sidebarTitle: "Container Tags"
|
||||
sidebarTitle: "Container tags"
|
||||
description: "The isolation boundary that groups and partitions memories by user, project, or any logical scope"
|
||||
icon: "folder"
|
||||
---
|
||||
|
|
@ -32,7 +32,7 @@ await client.add({
|
|||
});
|
||||
|
||||
// Later, retrieve only Alex's memories
|
||||
const results = await client.search.memories({
|
||||
const results = await client.search({
|
||||
q: "what are the user's UI preferences?",
|
||||
containerTag: "user_alex",
|
||||
});
|
||||
|
|
@ -103,7 +103,7 @@ The same tag flows through the entire lifecycle of a memory. Pass it consistentl
|
|||
await client.add({ content: "Q1 planning notes", containerTag: "project_q1" });
|
||||
|
||||
// Search within the same container
|
||||
await client.search.memories({ q: "planning", containerTag: "project_q1" });
|
||||
await client.search({ q: "planning", containerTag: "project_q1" });
|
||||
|
||||
// List everything in the container
|
||||
await client.documents.list({ containerTags: ["project_q1"] });
|
||||
|
|
@ -170,7 +170,10 @@ Keep tags **deterministic** — derive them directly from IDs you already have (
|
|||
<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">
|
||||
<Card title="Scoped API keys" icon="key" href="/authentication#scoped-api-keys">
|
||||
Mint keys that can only touch one container — multi-tenant clients without the org master key.
|
||||
</Card>
|
||||
<Card title="Adding Memories" icon="plus" href="/ingestion/add-memories">
|
||||
See container tags in action across the add API.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: "Supported Content Types"
|
||||
sidebarTitle: "Content Types"
|
||||
sidebarTitle: "Multi-modal ingestion"
|
||||
description: "All the content formats Supermemory can ingest and process"
|
||||
icon: "file-stack"
|
||||
---
|
||||
|
||||
Supermemory automatically extracts and indexes content from various formats. Just send it—we handle the rest. See [Add Memories](/add-memories) to learn how to ingest content via the API.
|
||||
Supermemory automatically extracts and indexes content from various formats. There are two entry points: `client.add()` for text and URLs, `client.documents.uploadFile()` for actual files. See [Add Memories](/ingestion/add-memories) to learn how to ingest content via the API.
|
||||
|
||||
## Text Content
|
||||
|
||||
|
|
@ -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,11 +29,11 @@ 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"
|
||||
});
|
||||
```
|
||||
|
||||
**Extracts:** Article text, headings, metadata. Strips navigation, ads, boilerplate.
|
||||
**Extracts:** Article text, headings, metadata. Strips navigation, ads, boilerplate. URL extraction is powered by [Markdowner](https://md.dhr.wtf).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -41,11 +41,15 @@ await client.add({
|
|||
|
||||
### PDF
|
||||
|
||||
Files are binary, so they go through `uploadFile`, not `add` — pass a stream, not base64:
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: pdfBase64,
|
||||
contentType: "pdf",
|
||||
title: "Q4 Financial Report"
|
||||
import fs from 'fs';
|
||||
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('report.pdf'),
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "Q4 Financial Report" })
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -53,17 +57,13 @@ await client.add({
|
|||
|
||||
### Microsoft Office
|
||||
|
||||
| Format | Extension | Content Type |
|
||||
|--------|-----------|--------------|
|
||||
| Word | `.docx` | `docx` |
|
||||
| Excel | `.xlsx` | `xlsx` |
|
||||
| PowerPoint | `.pptx` | `pptx` |
|
||||
Word, Excel, and PowerPoint files upload the same way — Supermemory detects the type from the file itself:
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: docxBase64,
|
||||
contentType: "docx",
|
||||
title: "Product Roadmap"
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('roadmap.docx'),
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "Product Roadmap" })
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -78,18 +78,20 @@ Automatically handled via [Google Drive connector](/connectors/google-drive):
|
|||
|
||||
## Code & Markdown
|
||||
|
||||
Both are plain text, so they go through `add` like any other string content — no file upload needed:
|
||||
|
||||
```typescript
|
||||
// Markdown
|
||||
await client.add({
|
||||
content: markdownContent,
|
||||
contentType: "md",
|
||||
title: "README.md"
|
||||
containerTag: "user_123",
|
||||
metadata: { title: "README.md" }
|
||||
});
|
||||
|
||||
// Code files (auto-detected language)
|
||||
// Code (language auto-detected)
|
||||
await client.add({
|
||||
content: codeContent,
|
||||
contentType: "code",
|
||||
containerTag: "user_123",
|
||||
metadata: { language: "typescript" }
|
||||
});
|
||||
```
|
||||
|
|
@ -102,11 +104,15 @@ Code is chunked using [code-chunk](https://github.com/supermemoryai/code-chunk),
|
|||
|
||||
## Images
|
||||
|
||||
`fileType: "image"` and `mimeType` are both required so Supermemory knows exactly how to process it:
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: imageBase64,
|
||||
contentType: "image",
|
||||
title: "Architecture Diagram"
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('diagram.png'),
|
||||
fileType: "image",
|
||||
mimeType: "image/png",
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "Architecture Diagram" })
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -118,19 +124,24 @@ await client.add({
|
|||
|
||||
## Audio & Video
|
||||
|
||||
Video has a dedicated `fileType`; audio is uploaded the same way and detected from the file itself:
|
||||
|
||||
```typescript
|
||||
// Audio
|
||||
await client.add({
|
||||
content: audioBase64,
|
||||
contentType: "audio",
|
||||
title: "Customer Call Recording"
|
||||
// Video
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('demo.mp4'),
|
||||
fileType: "video",
|
||||
mimeType: "video/mp4",
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "Product Demo" })
|
||||
});
|
||||
|
||||
// Video
|
||||
await client.add({
|
||||
content: videoBase64,
|
||||
contentType: "video",
|
||||
title: "Product Demo"
|
||||
// Audio
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('call-recording.mp3'),
|
||||
mimeType: "audio/mpeg",
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "Customer Call Recording" })
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -142,13 +153,15 @@ await client.add({
|
|||
|
||||
## Structured Data
|
||||
|
||||
JSON and CSV are text — stringify and send them through `add()`, no file upload needed.
|
||||
|
||||
### JSON
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: JSON.stringify(userData),
|
||||
contentType: "json",
|
||||
title: "User Profile Data"
|
||||
containerTag: "user_123",
|
||||
metadata: { title: "User Profile Data", format: "json" }
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -157,8 +170,8 @@ await client.add({
|
|||
```typescript
|
||||
await client.add({
|
||||
content: csvContent,
|
||||
contentType: "csv",
|
||||
title: "Sales Data Q4"
|
||||
containerTag: "user_123",
|
||||
metadata: { title: "Sales Data Q4", format: "csv" }
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -166,26 +179,33 @@ await client.add({
|
|||
|
||||
## File Upload
|
||||
|
||||
For binary files, encode as base64:
|
||||
For any binary file, use `uploadFile` — it accepts a stream, not base64:
|
||||
|
||||
```typescript
|
||||
import { readFileSync } from 'fs';
|
||||
import fs from 'fs';
|
||||
|
||||
const file = readFileSync('./document.pdf');
|
||||
const base64 = file.toString('base64');
|
||||
|
||||
await client.add({
|
||||
content: base64,
|
||||
contentType: "pdf",
|
||||
title: "document.pdf"
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('./document.pdf'),
|
||||
containerTag: "user_123",
|
||||
metadata: JSON.stringify({ title: "document.pdf" })
|
||||
});
|
||||
```
|
||||
|
||||
No Node `fs` access? `uploadFile` also accepts a web `File`, a `fetch` `Response`, or the SDK's `toFile` helper:
|
||||
|
||||
```typescript
|
||||
import Supermemory, { toFile } from 'supermemory';
|
||||
|
||||
await client.documents.uploadFile({ file: new File(['my bytes'], 'file') });
|
||||
await client.documents.uploadFile({ file: await fetch('https://somesite/file') });
|
||||
await client.documents.uploadFile({ file: await toFile(Buffer.from('my bytes'), 'file') });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Auto-Detection
|
||||
|
||||
If you don't specify `contentType`, Supermemory auto-detects:
|
||||
`add()` tells URLs and plain text apart on its own — no extra flag needed:
|
||||
|
||||
```typescript
|
||||
// URL detected automatically
|
||||
|
|
@ -195,9 +215,7 @@ await client.add({ content: "https://example.com/page" });
|
|||
await client.add({ content: "User said they prefer email contact" });
|
||||
```
|
||||
|
||||
<Note>
|
||||
For binary content (files), always specify `contentType` for reliable processing.
|
||||
</Note>
|
||||
For files, `uploadFile` detects type from the file itself in most cases. `fileType` only exists to force specific processing — and it's required (along with `mimeType`) for images and video.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -209,6 +227,8 @@ For binary content (files), always specify `contentType` for reliable processing
|
|||
| Files | 50MB |
|
||||
| URLs | Fetched content up to 10MB |
|
||||
|
||||
**Typical processing time:** text is near-instant; PDFs take 1-5s; images 2-10s; video 10s+; webpages 1-3s. Text content is chunked at the sentence level with a 2-sentence overlap between chunks.
|
||||
|
||||
<Tip>
|
||||
For large files, consider chunking or using [connectors](/connectors/overview) for automatic sync.
|
||||
</Tip>
|
||||
|
|
@ -218,7 +238,7 @@ For large files, consider chunking or using [connectors](/connectors/overview) f
|
|||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
<Card title="Add Memories" icon="plus" href="/ingestion/add-memories">
|
||||
Upload content via the API
|
||||
</Card>
|
||||
<Card title="Super RAG" icon="bolt" href="/concepts/super-rag">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: "Customizing for Your Use Case"
|
||||
sidebarTitle: "Customization"
|
||||
sidebarTitle: "Customizing"
|
||||
description: "Configure Supermemory's behavior for your specific application"
|
||||
icon: "settings-2"
|
||||
---
|
||||
|
|
@ -70,6 +70,16 @@ await client.settings.update({
|
|||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Related settings
|
||||
|
||||
`shouldLLMFilter` must be `true` for any of these to take effect — using them without it returns a 400 error.
|
||||
|
||||
| Setting | Type | Limits |
|
||||
|---------|------|--------|
|
||||
| `categories` | `string[]` | 1-50 chars each. If omitted, 3-5 categories are auto-generated |
|
||||
| `includeItems` / `excludeItems` | `string[]` | 1-20 chars each item |
|
||||
| `filterPrompt` | `string` | 1-750 characters |
|
||||
|
||||
---
|
||||
|
||||
## Entity Context
|
||||
|
|
@ -193,7 +203,7 @@ Settings are organization-wide. Changes apply to new content only—existing mem
|
|||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
<Card title="Add Memories" icon="plus" href="/ingestion/add-memories">
|
||||
See your custom settings in action
|
||||
</Card>
|
||||
<Card title="Connectors" icon="plug" href="/connectors/overview">
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
title: "Organizing & Filtering Memories"
|
||||
sidebarTitle: "Multi-Tenancy / Filtering"
|
||||
sidebarTitle: "Metadata filtering"
|
||||
description: "Use container tags and metadata to organize and retrieve memories"
|
||||
icon: "users"
|
||||
icon: "filter"
|
||||
---
|
||||
|
||||
Supermemory provides two ways to organize your memories:
|
||||
|
|
@ -29,21 +29,22 @@ Container tags create isolated memory spaces. Use them to separate memories by u
|
|||
```typescript
|
||||
await client.add({
|
||||
content: "Meeting notes from Q1 planning",
|
||||
containerTags: ["user_123"]
|
||||
containerTag: "user_123"
|
||||
});
|
||||
```
|
||||
|
||||
### Searching with Tags
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "planning notes",
|
||||
containerTags: ["user_123"]
|
||||
containerTag: "user_123",
|
||||
searchMode: "documents"
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
Container tags use **exact array matching**. A memory tagged `["user_123", "project_a"]` won't match a search for just `["user_123"]`.
|
||||
Each search is scoped to a single container tag. Passing `containerTag: "user_123"` restricts results to memories stored in that container.
|
||||
</Note>
|
||||
|
||||
### Recommended Patterns
|
||||
|
|
@ -60,34 +61,34 @@ Container tags use **exact array matching**. A memory tagged `["user_123", "proj
|
|||
// Multi-tenant SaaS - isolate by organization and user
|
||||
await client.add({
|
||||
content: "Company policy document",
|
||||
containerTags: ["org_acme_user_john"]
|
||||
containerTag: "org_acme_user_john"
|
||||
});
|
||||
|
||||
// Search only within that user's org context
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "vacation policy",
|
||||
containerTags: ["org_acme_user_john"]
|
||||
containerTag: "org_acme_user_john",
|
||||
searchMode: "documents"
|
||||
});
|
||||
|
||||
// Project-based isolation
|
||||
await client.add({
|
||||
content: "Sprint 5 retrospective notes",
|
||||
containerTags: ["project_mobile_app"]
|
||||
containerTag: "project_mobile_app"
|
||||
});
|
||||
|
||||
// Time-based segmentation
|
||||
await client.add({
|
||||
content: "Q1 2024 financial report",
|
||||
containerTags: ["user_cfo_2024_q1"]
|
||||
containerTag: "user_cfo_2024_q1"
|
||||
});
|
||||
```
|
||||
|
||||
**API field differences:**
|
||||
| Endpoint | Field | Type |
|
||||
|----------|-------|------|
|
||||
| `/v3/search` | `containerTags` | Array |
|
||||
| `/v4/search` | `containerTag` | String |
|
||||
| `/v3/documents/list` | `containerTags` | Array |
|
||||
| Operation | Field | Type |
|
||||
|-----------|-------|------|
|
||||
| Search | `containerTag` | String |
|
||||
| Documents list | `containerTags` | Array |
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
|
|
@ -102,7 +103,7 @@ Metadata lets you attach custom properties to memories and filter by them later.
|
|||
```typescript
|
||||
await client.add({
|
||||
content: "Technical design document for auth system",
|
||||
containerTags: ["user_123"],
|
||||
containerTag: "user_123",
|
||||
metadata: {
|
||||
category: "engineering",
|
||||
priority: "high",
|
||||
|
|
@ -116,9 +117,10 @@ await client.add({
|
|||
Filters must be wrapped in `AND` or `OR` arrays:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "design document",
|
||||
containerTags: ["user_123"],
|
||||
containerTag: "user_123",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "engineering" },
|
||||
|
|
@ -142,8 +144,9 @@ const results = await client.search.documents({
|
|||
Use `AND` and `OR` for complex queries:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "meeting notes",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "type", value: "meeting" },
|
||||
|
|
@ -163,8 +166,9 @@ const results = await client.search.documents({
|
|||
Use `negate: true` to exclude matches:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "documentation",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "status", value: "draft", negate: true }
|
||||
|
|
@ -178,8 +182,9 @@ const results = await client.search.documents({
|
|||
**String contains (substring search):**
|
||||
```typescript
|
||||
// Find documents with "machine learning" in the description
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "AI research",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
|
|
@ -196,8 +201,9 @@ const results = await client.search.documents({
|
|||
**Numeric comparisons:**
|
||||
```typescript
|
||||
// Find high-priority items created after a specific date
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "tasks",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
|
|
@ -220,8 +226,9 @@ const results = await client.search.documents({
|
|||
**Array contains (check array membership):**
|
||||
```typescript
|
||||
// Find documents where a specific user is a participant
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "meeting notes",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
|
|
@ -237,8 +244,9 @@ const results = await client.search.documents({
|
|||
**Complex nested filters:**
|
||||
```typescript
|
||||
// (category = "tech" OR category = "science") AND status != "archived"
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "research papers",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
|
|
@ -265,9 +273,10 @@ const results = await client.search.documents({
|
|||
<Accordion title="Real-World Patterns">
|
||||
**User's work documents from 2024:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "quarterly report",
|
||||
containerTags: ["user_123"],
|
||||
containerTag: "user_123",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "work" },
|
||||
|
|
@ -280,9 +289,10 @@ const results = await client.search.documents({
|
|||
|
||||
**Team meeting notes with specific participants:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "sprint planning",
|
||||
containerTags: ["project_alpha"],
|
||||
containerTag: "project_alpha",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "type", value: "meeting" },
|
||||
|
|
@ -299,8 +309,9 @@ const results = await client.search.documents({
|
|||
|
||||
**Exclude drafts and deprecated content:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "documentation",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "status", value: "draft", negate: true },
|
||||
|
|
@ -322,7 +333,7 @@ const results = await client.search.documents({
|
|||
```typescript
|
||||
await client.add({
|
||||
content: "Your content here",
|
||||
containerTags: ["user_123"], // Isolation
|
||||
containerTag: "user_123", // Isolation
|
||||
metadata: { key: "value" } // Custom properties
|
||||
});
|
||||
```
|
||||
|
|
@ -330,9 +341,10 @@ await client.add({
|
|||
### When Searching
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "search query",
|
||||
containerTags: ["user_123"], // Must match exactly
|
||||
containerTag: "user_123", // Scopes results to this container
|
||||
searchMode: "documents",
|
||||
filters: { // Optional metadata filters
|
||||
AND: [{ key: "status", value: "published" }]
|
||||
}
|
||||
|
|
@ -345,15 +357,35 @@ const results = await client.search.documents({
|
|||
- Max length: 64 characters
|
||||
- No spaces or special characters
|
||||
|
||||
### Query Complexity Limits
|
||||
|
||||
- Maximum 200 conditions per query
|
||||
- Maximum 8 levels of nested `AND`/`OR` expressions
|
||||
|
||||
<Note>
|
||||
If you need more conditions than these limits allow, break your query into multiple requests or use broader search terms with post-processing.
|
||||
</Note>
|
||||
|
||||
### Searching Within a Document
|
||||
|
||||
Use `docId` to scope a search to chunks within one large document — useful for books, podcasts, or other long-form content:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
q: "machine learning",
|
||||
docId: "doc_123"
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Search" icon="search" href="/search">
|
||||
<Card title="Search" icon="search" href="/recall/search">
|
||||
Apply filters in search queries
|
||||
</Card>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
<Card title="Add Memories" icon="plus" href="/ingestion/add-memories">
|
||||
Add content with container tags and metadata
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -1,146 +1,189 @@
|
|||
---
|
||||
title: "How Graph Memory Works"
|
||||
sidebarTitle: "Graph Memory"
|
||||
description: "Automatic memory evolution, knowledge updates, and intelligent forgetting"
|
||||
title: "Graph memory"
|
||||
sidebarTitle: "Graph memory"
|
||||
description: "How facts connect, update, and stay true — memory relationships, temporal truth, and automatic forgetting."
|
||||
icon: "vector-square"
|
||||
---
|
||||
|
||||
Supermemory builds a living knowledge graph where memories connect to other memories. Unlike traditional knowledge graphs with entity-relation-entity triples, Supermemory's graph is **facts built on top of other facts**.
|
||||
**How understanding is stored and stays true over time.**
|
||||
|
||||
## Memory Relationships
|
||||
Supermemory builds a **living knowledge graph of facts on top of other facts** — not a static folder of embeddings, and not classic entity–relation–entity triples you maintain by hand.
|
||||
|
||||
When you add content, Supermemory extracts facts and automatically connects them to existing memories through three relationship types:
|
||||
The **pipeline** that turns a chat or file into memories is [How it works](/concepts/how-it-works).
|
||||
|
||||
### Updates: Information Changes
|
||||
This page is the **model**: what a memory is, how edges form, and why agents utilize supermemory's graph
|
||||
|
||||
When new information contradicts existing knowledge:
|
||||
## Try it
|
||||
|
||||
```
|
||||
Memory 1: "Alex works at Google as a software engineer"
|
||||
Memory 2: "Alex just started at Stripe as a PM"
|
||||
↓
|
||||
Memory 2 UPDATES Memory 1
|
||||
```
|
||||
|
||||
The system tracks which memory is latest with `isLatest`, so searches return current information while preserving history.
|
||||
|
||||
### Extends: Information Enriches
|
||||
|
||||
When new information adds detail without replacing:
|
||||
|
||||
```
|
||||
Memory 1: "Alex works at Stripe as a PM"
|
||||
Memory 2: "Alex focuses on payments infrastructure and leads a team of 5"
|
||||
↓
|
||||
Memory 2 EXTENDS Memory 1
|
||||
```
|
||||
|
||||
Both memories remain valid—searches get richer context.
|
||||
|
||||
### Derives: Information Infers
|
||||
|
||||
When Supermemory infers new facts from patterns:
|
||||
|
||||
```
|
||||
Memory 1: "Alex is a PM at Stripe"
|
||||
Memory 2: "Alex frequently discusses payment APIs and fraud detection"
|
||||
↓
|
||||
Derived: "Alex likely works on Stripe's core payments product"
|
||||
```
|
||||
|
||||
These inferences surface insights you didn't explicitly state.
|
||||
|
||||
---
|
||||
|
||||
## Automatic Memory Extraction
|
||||
|
||||
From a single conversation, Supermemory extracts multiple connected memories:
|
||||
|
||||
**Input:**
|
||||
> "Had a great call with Alex. He's enjoying the new PM role at Stripe, though the
|
||||
> payments infrastructure work is intense. He moved to Seattle for the job—got a
|
||||
> place in Capitol Hill. Wants to grab dinner next time I'm in town."
|
||||
|
||||
**Extracted memories:**
|
||||
- Alex works at Stripe as a PM
|
||||
- Alex works on payments infrastructure *(extends role memory)*
|
||||
- Alex lives in Seattle, Capitol Hill *(new fact)*
|
||||
- Alex wants to meet for dinner *(episodic)*
|
||||
|
||||
Each fact is connected to related memories automatically.
|
||||
|
||||
---
|
||||
|
||||
## Automatic Forgetting
|
||||
|
||||
Supermemory knows when memories become irrelevant:
|
||||
|
||||
**Time-based forgetting**: Temporary facts are automatically forgotten when they expire.
|
||||
|
||||
```
|
||||
"I have an exam tomorrow"
|
||||
↓
|
||||
After the exam date passes → automatically forgotten
|
||||
|
||||
"Meeting with Alex at 3pm today"
|
||||
↓
|
||||
After today → automatically forgotten
|
||||
```
|
||||
|
||||
**Contradiction resolution**: When new facts contradict old ones, the Update relationship ensures searches return current information.
|
||||
|
||||
**Noise filtering**: Casual, non-meaningful content doesn't become permanent memories.
|
||||
|
||||
---
|
||||
|
||||
## Memory Types
|
||||
|
||||
Supermemory distinguishes memory types automatically:
|
||||
|
||||
| Type | Example | Behavior |
|
||||
|------|---------|----------|
|
||||
| **Facts** | "Alex is a PM at Stripe" | Persists until updated |
|
||||
| **Preferences** | "Alex prefers morning meetings" | Strengthens with repetition |
|
||||
| **Episodes** | "Met Alex for coffee Tuesday" | Decays unless significant |
|
||||
|
||||
---
|
||||
|
||||
## What You Don't Do
|
||||
|
||||
All of this is automatic. You don't:
|
||||
- Define relationships manually
|
||||
- Tag memory types
|
||||
- Clean up old memories
|
||||
- Resolve contradictions
|
||||
|
||||
Just add content and search naturally:
|
||||
Get a key from the [developer console](https://console.supermemory.ai) — **API Keys → Create API Key** — then add a memory and pull it back with related edges:
|
||||
|
||||
```typescript
|
||||
import Supermemory from "supermemory";
|
||||
|
||||
const client = new Supermemory({ apiKey: "sm_..." }); // from console.supermemory.ai → API Keys
|
||||
|
||||
await client.add({
|
||||
content: "Alex mentioned he just started at Stripe"
|
||||
content: "Alex mentioned he just started at Stripe",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
|
||||
const results = await client.search({
|
||||
query: "where does Alex work?"
|
||||
q: "where does Alex work?",
|
||||
containerTag: "user_123",
|
||||
include: { relatedMemories: true },
|
||||
});
|
||||
// → Stripe (latest), previously Google (historical)
|
||||
```
|
||||
|
||||
---
|
||||
Full walkthrough with a live example: [Quickstart](/quickstart).
|
||||
|
||||
## Learn More
|
||||

|
||||
|
||||
## Documents vs memories
|
||||
|
||||
| | **Documents** | **Memories** |
|
||||
|---|---|---|
|
||||
| **What** | Raw input you send | Facts Supermemory extracts |
|
||||
| **Examples** | PDF, chat log, Drive file, URL | “Alex is a PM at Stripe” |
|
||||
| **Role** | Source of truth for RAG / SuperRAG | Personal and entity state over time |
|
||||
| **Lifecycle** | You add / update / delete | Graph updates, extends, derives, forgets |
|
||||
|
||||
Think of documents as books you hand the system. Memories are the insights it keeps — connected to each other as new content arrives.
|
||||
|
||||
<Note>
|
||||
Uploading a long PDF does more than store bytes: Supermemory derives many memories and links them to what it already knows about that entity or user. Chunks of the document remain available for [SuperRAG](/concepts/super-rag) grounding.
|
||||
</Note>
|
||||
|
||||
## Properties and rules of memories
|
||||
|
||||
1. Memories are atomic - Each memory has enough information and context about one particular topic
|
||||
2. They always build on top of each other - with `updates`, the model knows the history, a memory `extends` from other memories, and new facts are derived (`derives` relation) from existing knowledg.e
|
||||
|
||||
## Memory relationships
|
||||
|
||||

|
||||
|
||||
When content is processed, new facts connect to existing ones through three relationship types.
|
||||
|
||||
### Updates — information changes
|
||||
|
||||
New fact **replaces** what was true before for search purposes; history can remain for audit.
|
||||
|
||||
```text
|
||||
Memory 1: "Alex works at Google as a software engineer"
|
||||
Memory 2: "Alex just started at Stripe as a PM"
|
||||
→ Memory 2 UPDATES Memory 1
|
||||
```
|
||||
|
||||
`isLatest` (and related graph fields) keep retrieval on the current fact without erasing the past.
|
||||
|
||||
### Extends — information enriches
|
||||
|
||||
New fact **adds detail** without invalidating the old one.
|
||||
|
||||
```text
|
||||
Memory 1: "Alex works at Stripe as a PM"
|
||||
Memory 2: "Alex focuses on payments and leads a team of 5"
|
||||
→ Memory 2 EXTENDS Memory 1
|
||||
```
|
||||
|
||||
Both stay valid; context gets richer.
|
||||
|
||||
### Derives — information infers
|
||||
|
||||
Supermemory **infers** a fact you never stated in one place, from patterns across memories.
|
||||
|
||||
```text
|
||||
Memory 1: "Alex is a PM at Stripe"
|
||||
Memory 2: "Alex frequently discusses payment APIs and fraud detection"
|
||||
→ Derived: "Alex likely works on Stripe's core payments product"
|
||||
```
|
||||
|
||||
That is the same class of “entity chain” you see in the [quickstart](/quickstart) (gift → VP of Product → Sarah → Tokyo offsite). Search can expose edges via `include.relatedMemories` — see [Search API](/recall/search).
|
||||
|
||||
## Automatic extraction (one input → many facts)
|
||||
|
||||
**Input:**
|
||||
|
||||
> Had a great call with Alex. He's enjoying the new PM role at Stripe, though the payments work is intense. He moved to Seattle for the job—Capitol Hill. Wants dinner next time I'm in town.
|
||||
|
||||
**Example extracted memories:**
|
||||
|
||||
- Alex works at Stripe as a PM
|
||||
- Alex works on payments infrastructure *(extends role)*
|
||||
- Alex lives in Seattle, Capitol Hill
|
||||
- Alex wants to meet for dinner *(episodic)*
|
||||
|
||||
You do not define schema or draw edges. You [add content](/ingestion/add-memories); the graph updates.
|
||||
|
||||
## Dreaming keeps the graph alive
|
||||
|
||||
Ingest is not a one-shot snapshot. After (and alongside) indexing, **dreaming** continues building the graph: extracting facts, linking related memories, resolving updates, and producing derives you never stated in one place.
|
||||
|
||||
By default Supermemory uses **`dreaming: "dynamic"`** — related documents are grouped so memories form from **coherent units** (e.g. a real multi-turn session), not each isolated write in isolation. That is why production quality is higher when you keep a stable `customId` on conversations and let dynamic dreaming do its job.
|
||||
|
||||
Use **`dreaming: "instant"`** when this document must hit the graph immediately (demos, “search right after add”). That path processes the document alone and costs an extra operation.
|
||||
|
||||
How to set the flag, statuses, and when `done` means what: [How it works → Dreaming](/concepts/how-it-works#dreaming-how-memories-enter-the-graph) and [Processing modes](/ingestion/add-memories#processing-modes).
|
||||
|
||||
## Memory types
|
||||
|
||||
| Type | Example | Behavior |
|
||||
| --- | --- | --- |
|
||||
| **Facts** | “Alex is a PM at Stripe” | Persists until updated |
|
||||
| **Preferences** | “Alex prefers morning meetings” | Strengthens with repetition |
|
||||
| **Episodes** | “Met Alex for coffee Tuesday” | Decays unless significant |
|
||||
|
||||
## Automatic forgetting
|
||||
|
||||
- **Time-based** — temporary facts drop after they expire (“exam tomorrow”, “meeting at 3pm today”).
|
||||
- **Contradiction** — updates win for “what’s true now.”
|
||||
- **Noise filtering** — casual, non-meaningful chatter is less likely to become durable memory.
|
||||
|
||||
For explicit product controls (forget, review low-confidence derives), see [Forget & update](/recall/memory-operations) and [Memory review](/recall/memory-review).
|
||||
|
||||
## What you don’t do
|
||||
|
||||
You do **not** hand-maintain the graph. You:
|
||||
|
||||
1. Ingest under a [container tag](/concepts/container-tags)
|
||||
2. Wait for the [pipeline](/concepts/how-it-works) when needed
|
||||
3. [Search](/recall/search) or load a [profile](/recall/user-profiles)
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Alex mentioned he just started at Stripe",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
|
||||
const results = await client.search({
|
||||
q: "where does Alex work?",
|
||||
containerTag: "user_123",
|
||||
include: { relatedMemories: true },
|
||||
});
|
||||
// Prefer latest work fact (Stripe); history remains in the graph
|
||||
```
|
||||
|
||||
## Related in the docs
|
||||
|
||||
| If you need… | Go to |
|
||||
| --- | --- |
|
||||
| Pipeline statuses, dreaming, documents in | [How it works](/concepts/how-it-works) |
|
||||
| Memory vs document retrieval | [Memory vs RAG](/concepts/memory-vs-rag) · [SuperRAG](/concepts/super-rag) |
|
||||
| Always-on summary of a user | [Profiles](/concepts/user-profiles) |
|
||||
| Isolation / tenants | [Multi-tenancy](/concepts/container-tags) |
|
||||
| API: add / search / forget | [Ingestion](/ingestion/add-memories) · [Search](/recall/search) · [Forget & update](/recall/memory-operations) |
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="How It Works" icon="cpu" href="/concepts/how-it-works">
|
||||
Deep dive into the architecture
|
||||
<Card title="How it works" icon="cpu" href="/concepts/how-it-works">
|
||||
Ingest pipeline, statuses, and outputs.
|
||||
</Card>
|
||||
<Card title="Memory vs RAG" icon="scale" href="/concepts/memory-vs-rag">
|
||||
When to use memory vs document retrieval
|
||||
When to use memory vs document retrieval.
|
||||
</Card>
|
||||
<Card title="User Profiles" icon="user" href="/user-profiles">
|
||||
Automatic summaries from the graph
|
||||
<Card title="Profiles" icon="user" href="/concepts/user-profiles">
|
||||
Static + dynamic context built from the graph.
|
||||
</Card>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
Start building your knowledge graph
|
||||
<Card title="Quickstart" icon="play" href="/quickstart">
|
||||
See entity chains in a full conversation + document flow.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -1,152 +1,182 @@
|
|||
---
|
||||
title: "How Supermemory Works"
|
||||
description: "Understanding the knowledge graph architecture that powers intelligent memory"
|
||||
sidebarTitle: "How it works"
|
||||
description: "From a file or chat turn to something you can search — the ingest pipeline, statuses, and outputs."
|
||||
icon: "cpu"
|
||||
---
|
||||
|
||||
|
||||
Supermemory isn't just another document storage system. It's designed to mirror how human memory actually works - forming connections, evolving over time, and generating insights from accumulated knowledge.
|
||||
|
||||

|
||||
|
||||
## The Mental Model
|
||||
|
||||
Traditional systems store files. Supermemory creates a living knowledge graph.
|
||||
At it's core, supermemory is powered by a custom learning model and a graph database that we built internally.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Traditional Systems" icon="folder">
|
||||
- Static files in folders
|
||||
- No connections between content
|
||||
- Search matches keywords
|
||||
- Information stays frozen
|
||||
<Card title="Learning model">
|
||||
Decides what and how to learn, what is important, when to forget, creating relations, etc.
|
||||
</Card>
|
||||
|
||||
<Card title="Supermemory" icon="network">
|
||||
- Dynamic knowledge graph
|
||||
- Rich relationships between memories
|
||||
- Semantic understanding
|
||||
- Information evolves and connects
|
||||
<Card title="Temporal Vector-graph engine">
|
||||
Where the learnings are actually stored, optimized for search. Fact-based temporal graph that has Vector, FTS, and graph built in.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Documents vs Memories
|
||||
But, you don't have to think about the above. The interface for users is as simple as it gets.
|
||||
|
||||
Understanding this distinction is crucial to using Supermemory effectively.
|
||||
|
||||
### Documents: Your Raw Input
|
||||
|
||||
Documents are what you provide - the raw materials:
|
||||
- PDF files you upload
|
||||
- Web pages you save
|
||||
- Text you paste
|
||||
- Images with text
|
||||
- Videos to transcribe
|
||||
|
||||
Think of documents as books you hand to Supermemory. See [Content Types](/concepts/content-types) for the full list of supported formats.
|
||||
|
||||
### Memories: Intelligent Knowledge Units
|
||||
|
||||
Memories are what Supermemory creates - the understanding:
|
||||
- Semantic chunks with meaning
|
||||
- Embedded for similarity search
|
||||
- Connected through relationships
|
||||
- Dynamically updated over time
|
||||
|
||||
Think of memories as the insights and connections your brain makes after reading those books.
|
||||
|
||||
<Note>
|
||||
**Key Insight**: When you upload a 50-page PDF, Supermemory doesn't just store it. It breaks it into hundreds of interconnected memories, each understanding its context and relationships to your other knowledge.
|
||||
</Note>
|
||||
|
||||
|
||||
## Memory Relationships
|
||||
|
||||

|
||||
|
||||
The graph connects memories through three types of relationships. For a deeper dive into how these relationships work, see [Graph Memory](/concepts/graph-memory).
|
||||
|
||||
### Updates: Information Changes
|
||||
|
||||
When new information contradicts or updates existing knowledge, Supermemory creates an "update" relationship.
|
||||
|
||||
<CodeGroup>
|
||||
```text Original Memory
|
||||
"You work at Supermemory as a content engineer"
|
||||
```
|
||||
|
||||
```text New Memory (Updates Original)
|
||||
"You now work at Supermemory as the CMO"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
The system tracks which memory is latest with an `isLatest` field, ensuring searches return current information.
|
||||
|
||||
### Extends: Information Enriches
|
||||
|
||||
When new information adds to existing knowledge without replacing it, Supermemory creates an "extends" relationship.
|
||||
|
||||
Continuing our "working at supermemory" analogy, a memory about what you work on would extend the memory about your role given above.
|
||||
|
||||
<CodeGroup>
|
||||
```text Original Memory
|
||||
"You work at Supermemory as the CMO"
|
||||
```
|
||||
|
||||
```text New Memory (Extension) - Separate From Previous
|
||||
"Your work consists of ensuring the docs are up to date, making marketing campaigns, SEO, etc."
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Both memories remain valid and searchable, providing richer context.
|
||||
|
||||
### Derives: Information Infers
|
||||
|
||||
The most sophisticated relationship - when Supermemory infers new connections from patterns in your knowledge.
|
||||
|
||||
<CodeGroup>
|
||||
```text Memory 1
|
||||
"Dhravya is the founder of Supermemory"
|
||||
```
|
||||
|
||||
```text Memory 2
|
||||
"Dhravya frequently discusses AI and machine learning innovations"
|
||||
```
|
||||
|
||||
```text Derived Memory
|
||||
"Supermemory is likely an AI-focused company"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
These inferences help surface insights you might not have explicitly stated.
|
||||
|
||||
## Processing Pipeline
|
||||
|
||||
Understanding the pipeline helps you optimize your usage:
|
||||
|
||||
| Stage | What Happens |
|
||||
|-------|-------------|
|
||||
| **Queued** | Document waiting to process
|
||||
| **Extracting** | Content being extracted |
|
||||
| **Chunking** | Creating memory chunks |
|
||||
| **Embedding** | Generating vectors |
|
||||
| **Indexing** | Building relationships |
|
||||
| **Done** | Fully searchable |
|
||||
|
||||
<Note>
|
||||
**Tip**: Larger documents and videos take longer. A 100-page PDF might take 1-2 minutes, while a 1-hour video could take 5-10 minutes.
|
||||
</Note>
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you understand how Supermemory works:
|
||||
## Get started in under a minute
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
Start adding content to your knowledge graph
|
||||
<Card title="1. Get an API key" icon="key" href="https://console.supermemory.ai">
|
||||
From the [developer console](https://console.supermemory.ai) — **API Keys → Create API Key**. `console.supermemory.ai` is where keys and usage live.
|
||||
</Card>
|
||||
|
||||
<Card title="Search Memories" icon="search" href="/search">
|
||||
Learn to query your knowledge effectively
|
||||
<Card title="2. Use it" icon="terminal" href="/using-supermemory">
|
||||
Install the SDK, drop in your key, add a memory, and search it — right below, or the full [ingest → retrieve loop](/using-supermemory).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CodeGroup>
|
||||
```bash TypeScript
|
||||
npm install supermemory
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
import Supermemory from "supermemory";
|
||||
|
||||
const client = new Supermemory({ apiKey: "sm_..." }); // from console.supermemory.ai → API Keys
|
||||
|
||||
await client.add({ content: "The user loves Paris.", containerTag: "user_123" });
|
||||
|
||||
const { results } = await client.search({
|
||||
q: "where does the user want to travel?",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from supermemory import Supermemory
|
||||
|
||||
client = Supermemory(api_key="sm_...") # from console.supermemory.ai → API Keys
|
||||
|
||||
client.add(content="The user loves Paris.", container_tag="user_123")
|
||||
|
||||
results = client.search(
|
||||
q="where does the user want to travel?",
|
||||
container_tag="user_123",
|
||||
)
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST https://api.supermemory.ai/v3/documents \
|
||||
-H "Authorization: Bearer sm_..." \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "The user loves Paris.",
|
||||
"containerTag": "user_123"
|
||||
}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## What you send: documents
|
||||
|
||||
A **document** is raw input — whatever you hand Supermemory:
|
||||
|
||||
- Conversation transcripts and messages
|
||||
- Text, markdown, HTML
|
||||
- PDFs, images, audio/video, code
|
||||
- URLs and connector items (Drive, Notion, Gmail, …)
|
||||
|
||||
You do not pre-chunk or pick an embedding model. See [Multi-modal ingestion](/concepts/content-types) for formats, and [Add context](/ingestion/add-memories) for the API.
|
||||
|
||||
Supermemory handles the ingestion and extraction for you. This also gives us a big advantage for quality - The engine extracts it in an optimized way with Contextual Chunking and other features for better quality search and memory generation.
|
||||
|
||||
> Use a stable **`customId`** when the same conversation or file will be updated later (sessions, connector syncs). That identity also drives [diff billing](/overview/billing#full-discount-on-already-seen-tokens-diff-billing) on re-ingest.
|
||||
|
||||
## What the pipeline does
|
||||
|
||||
| Stage | What happens |
|
||||
| --- | --- |
|
||||
| **Queued** | Accepted; waiting to run |
|
||||
| **Extracting** | Text / OCR / transcription / page fetch |
|
||||
| **Chunking** | Splits content for retrieval (type-aware where needed) |
|
||||
| **Embedding** | Vectors for similarity search |
|
||||
| **Indexing** | Makes chunks and derived structure searchable |
|
||||
| **Done** | Document path is ready for search |
|
||||
|
||||
```typescript
|
||||
const doc = await client.add({
|
||||
content: conversationText,
|
||||
containerTag: "user_123",
|
||||
customId: "chat_session_1",
|
||||
});
|
||||
|
||||
// Poll until ready
|
||||
const status = await client.documents.get(doc.id);
|
||||
// status.status → "queued" | "extracting" | ... | "done" | "failed"
|
||||
```
|
||||
|
||||
Larger PDFs and long video take longer. Short chat turns usually finish in seconds.
|
||||
|
||||
## Dreaming (how memories enter the graph)
|
||||
|
||||
Document **status `done`** means chunks are indexed for search. **Memories** — the graph facts, updates, and derives — come from a second phase called **dreaming**.
|
||||
|
||||
This is when the content is passed through the memory model and merged, arranged and organized for the future.
|
||||
|
||||
Pass `dreaming` on [add](/ingestion/add-memories):
|
||||
|
||||
| Mode | Default? | Behavior | When to use |
|
||||
| --- | --- | --- | --- |
|
||||
| **`dynamic`** | Yes | Related documents are grouped so memories form from **coherent units**, not one isolated write at a time. Graph quality is higher for real multi-turn / multi-doc flows. Memory extraction may continue **after** `status: "done"`. | Production agents, connectors, ongoing sessions |
|
||||
| **`instant`** | No | This document is dreamed **on its own, right away**. Memories are available as soon as processing finishes for that doc. Bills **one extra [operation](/overview/billing)** per document. | Demos, quickstarts, “I need the graph now” |
|
||||
|
||||
```typescript
|
||||
// Production default — omit or set explicitly
|
||||
await client.add({
|
||||
content: conversationText,
|
||||
containerTag: "user_123",
|
||||
customId: "chat_session_1",
|
||||
dreaming: "dynamic",
|
||||
});
|
||||
|
||||
// Need memories immediately (e.g. tutorial)
|
||||
await client.add({
|
||||
content: conversationText,
|
||||
containerTag: "user_123",
|
||||
customId: "chat_session_1",
|
||||
dreaming: "instant",
|
||||
});
|
||||
```
|
||||
|
||||
**Rule of thumb:** prefer **`dynamic`** for quality and cost in real apps, use **`instant`** when the next step is a memory search or profile that must reflect this document immediately (as in the [quickstart](/quickstart)). Keeping it dynamic helps it pair better with other memories and better connections, inferences to be made.
|
||||
|
||||
How those memories connect and stay true over time is [Graph memory](/concepts/graph-memory). API detail: [Processing modes](/ingestion/add-memories#processing-modes).
|
||||
|
||||
## What you get out
|
||||
|
||||
After the pipeline runs, the same document leads to three things -> Chunks, Memories and Profile. (in the same `containerTag`):
|
||||
|
||||
| Output | Role | Go deeper |
|
||||
| --- | --- | --- |
|
||||
| **Document chunks** | Grounding in the raw source (RAG / SuperRAG) | [SuperRAG](/concepts/super-rag), [Search API](/recall/search) |
|
||||
| **Memories** | Extracted facts in a living graph — updates, links, time | [Graph memory](/concepts/graph-memory) |
|
||||
| **Profile** | A sample of memories, static + dynamic summary for always-on context | [Profiles](/concepts/user-profiles), [Profile API](/recall/user-profiles) |
|
||||
|
||||
Supermemory does **not** only store the file. It derives **memories** (understanding) and keeps **chunks** (the source) so you can personalize *and* ground. That distinction is the core of [Memory vs RAG](/concepts/memory-vs-rag).
|
||||
|
||||
## Isolation and identity
|
||||
|
||||
- **`containerTag`** — hard isolation boundary (user, tenant, project). See [Container tags](/concepts/container-tags).
|
||||
- **Metadata** — soft dimensions *inside* a tag for filtering. See [Metadata filtering](/concepts/filtering).
|
||||
- **Scoped API keys** — credentials that cannot cross a container. See [API keys](/authentication#scoped-api-keys).
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Graph memory" icon="vector-square" href="/concepts/graph-memory">
|
||||
How facts connect, update, and stay true over time.
|
||||
</Card>
|
||||
<Card title="Multi-modal ingestion" icon="file-stack" href="/concepts/content-types">
|
||||
Formats, extractors, and what you can send.
|
||||
</Card>
|
||||
<Card title="Add context" icon="plus" href="/ingestion/add-memories">
|
||||
API: add, customId, files, dreaming, status.
|
||||
</Card>
|
||||
<Card title="Search API" icon="search" href="/recall/search">
|
||||
Query documents and memories after the pipeline finishes.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -216,10 +216,10 @@ 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
|
||||
# Also searches general knowledge
|
||||
results = client.search.memories(
|
||||
q="What phone should I recommend?",
|
||||
container_tag="user_123", # Gets user memories
|
||||
search_mode="hybrid", # Also searches general knowledge
|
||||
)
|
||||
|
||||
# Results include:
|
||||
|
|
@ -250,10 +250,10 @@ Supermemory provides both capabilities in a unified platform, ensuring your agen
|
|||
<Card title="Super RAG" icon="bolt" href="/concepts/super-rag">
|
||||
Our managed RAG solution
|
||||
</Card>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
<Card title="Add Memories" icon="plus" href="/ingestion/add-memories">
|
||||
Start ingesting content
|
||||
</Card>
|
||||
<Card title="Search" icon="search" href="/search">
|
||||
<Card title="Search" icon="search" href="/recall/search">
|
||||
Query your memories and documents
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
134
apps/docs/concepts/multi-tenancy-examples.mdx
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
---
|
||||
title: "Multi-tenancy Examples"
|
||||
sidebarTitle: "Examples"
|
||||
description: "Common container tag and metadata patterns for personal agents, company agents, email assistants, and support platforms"
|
||||
icon: "list-checks"
|
||||
---
|
||||
|
||||
A few common shapes multi-tenancy takes in practice, combining [container tags](/concepts/container-tags) for isolation with [metadata filters](/concepts/filtering) for organization within a boundary.
|
||||
|
||||
---
|
||||
|
||||
## Personal agent
|
||||
|
||||
A single container tag per user is enough — there's no shared data to leak, so metadata is optional.
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "User prefers morning workouts and vegetarian meals",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
|
||||
const results = await client.search({
|
||||
q: "workout preferences",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Company agent (shared + personal memory)
|
||||
|
||||
A company-wide assistant usually needs two kinds of containers: one **shared** container the whole org reads from, and one **personal** container per employee that nobody else can see.
|
||||
|
||||
```typescript
|
||||
// Shared org knowledge — visible to everyone at the company
|
||||
await client.add({
|
||||
content: "Q3 roadmap: ship the mobile app redesign by end of August",
|
||||
containerTag: "org_acme_shared",
|
||||
metadata: { team: "product", type: "roadmap" },
|
||||
});
|
||||
|
||||
// Personal memory — only this employee's agent should see this
|
||||
await client.add({
|
||||
content: "Prefers async updates over meetings",
|
||||
containerTag: "org_acme_user_alex",
|
||||
});
|
||||
```
|
||||
|
||||
Inside the shared container, use metadata to scope queries to a team rather than creating a container tag per team:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
q: "roadmap updates",
|
||||
containerTag: "org_acme_shared",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [{ key: "team", value: "product" }],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
An employee's agent typically queries both containers — their personal one plus the shared one — and merges the results, since the container tag boundary is per-request rather than per-user.
|
||||
|
||||
---
|
||||
|
||||
## Email assistant
|
||||
|
||||
One container tag per user, with metadata carrying email-specific properties like label, sender, or folder — so the assistant can answer things like *"find the Spotify email tagged Promotional"*.
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Your Spotify Premium receipt for July — $11.99 charged",
|
||||
containerTag: "user_123",
|
||||
metadata: {
|
||||
source: "gmail",
|
||||
sender: "no-reply@spotify.com",
|
||||
label: "Promotional",
|
||||
},
|
||||
});
|
||||
|
||||
const results = await client.search({
|
||||
q: "spotify",
|
||||
containerTag: "user_123",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "source", value: "gmail" },
|
||||
{ key: "label", value: "Promotional" },
|
||||
],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-tenant support platform
|
||||
|
||||
Each customer gets their own container tag, and metadata tracks ticket-level fields like status and priority — so "open, high-priority tickets" is a filter, not a new tag, and it can never accidentally include another customer's tickets.
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Customer reports checkout button unresponsive on Safari",
|
||||
containerTag: "org_customer_442",
|
||||
metadata: { status: "open", priority: "high", channel: "chat" },
|
||||
});
|
||||
|
||||
const results = await client.search({
|
||||
q: "checkout issue",
|
||||
containerTag: "org_customer_442",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "status", value: "open" },
|
||||
{ key: "priority", value: "high" },
|
||||
],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Multi-tenancy Overview" icon="users" href="/concepts/multi-tenancy">
|
||||
Why container tags and metadata are separate mechanisms.
|
||||
</Card>
|
||||
<Card title="Container Tags" icon="folder" href="/concepts/container-tags">
|
||||
How isolation works, naming rules, and access control.
|
||||
</Card>
|
||||
<Card title="Organizing & Filtering" icon="filter" href="/concepts/filtering">
|
||||
Metadata filter types, combining `AND`/`OR`, and query limits.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
114
apps/docs/concepts/multi-tenancy.mdx
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
---
|
||||
title: "Multi-tenancy Overview"
|
||||
sidebarTitle: "Overview"
|
||||
description: "How Supermemory isolates and organizes memories across users, tenants, and projects"
|
||||
icon: "users"
|
||||
---
|
||||
|
||||
Most apps built on Supermemory serve more than one user, customer, or tenant out of a single Supermemory organization. Multi-tenancy is how you keep those memories apart — so User A's data is never visible to User B, and so you can still slice and query within a user's own data by things like category, status, or date.
|
||||
|
||||
Supermemory gives you two complementary tools for this:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Container Tags" icon="folder" href="/concepts/container-tags">
|
||||
**Isolation.** A container tag is a hard boundary — its own namespace. Memories in one tag are never returned by a search scoped to another tag.
|
||||
</Card>
|
||||
<Card title="Metadata Filtering" icon="database" href="/concepts/filtering">
|
||||
**Organization.** Metadata is a set of custom key/value properties on a memory that you filter by — category, priority, date, participants, anything you define.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
They solve different problems, and most production apps use both together.
|
||||
|
||||
---
|
||||
|
||||
## Why two mechanisms
|
||||
|
||||
It's tempting to reach for one tool and make it do everything, but tags and metadata aren't interchangeable — they answer different questions.
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| "Which tenant does this memory belong to?" | **Container tag** |
|
||||
| "Within this tenant's memories, which ones match `status: open`?" | **Metadata filter** |
|
||||
| "Can this API key even see tenant X's data?" | **Container tag** (enforced as an access boundary) |
|
||||
| "Find memories tagged `engineering` created after March" | **Metadata filter** |
|
||||
|
||||
A container tag decides **whether a memory is reachable at all** for a given request. Metadata decides **which of the reachable memories match**. Filtering never crosses a container tag boundary — you can't use metadata to peek into another tenant's container.
|
||||
|
||||
---
|
||||
|
||||
## How they work together
|
||||
|
||||
A typical multi-tenant write scopes the memory to a tenant with a container tag, then attaches metadata for finer-grained querying later:
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Customer requested a refund for order #4821",
|
||||
containerTag: "org_acme", // isolates to the "acme" tenant
|
||||
metadata: {
|
||||
category: "support",
|
||||
status: "open",
|
||||
priority: "high",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
And a search combines both: the container tag restricts *which tenant's data* is in scope, and filters narrow down *which memories within that tenant* come back:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
q: "refund request",
|
||||
containerTag: "org_acme",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "support" },
|
||||
{ key: "status", value: "open" },
|
||||
],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
Container tags are **required** for isolation and validated as an access boundary. Metadata filters are **optional** — a search with just `containerTag` and no `filters` still only returns that tenant's memories.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Choosing your boundary
|
||||
|
||||
Container tags are the layer that should map to your actual tenancy model — pick the level that matches what "one isolated space" means in your app:
|
||||
|
||||
| Pattern | Example | Use case |
|
||||
|---------|---------|----------|
|
||||
| Per-user | `user_{userId}` | Consumer app, personal memory per user |
|
||||
| Per-tenant/org | `org_{orgId}` | B2B SaaS, one container per customer org |
|
||||
| Hierarchical | `org:{orgId}:user:{userId}` | Multi-level — isolate by org, and optionally drill into a user within it |
|
||||
| Per-project | `project_{projectId}` | Workspace- or project-scoped content |
|
||||
|
||||
Everything *within* that boundary — categories, statuses, dates, custom fields — is metadata, not a new tag. Don't create a new container tag for every property you want to filter on; that's what metadata is for.
|
||||
|
||||
---
|
||||
|
||||
## Access control
|
||||
|
||||
Container tags aren't just organizational — they're enforced as an authorization boundary. API keys and org members can be restricted to specific tags, so a request for a tag outside the caller's allowed set is rejected with `403 Forbidden` rather than silently filtered. See [Container Tags → Access control](/concepts/container-tags#access-control) for the details.
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Examples" icon="list-checks" href="/concepts/multi-tenancy-examples">
|
||||
Personal agents, company agents, email assistants, and support platforms.
|
||||
</Card>
|
||||
<Card title="Container Tags" icon="folder" href="/concepts/container-tags">
|
||||
How isolation works, naming rules, and access control.
|
||||
</Card>
|
||||
<Card title="Organizing & Filtering" icon="filter" href="/concepts/filtering">
|
||||
Metadata filter types, combining `AND`/`OR`, and query limits.
|
||||
</Card>
|
||||
<Card title="Scoped API keys" icon="key" href="/authentication#scoped-api-keys">
|
||||
Mint keys that can only touch one container tag.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
305
apps/docs/concepts/rules.mdx
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
---
|
||||
title: "Rules of supermemory"
|
||||
description: "Best practices and things to consider when using supermemory in your system"
|
||||
sidebarTitle: "Rules of supermemory"
|
||||
icon: "gavel"
|
||||
---
|
||||
|
||||
Supermemory provides powerful primitives and the full context stack for building AI agents. This page collects rules of thumb from building and running supermemory in production. They aren't hard constraints, just shortcuts that save you time, cost, and confusing search results.
|
||||
|
||||
## Thinking about ingestion
|
||||
|
||||
### What to ingest, and what not to
|
||||
|
||||
#### Send what you would send to a human for memory
|
||||
|
||||
Treat supermemory as a database for human-like understanding of knowledge and search. You should be feeding it unstructured data like documents, chat conversations, or even images, videos, and websites. You should not be ingesting database records or CSVs, since those are more structured.
|
||||
|
||||
Although supermemory _does_ support learning from long-horizon structured data, typically the right approach is to give an agent tools to traverse the structure directly.
|
||||
|
||||
Agents benefit most from having a _general_ idea of the topic alongside tools to look through the data. For example, knowing "this company uses PostHog and has three products (API, Console, and Landing Page)" helps the agent navigate the PostHog data more effectively.
|
||||
|
||||
#### A quick test for where information belongs
|
||||
|
||||
| Context | Test result | Where it goes |
|
||||
| --- | --- | --- |
|
||||
| "Sarah prefers async updates and is being promoted to VP of Product" | A colleague would remember this | supermemory: [memory search](/recall/search) + profile |
|
||||
| The Q3 planning doc, support tickets, the API changelog | A colleague would look it up by meaning | supermemory: ingested as documents, recalled with document search |
|
||||
| Invoice #4821, total \$1,340.50, status `paid` | Queried by ID, summed in reports | your database |
|
||||
| "Answer in the user's language. Never quote internal pricing." | Every request needs it, verbatim | system prompt |
|
||||
|
||||
Two things about this table that trip people up.
|
||||
|
||||
**"Remember" and "look up" are both supermemory, but different reads.** You [ingest documents](/ingestion/add-memories); the pipeline derives memories from them and maintains a profile per [container tag](/concepts/how-it-works). `client.search({ searchMode: "memories" })` recalls the derived facts. `client.search({ searchMode: "documents" })` recalls the source material itself. A support agent usually needs both: memories for "this customer runs self-hosted and already tried reinstalling", documents for the actual troubleshooting guide.
|
||||
|
||||
**Supermemory is not your system of record.** There's no SQL over memories, no joins, no aggregates, no querying by primary key. Keep transactional data in your database, and ingest the narrative *around* it ("the customer disputed invoice #4821 and churned over it") so your AI understands what the rows mean.
|
||||
|
||||
#### Ingest with SuperRag when you just need search
|
||||
|
||||
When you know you only want search, you can cut costs by 5x. Just set `taskType` when ingesting:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.add({
|
||||
content: "testing",
|
||||
containerTag: "test",
|
||||
taskType: "superrag"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.add(
|
||||
content="testing",
|
||||
container_tag="test",
|
||||
task_type="superrag"
|
||||
)
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "testing",
|
||||
"containerTag": "test",
|
||||
"taskType": "superrag"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
#### Use hybrid mode when searching over SuperRag content
|
||||
|
||||
`hybrid` mode makes it much easier to get complete results from supermemory when you have both memories and documents.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const results = await client.search({
|
||||
q: "test",
|
||||
searchMode: "hybrid"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
results = client.search.memories(
|
||||
q="test",
|
||||
search_mode="hybrid"
|
||||
)
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "test",
|
||||
"searchMode": "hybrid"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
The response comes back in this shape:
|
||||
|
||||
```ts
|
||||
({ memory: string } | { chunk: string })[]
|
||||
```
|
||||
|
||||
Use `item.memory || item.chunk` when reading results.
|
||||
|
||||
#### Keep documents medium-sized
|
||||
|
||||
While supermemory can handle documents with 400k+ tokens, sending smaller, self-contained documents produces better-quality learnings. The internal learning agent and "dreaming" jobs reflect on memories to build relations between them. If documents are too long, fewer memories get generated and fewer relations get made.
|
||||
|
||||
We also recommend ingesting documents sequentially within a single `containerTag` where possible, since that's how supermemory determines what came first (used for `updates` relations and temporal reasoning).
|
||||
|
||||
#### Handling single-threaded chatbots
|
||||
|
||||
Many agent harnesses, like `openclaw`, `hermes`, and other single-threaded custom agents, run one long conversation with compaction. Some tips for managing single-threaded (and other long-running) conversations:
|
||||
|
||||
1. **Send a `customId` when you can**: a sessionId, conversationId, document ID, or any representation of a "session" in your application.
|
||||
2. **Generate one if you don't have one**, e.g. the current 4-hour window: `${new Date().toISOString().slice(0,10)}-${new Date().getHours()>>2}`. Adjust the window size based on traffic per container.
|
||||
3. **Send the same prefix**: keep the start of the document identical across ingests under the same `customId` so supermemory can diff cleanly. You can either resend the full growing transcript each time, or send only the new turns since your last ingest. Just don't mix the two for the same `customId`.
|
||||
|
||||
```
|
||||
Ingestion 1:
|
||||
Assistant: Hey, how are you?
|
||||
User: I'm fine.
|
||||
|
||||
Ingestion 2 (full transcript):
|
||||
Assistant: Hey, how are you?
|
||||
User: I'm fine.
|
||||
Assistant: Anything I can help with today?
|
||||
|
||||
Ingestion 2 (delta only):
|
||||
Assistant: Anything I can help with today?
|
||||
```
|
||||
|
||||
You're only billed for the new (diff) content you send, so doing this well improves performance, cuts cost, and keeps usage simple.
|
||||
|
||||
## Architecture and design
|
||||
|
||||
#### Let supermemory handle the learning
|
||||
|
||||
Don't pass content through an additional LLM before sending it to supermemory. Supermemory does that learning automatically. Because the engine already knows what it knows, it can contextually summarize, update, and forget information as needed.
|
||||
|
||||
#### Configure what you want it to learn
|
||||
|
||||
Ground it with `entityContext` to prevent drift over time. Picture a third person watching a conversation between two people: what do they remember, and about whom? Giving supermemory context about the entity itself helps ground its learnings and prevents drift and decay over time.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const user = auth.user.name;
|
||||
await client.add({
|
||||
content: "Hey, I'm doing great!",
|
||||
containerTag: user,
|
||||
entityContext: `User is ${user}, talking to assistant Kira`
|
||||
}); // -> supermemory learns "Dhravya is doing great"
|
||||
```
|
||||
|
||||
```python Python
|
||||
user = auth.user.name
|
||||
client.add(
|
||||
content="Hey, I'm doing great!",
|
||||
container_tag=user,
|
||||
entity_context=f"User is {user}, talking to assistant Kira"
|
||||
) # -> supermemory learns "Dhravya is doing great"
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Hey, I'\''m doing great!",
|
||||
"containerTag": "dhravya",
|
||||
"entityContext": "User is dhravya, talking to assistant Kira"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
#### Use containerTags, don't over-stuff a single one
|
||||
|
||||
Use a containerTag wherever there's a hard permission boundary.
|
||||
|
||||
- **Don't**: ingest everything into one container and filter through it with metadata.
|
||||
- **Do**: give each user their own container, and still filter by metadata inside it if needed.
|
||||
|
||||
There's little correlation between the number of items in a container and its quality or latency. Supermemory is built for multi-tenant workloads and supports up to 1M documents and 10M memories per container.
|
||||
|
||||
#### Use metadata filtering for detailed scoping inside containers
|
||||
|
||||
You'll often want to ingest and search with filtering inside a single container. Say the engineering team ingests this:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.add({
|
||||
content: "The team prefers TypeScript",
|
||||
metadata: { team: "Engineering" },
|
||||
containerTag: "org-supermemory",
|
||||
filterByMetadata: { team: "Engineering" }
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.add(
|
||||
content="The team prefers TypeScript",
|
||||
metadata={"team": "Engineering"},
|
||||
container_tag="org-supermemory",
|
||||
filter_by_metadata={"team": "Engineering"}
|
||||
)
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "The team prefers TypeScript",
|
||||
"metadata": { "team": "Engineering" },
|
||||
"containerTag": "org-supermemory",
|
||||
"filterByMetadata": { "team": "Engineering" }
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
> Tip: `filterByMetadata` ensures a fact like "the team prefers TypeScript" is only built on top of the engineering team's knowledge.
|
||||
|
||||
Later, the research team ingests this, with the same `containerTag` but different `metadata`:
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "The team prefers Python",
|
||||
"metadata": { "team": "Research" },
|
||||
"containerTag": "org-supermemory",
|
||||
"filterByMetadata": { "team": "Research" }
|
||||
}
|
||||
```
|
||||
|
||||
This keeps research's and engineering's memories from mixing, even though they share a `containerTag`. When searching:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const results = await client.search({
|
||||
q: "preferred language",
|
||||
containerTag: "org-supermemory",
|
||||
searchMode: "documents",
|
||||
filters: {
|
||||
AND: [{ key: "team", value: "research" }]
|
||||
}
|
||||
}); // -> "python"
|
||||
```
|
||||
|
||||
```python Python
|
||||
results = client.search.documents(
|
||||
q="preferred language",
|
||||
container_tag="org-supermemory",
|
||||
filters={
|
||||
"AND": [{"key": "team", "value": "research"}]
|
||||
}
|
||||
) # -> "python"
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "preferred language",
|
||||
"containerTag": "org-supermemory",
|
||||
"filters": {
|
||||
"AND": [{ "key": "team", "value": "research" }]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Thinking about harness
|
||||
|
||||
Think about how to bring memory back into the harness itself.
|
||||
|
||||
#### Embrace a little noise
|
||||
|
||||
You might want to hyper-optimize everything that goes into the model's prompt, but counterintuitively, you sometimes want to embrace noise, since true personalization comes from distinctive information.
|
||||
|
||||
Example: a user says "hi" and the LLM responds "Hey Dhravya! How's it going? How's the new office coming along?" instead of something generic.
|
||||
|
||||
Supermemory is designed for this: it returns an average of 10 tokens per fact, so even 50 facts is just 500 tokens of context, cheap enough to stay generous.
|
||||
|
||||
#### Tools, hooks, and making the choice
|
||||
|
||||
Think about how supermemory fits into your harness. Example, a personal agent:
|
||||
|
||||
- **Session start hook** → load profile
|
||||
- **On-message hook** → enrich the prompt with search
|
||||
- **On-stop hook** → save the conversation
|
||||
|
||||
Play around with these options in our [playground](https://console.supermemory.ai/playground), and read more in [this post on memory at the harness level](https://dhravya.dev/writing/memory-on-the-harness-level/).
|
||||
|
|
@ -18,11 +18,10 @@ When you add content, Supermemory:
|
|||
5. **Builds relationships** — Connects new knowledge to existing memories
|
||||
|
||||
```typescript
|
||||
// Just add content — Supermemory handles the rest
|
||||
await client.add({
|
||||
content: pdfBase64,
|
||||
contentType: "pdf",
|
||||
title: "Technical Documentation"
|
||||
// Just upload — Supermemory handles the rest
|
||||
await client.documents.uploadFile({
|
||||
file: fs.createReadStream('technical-documentation.pdf'),
|
||||
metadata: JSON.stringify({ title: "Technical Documentation" })
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -30,6 +29,63 @@ No chunking strategies to configure. No embedding models to choose. It just work
|
|||
|
||||
---
|
||||
|
||||
## Ingesting as pure SuperRAG (`taskType: "superrag"`)
|
||||
|
||||
By default, every `client.add()` call runs on the **memory** path (`taskType: "memory"`): Supermemory chunks and embeds the content for retrieval, *and* runs it through the memory pipeline — extracting facts, updating the profile, and linking it into the knowledge graph.
|
||||
|
||||
If you're ingesting content that's purely reference material — documentation, a large PDF, a knowledge base article — and you don't need Supermemory to derive personal facts or update a profile from it, set `taskType: "superrag"`. It skips the memory pipeline entirely and only does the chunk → embed → index work needed to make the content searchable.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.add({
|
||||
content: "...", // e.g. a long internal wiki page
|
||||
containerTag: "docs_kb",
|
||||
taskType: "superrag",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.add(
|
||||
content="...",
|
||||
container_tag="docs_kb",
|
||||
task_type="superrag",
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "...",
|
||||
"containerTag": "docs_kb",
|
||||
"taskType": "superrag"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
| | `taskType: "memory"` (default) | `taskType: "superrag"` |
|
||||
|---|---|---|
|
||||
| Chunking, embedding, indexing | ✅ | ✅ — searchable immediately via `searchMode: "documents"` |
|
||||
| Fact extraction into memories | ✅ | ❌ skipped |
|
||||
| Profile (`static`/`dynamic`/buckets) updates | ✅ | ❌ skipped |
|
||||
| Graph linking (updates/extends/derives) | ✅ | ❌ skipped |
|
||||
| Price per ingested token | Full rate | **5x cheaper** |
|
||||
|
||||
<Tip>
|
||||
`taskType: "superrag"` is a **5x discount on ingested tokens** — `sm_superrag_text`/`sm_superrag_rich` are priced at 20% of `sm_tokens_text`/`sm_tokens_rich`. See [Billing → Memory vs SuperRAG tokens](/overview/billing#memory-vs-superrag-tokens) for the exact rates.
|
||||
</Tip>
|
||||
|
||||
<Warning>
|
||||
Content ingested as `superrag` is retrievable via document search (`searchMode: "documents"`), but it will **never** surface as a memory, contribute to a user's profile, or connect into the knowledge graph. Use it for reference material you want searchable, not for anything that should shape what Supermemory knows about a user — that still needs the default `taskType: "memory"`.
|
||||
</Warning>
|
||||
|
||||
When you're searching over a mix of both, `searchMode: "hybrid"` (below) is what pulls memory-path facts and superrag-path document chunks into one result set. More ingestion guidance: [Rules of supermemory → Ingest with SuperRag when you just need search](/concepts/rules#ingest-with-superrag-when-you-just-need-search).
|
||||
|
||||
---
|
||||
|
||||
## Smart Chunking by Content Type
|
||||
|
||||
Different content types need different chunking strategies. Supermemory applies the optimal approach automatically:
|
||||
|
|
@ -170,7 +226,13 @@ You focus on building your product. Supermemory handles the RAG complexity.
|
|||
<Card title="Memory vs RAG" icon="scale" href="/concepts/memory-vs-rag">
|
||||
When to use each approach
|
||||
</Card>
|
||||
<Card title="Search" icon="search" href="/search">
|
||||
<Card title="Search" icon="search" href="/recall/search">
|
||||
Search parameters and optimization
|
||||
</Card>
|
||||
<Card title="Billing" icon="receipt" href="/overview/billing#memory-vs-superrag-tokens">
|
||||
Exact meter rates for memory vs SuperRAG tokens
|
||||
</Card>
|
||||
<Card title="Adding Memories" icon="plus" href="/ingestion/add-memories">
|
||||
`taskType` and other ingestion parameters
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
---
|
||||
title: "User Profiles"
|
||||
sidebarTitle: "User Profiles"
|
||||
sidebarTitle: "Profiles"
|
||||
description: "Automatically maintained context about your users"
|
||||
icon: "circle-user"
|
||||
---
|
||||
|
||||
User profiles are **automatically maintained collections of facts about your users** that Supermemory builds from all their interactions. Think of it as a persistent "about me" document that's always up-to-date.
|
||||
|
||||
Each `containerTag` gets it's own profile.
|
||||
|
||||
> Note: It's called "user" profile, but in reality it can be anything - an agent, organization, etc.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Instant Context" icon="bolt">
|
||||
No search needed — comprehensive user info always ready
|
||||
|
|
@ -30,6 +34,40 @@ Traditional memory systems rely entirely on search:
|
|||
|
||||
**Profiles provide the foundation**: Instead of searching for basic context, profiles give your LLM a complete picture of who the user is.
|
||||
|
||||

|
||||
|
||||
A pure search architecture means every turn pays a `search(prompt)` round trip before the agent can respond. A profile is attached once and sits alongside every user prompt and agent output — no extra call, no latency, and no risk of the query missing something important.
|
||||
|
||||
---
|
||||
|
||||
## Non-literal-matching use cases
|
||||
|
||||
Semantic search retrieves content that's *similar to the query* — it's built for questions like "what did we discuss about the migration?" It's a poor fit for facts that should be known **regardless of what's being asked**, because there's rarely a query that's semantically close to them.
|
||||
|
||||
The clearest example is the user's own name. If someone tells your agent "call me Dhravya, not my full name" once during onboarding, that fact has almost nothing in common — vector-wise — with "help me plan a trip to Japan" or "review this PR." A search for either of those queries will not surface the name preference, because search only returns what's relevant to the query, and a name preference isn't relevant to trip planning or code review — it should just always be there.
|
||||
|
||||
```typescript
|
||||
// Weeks earlier, during onboarding
|
||||
await client.add({
|
||||
content: "Call me Dhravya, not my full first name",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
|
||||
// Later — an unrelated query
|
||||
const results = await client.search({
|
||||
q: "help me plan a trip to Japan",
|
||||
containerTag: "user_123",
|
||||
});
|
||||
// The name preference won't be in `results` — it's not semantically
|
||||
// related to trip planning, so search correctly leaves it out.
|
||||
|
||||
// But it's always in the profile, independent of the query:
|
||||
const { profile } = await client.profile({ containerTag: "user_123" });
|
||||
console.log(profile.static); // ["User goes by Dhravya, not their full name", ...]
|
||||
```
|
||||
|
||||
This is the general pattern: names, pronouns, timezone, tone/format preferences, role, and other facts that should color *every* response — not just responses to a matching query — belong in the profile, not left to be caught by search. If your agent needs to "just know" something at all times, that's a strong signal it belongs in the profile rather than relying on a lucky semantic match.
|
||||
|
||||
---
|
||||
|
||||
## Static vs Dynamic
|
||||
|
|
@ -54,17 +92,42 @@ Recent context and temporary states:
|
|||
|
||||
---
|
||||
|
||||
## Buckets
|
||||
|
||||
Static and dynamic split facts by how long-lived they are. **Buckets** split them by *topic* — a third, independent axis you define, like `preferences`, `goals`, or `work`. As content is ingested, a classifier sorts each fact into the buckets it matches.
|
||||
|
||||
Every org starts with a default `preferences` bucket. Add your own in console settings at the organization level, or per space — space buckets are add-only, so a container tag always keeps every org-level bucket.
|
||||
|
||||
```typescript
|
||||
const { profile } = await client.profile({
|
||||
containerTag: "user_123",
|
||||
include: ["buckets"],
|
||||
buckets: ["preferences", "goals"], // optional — omit for all configured buckets
|
||||
});
|
||||
|
||||
console.log(profile.buckets.preferences);
|
||||
console.log(profile.buckets.goals);
|
||||
```
|
||||
|
||||
Bucket descriptions steer the classifier, so a precise description ("explicit first-person preferences only, exclude inferred traits") produces cleaner buckets than a vague one. Buckets are separate from [`filterPrompt`](/concepts/customization), which controls what gets ingested at all — buckets only organize facts that already made it into the profile.
|
||||
|
||||
<Card title="Profile Buckets reference" icon="tags" href="/user-profiles/buckets">
|
||||
Request bucketed profiles, create buckets at the org or space level, get AI-generated suggestions, and see validation limits.
|
||||
</Card>
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
Profiles are built automatically through ingestion:
|
||||
|
||||
1. **Ingest content** — Users [add documents](/add-memories), chat, or any content
|
||||
1. **Ingest content** — Users [add documents](/ingestion/add-memories), chat, or any content
|
||||
2. **Extract facts** — AI analyzes content for facts about the user
|
||||
3. **Update profile** — System adds, updates, or removes facts
|
||||
4. **Always current** — Profiles reflect the latest information
|
||||
|
||||
<Note>
|
||||
You don't manually manage profiles — they build themselves as users interact. Start by [adding content](/add-memories) to see profiles in action.
|
||||
You don't manually manage profiles — they build themselves as users interact. Start by [adding content](/ingestion/add-memories) to see profiles in action.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
|
@ -90,6 +153,36 @@ User asks: **"Can you help me debug this?"**
|
|||
|
||||
---
|
||||
|
||||
## Filtering Profiles
|
||||
|
||||
Not many people realize this, but profiles support the same [metadata filtering](/concepts/filtering) as memory and document search. A profile is synthesized from the underlying memories in a container tag, so any `AND`/`OR` metadata filter you'd pass to `search` also narrows which memories are eligible to contribute to `static`, `dynamic`, and `buckets`.
|
||||
|
||||
```typescript
|
||||
// Only build the profile from memories tagged as onboarding data
|
||||
const { profile } = await client.profile({
|
||||
containerTag: "user_123",
|
||||
filters: {
|
||||
AND: [{ key: "source", value: "onboarding" }],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This is useful when a container tag mixes memories from several sources or contexts and you only want one of them reflected in the profile — for example, a support agent that should only see profile facts derived from support tickets, not from an internal wiki synced into the same container:
|
||||
|
||||
```typescript
|
||||
const { profile } = await client.profile({
|
||||
containerTag: "org_customer_442",
|
||||
filters: {
|
||||
AND: [{ key: "channel", value: "support_ticket" }],
|
||||
},
|
||||
include: ["static", "dynamic"],
|
||||
});
|
||||
```
|
||||
|
||||
Filters apply on top of the search query too — combine `q` and `filters` to scope both the profile synthesis and the accompanying search results in one call. See [Filtering Profiles](/recall/user-profiles#filtering-profiles) for the full parameter reference.
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Personalized AI Assistants
|
||||
|
|
@ -126,16 +219,19 @@ Profiles provide: preferred languages, coding style, current project context.
|
|||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="User Profiles API" icon="code" href="/user-profiles">
|
||||
<Card title="User Profiles API" icon="code" href="/recall/user-profiles">
|
||||
Fetch and use profiles via the API
|
||||
</Card>
|
||||
<Card title="Profile Buckets" icon="tags" href="/user-profiles/buckets">
|
||||
Create and configure topical buckets
|
||||
</Card>
|
||||
<Card title="Graph Memory" icon="network" href="/concepts/graph-memory">
|
||||
How the underlying knowledge graph works
|
||||
</Card>
|
||||
<Card title="AI SDK Integration" icon="triangle" href="/integrations/ai-sdk">
|
||||
Automatic profile injection with AI SDK
|
||||
</Card>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
<Card title="Add Memories" icon="plus" href="/ingestion/add-memories">
|
||||
Build profiles by adding content
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "GitHub Connector"
|
||||
description: "Connect GitHub repositories to sync documentation files into your Supermemory knowledge base"
|
||||
icon: "github"
|
||||
icon: "/images/github-icon.svg"
|
||||
---
|
||||
|
||||
Connect GitHub repositories to sync documentation files into your Supermemory knowledge base with OAuth authentication, webhook support, and automatic incremental syncing.
|
||||
|
|
@ -25,7 +25,7 @@ The GitHub connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
|
||||
const connection = await client.connections.create('github', {
|
||||
redirectUrl: 'https://yourapp.com/auth/github/callback',
|
||||
containerTags: ['user-123', 'github-sync'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 5000,
|
||||
metadata: {
|
||||
source: 'github',
|
||||
|
|
@ -48,7 +48,7 @@ The GitHub connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
connection = client.connections.create(
|
||||
'github',
|
||||
redirect_url='https://yourapp.com/auth/github/callback',
|
||||
container_tags=['user-123', 'github-sync'],
|
||||
container_tag='user-123',
|
||||
document_limit=10000,
|
||||
metadata={
|
||||
'source': 'github',
|
||||
|
|
@ -68,7 +68,7 @@ The GitHub connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/auth/github/callback",
|
||||
"containerTags": ["user-123", "github-sync"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 5000,
|
||||
"metadata": {
|
||||
"source": "github",
|
||||
|
|
@ -95,7 +95,7 @@ After the user grants permissions, GitHub redirects to your callback URL. The co
|
|||
Unlike other connectors, GitHub requires repository selection before syncing begins. This gives your users control over which repositories to index.
|
||||
|
||||
<Note>
|
||||
**Generic Endpoints:** GitHub uses the generic resource management endpoints (Get Resources and Configure Connection) that work for any provider supporting resource management. See [Managing Connection Resources](/memory-api/connectors/managing-resources) for detailed API documentation.
|
||||
**Generic Endpoints:** GitHub uses the generic resource management endpoints (Get Resources and Configure Connection) that work for any provider supporting resource management. See [Managing Connection Resources](/connectors/managing-resources) for detailed API documentation.
|
||||
</Note>
|
||||
|
||||
<Tabs>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Connect Gmail to automatically sync email threads into your supermemory knowledg
|
|||
|
||||
const connection = await client.connections.create('gmail', {
|
||||
redirectUrl: 'https://yourapp.com/auth/gmail/callback',
|
||||
containerTags: ['user-123', 'gmail-sync'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 5000,
|
||||
metadata: {
|
||||
source: 'gmail',
|
||||
|
|
@ -48,7 +48,7 @@ Connect Gmail to automatically sync email threads into your supermemory knowledg
|
|||
connection = client.connections.create(
|
||||
'gmail',
|
||||
redirect_url='https://yourapp.com/auth/gmail/callback',
|
||||
container_tags=['user-123', 'gmail-sync'],
|
||||
container_tag='user-123',
|
||||
document_limit=5000,
|
||||
metadata={
|
||||
'source': 'gmail',
|
||||
|
|
@ -68,7 +68,7 @@ Connect Gmail to automatically sync email threads into your supermemory knowledg
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/auth/gmail/callback",
|
||||
"containerTags": ["user-123", "gmail-sync"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 5000,
|
||||
"metadata": {
|
||||
"source": "gmail",
|
||||
|
|
@ -90,7 +90,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
```typescript
|
||||
// Get connection details
|
||||
const connection = await client.connections.getByTags('gmail', {
|
||||
containerTags: ['user-123', 'gmail-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log('Connected email:', connection.email);
|
||||
|
|
@ -98,7 +98,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
|
||||
// List synced email threads
|
||||
const documents = await client.documents.list({
|
||||
containerTags: ['user-123', 'gmail-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log(`Synced ${documents.memories.length} email threads`);
|
||||
|
|
@ -109,7 +109,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
# Get connection details
|
||||
connection = client.connections.get_by_tags(
|
||||
'gmail',
|
||||
container_tags=['user-123', 'gmail-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
print(f'Connected email: {connection.email}')
|
||||
|
|
@ -117,7 +117,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
|
||||
# List synced email threads
|
||||
documents = client.documents.list(
|
||||
container_tags=['user-123', 'gmail-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
print(f'Synced {len(documents.memories)} email threads')
|
||||
|
|
@ -130,7 +130,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "gmail-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"provider": "gmail"
|
||||
}'
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ After user grants permissions, Google redirects to your callback URL. The connec
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "gmail-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"source": "gmail"
|
||||
}'
|
||||
```
|
||||
|
|
@ -177,9 +177,10 @@ Each synced thread includes searchable metadata:
|
|||
You can filter searches using these metadata fields:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "project update",
|
||||
containerTags: ['user-123'],
|
||||
containerTag: 'user-123',
|
||||
searchMode: "documents",
|
||||
filters: JSON.stringify({
|
||||
AND: [
|
||||
{ key: "type", value: "gmail_thread", negate: false },
|
||||
|
|
@ -408,7 +409,7 @@ await client.connections.deleteByProvider('gmail', {
|
|||
|
||||
const newConnection = await client.connections.create('gmail', {
|
||||
redirectUrl: 'https://yourapp.com/auth/gmail/callback',
|
||||
containerTags: ['user-123']
|
||||
containerTag: 'user-123'
|
||||
});
|
||||
|
||||
// User must re-authenticate
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "Google Drive Connector"
|
||||
description: "Connect Google Drive to sync documents into your Supermemory knowledge base"
|
||||
icon: "google-drive"
|
||||
icon: "/images/google-drive-icon.svg"
|
||||
---
|
||||
|
||||
Connect Google Drive to sync documents into your Supermemory knowledge base with OAuth authentication and custom app support.
|
||||
|
|
@ -33,7 +33,7 @@ If you use scoped sync and the user has not finished the picker yet, **scheduled
|
|||
|
||||
const connection = await client.connections.create('google-drive', {
|
||||
redirectUrl: 'https://yourapp.com/auth/google-drive/callback',
|
||||
containerTags: ['user-123', 'gdrive-sync'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 3000,
|
||||
metadata: {
|
||||
source: 'google-drive',
|
||||
|
|
@ -57,7 +57,7 @@ If you use scoped sync and the user has not finished the picker yet, **scheduled
|
|||
connection = client.connections.create(
|
||||
'google-drive',
|
||||
redirect_url='https://yourapp.com/auth/google-drive/callback',
|
||||
container_tags=['user-123', 'gdrive-sync'],
|
||||
container_tag='user-123',
|
||||
document_limit=3000,
|
||||
metadata={
|
||||
'source': 'google-drive',
|
||||
|
|
@ -78,7 +78,7 @@ If you use scoped sync and the user has not finished the picker yet, **scheduled
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/auth/google-drive/callback",
|
||||
"containerTags": ["user-123", "gdrive-sync"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 3000,
|
||||
"metadata": {
|
||||
"source": "google-drive",
|
||||
|
|
@ -105,7 +105,7 @@ After the user grants permissions, Google redirects through Supermemory to finis
|
|||
```typescript
|
||||
// Get connection details
|
||||
const connection = await client.connections.getByTags('google-drive', {
|
||||
containerTags: ['user-123', 'gdrive-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -114,13 +114,13 @@ After the user grants permissions, Google redirects through Supermemory to finis
|
|||
# Get connection details
|
||||
connection = client.connections.get_by_tags(
|
||||
'google-drive',
|
||||
container_tags=['user-123', 'gdrive-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
# List synced documents
|
||||
documents = client.connections.list_documents(
|
||||
'google-drive',
|
||||
container_tags=['user-123', 'gdrive-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -131,7 +131,7 @@ After the user grants permissions, Google redirects through Supermemory to finis
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "gdrive-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"provider": "google-drive"
|
||||
}'
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ After the user grants permissions, Google redirects through Supermemory to finis
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "gdrive-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"source": "google-drive"
|
||||
}'
|
||||
```
|
||||
|
|
@ -154,6 +154,10 @@ Based on the API type definitions, Google Drive documents are identified with th
|
|||
- `google_slide` - Google Slides
|
||||
- `google_sheet` - Google Sheets
|
||||
|
||||
<Note>
|
||||
Drive documents are converted to markdown before ingestion. This conversion is lossy — some formatting may not be preserved.
|
||||
</Note>
|
||||
|
||||
## Connection Management
|
||||
|
||||
### List All Connections
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ The console limits connector setup to 500 documents. Use the API setup below for
|
|||
metadata: {
|
||||
apiKey: process.env.GRANOLA_API_KEY!
|
||||
},
|
||||
containerTags: ['org-123', 'meeting-notes'],
|
||||
containerTag: 'org-123',
|
||||
documentLimit: 1000
|
||||
});
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ The console limits connector setup to 500 documents. Use the API setup below for
|
|||
metadata={
|
||||
'apiKey': os.environ["GRANOLA_API_KEY"]
|
||||
},
|
||||
container_tags=['org-123', 'meeting-notes'],
|
||||
container_tag='org-123',
|
||||
document_limit=1000
|
||||
)
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ The console limits connector setup to 500 documents. Use the API setup below for
|
|||
"metadata": {
|
||||
"apiKey": "'"$GRANOLA_API_KEY"'"
|
||||
},
|
||||
"containerTags": ["org-123", "meeting-notes"],
|
||||
"containerTag": "org-123",
|
||||
"documentLimit": 1000
|
||||
}'
|
||||
```
|
||||
|
|
@ -93,7 +93,7 @@ For Granola, provider-specific fields are passed inside the top-level `metadata`
|
|||
| Parameter | Location | Required | Description |
|
||||
|-----------|----------|----------|-------------|
|
||||
| `apiKey` | `metadata.apiKey` | Yes | Granola API key from **Settings > Connectors > API keys** |
|
||||
| `containerTags` | top-level | No | Tags for organizing imported notes by user, organization, project, or tenant |
|
||||
| `containerTag` | top-level | No | Tag for organizing imported notes by user, organization, project, or tenant |
|
||||
| `documentLimit` | top-level | No | Maximum notes to sync per connection (default: 10,000) |
|
||||
|
||||
<Note>
|
||||
|
|
@ -126,9 +126,10 @@ Each synced note includes searchable metadata:
|
|||
You can filter searches using these metadata fields:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
const results = await client.search({
|
||||
q: "customer onboarding discussion",
|
||||
containerTags: ['org-123'],
|
||||
containerTag: 'org-123',
|
||||
searchMode: "documents",
|
||||
filters: JSON.stringify({
|
||||
AND: [
|
||||
{ key: "type", value: "granola", negate: false },
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "Notion Connector"
|
||||
description: "Sync Notion pages, databases, and blocks with real-time webhooks and workspace integration"
|
||||
icon: "notion"
|
||||
icon: "/images/notion-icon.svg"
|
||||
---
|
||||
Connect Notion workspaces to automatically sync pages, databases, and content blocks into your Supermemory knowledge base. Supports real-time updates, rich formatting, and database properties.
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ Connect Notion workspaces to automatically sync pages, databases, and content bl
|
|||
|
||||
const connection = await client.connections.create('notion', {
|
||||
redirectUrl: 'https://yourapp.com/auth/notion/callback',
|
||||
containerTags: ['user-123', 'notion-workspace'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 2000,
|
||||
metadata: {
|
||||
source: 'notion',
|
||||
|
|
@ -43,7 +43,7 @@ Connect Notion workspaces to automatically sync pages, databases, and content bl
|
|||
connection = client.connections.create(
|
||||
'notion',
|
||||
redirect_url='https://yourapp.com/auth/notion/callback',
|
||||
container_tags=['user-123', 'notion-workspace'],
|
||||
container_tag='user-123',
|
||||
document_limit=2000,
|
||||
metadata={
|
||||
'source': 'notion',
|
||||
|
|
@ -63,7 +63,7 @@ Connect Notion workspaces to automatically sync pages, databases, and content bl
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/auth/notion/callback",
|
||||
"containerTags": ["user-123", "notion-workspace"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 2000,
|
||||
"metadata": {
|
||||
"source": "notion",
|
||||
|
|
@ -86,7 +86,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
```typescript
|
||||
// Check connection details
|
||||
const connection = await client.connections.getByTags('notion', {
|
||||
containerTags: ['user-123', 'notion-workspace']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log('Connected workspace:', connection.email);
|
||||
|
|
@ -94,7 +94,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
|
||||
// List synced pages and databases
|
||||
const documents = await client.connections.listDocuments('notion', {
|
||||
containerTags: ['user-123', 'notion-workspace']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -103,7 +103,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
# Check connection details
|
||||
connection = client.connections.get_by_tags(
|
||||
'notion',
|
||||
container_tags=['user-123', 'notion-workspace']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
print(f'Connected workspace: {connection.email}')
|
||||
|
|
@ -112,7 +112,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
# List synced pages and databases
|
||||
documents = client.connections.list_documents(
|
||||
'notion',
|
||||
container_tags=['user-123', 'notion-workspace']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -122,7 +122,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
curl -X POST "https://api.supermemory.ai/v3/connections/notion/connection" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user-123", "notion-workspace"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response includes connection details:
|
||||
# {
|
||||
|
|
@ -138,7 +138,7 @@ After user grants workspace access, Notion redirects to your callback URL. The c
|
|||
curl -X POST "https://api.supermemory.ai/v3/connections/notion/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user-123", "notion-workspace"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response: Array of document objects with sync status
|
||||
# [
|
||||
|
|
@ -261,7 +261,7 @@ For production deployments, create your own Notion integration:
|
|||
// Then create connections using your custom integration
|
||||
const connection = await client.connections.create('notion', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['org-456', 'user-789'],
|
||||
containerTag: 'user-789',
|
||||
metadata: { customIntegration: true }
|
||||
});
|
||||
```
|
||||
|
|
@ -279,7 +279,7 @@ For production deployments, create your own Notion integration:
|
|||
connection = client.connections.create(
|
||||
'notion',
|
||||
redirect_url='https://yourapp.com/callback',
|
||||
container_tags=['org-456', 'user-789'],
|
||||
container_tag='user-789',
|
||||
metadata={'customIntegration': True}
|
||||
)
|
||||
```
|
||||
|
|
@ -399,9 +399,10 @@ const projectEntries = documents.filter(doc =>
|
|||
);
|
||||
|
||||
// Database properties become searchable metadata
|
||||
const projectWithStatus = await client.search.documents({
|
||||
const projectWithStatus = await client.search({
|
||||
q: "machine learning project",
|
||||
containerTags: ['user-123'],
|
||||
containerTag: 'user-123',
|
||||
searchMode: "documents",
|
||||
filters: JSON.stringify({
|
||||
AND: [
|
||||
{ key: "status", value: "In Progress", negate: false },
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "OneDrive Connector"
|
||||
description: "Sync Microsoft Office documents from OneDrive with scheduled synchronization and business account support"
|
||||
icon: "microsoft"
|
||||
icon: "/images/microsoft-icon.svg"
|
||||
---
|
||||
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ const client = new Supermemory({
|
|||
|
||||
const connection = await client.connections.create('onedrive', {
|
||||
redirectUrl: 'https://yourapp.com/auth/onedrive/callback',
|
||||
containerTags: ['user-123', 'onedrive-sync'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 1500,
|
||||
metadata: {
|
||||
source: 'onedrive',
|
||||
|
|
@ -46,7 +46,7 @@ client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
|||
connection = client.connections.create(
|
||||
'onedrive',
|
||||
redirect_url='https://yourapp.com/auth/onedrive/callback',
|
||||
container_tags=['user-123', 'onedrive-sync'],
|
||||
container_tag='user-123',
|
||||
document_limit=1500,
|
||||
metadata={
|
||||
'source': 'onedrive',
|
||||
|
|
@ -67,7 +67,7 @@ curl -X POST "https://api.supermemory.ai/v3/connections/onedrive" \
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/auth/onedrive/callback",
|
||||
"containerTags": ["user-123", "onedrive-sync"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 1500,
|
||||
"metadata": {
|
||||
"source": "onedrive",
|
||||
|
|
@ -95,26 +95,26 @@ After user grants permissions, Microsoft redirects to your callback URL. The con
|
|||
```typescript Typescript
|
||||
// Check connection details
|
||||
const connection = await client.connections.getByTags('onedrive', {
|
||||
containerTags: ['user-123', 'onedrive-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
|
||||
// List synced Office documents
|
||||
const documents = await client.connections.listDocuments('onedrive', {
|
||||
containerTags: ['user-123', 'onedrive-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
```
|
||||
```python Python
|
||||
# Check connection details
|
||||
connection = client.connections.get_by_tags(
|
||||
'onedrive',
|
||||
container_tags=['user-123', 'onedrive-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
# List synced Office documents
|
||||
documents = client.connections.list_documents(
|
||||
'onedrive',
|
||||
container_tags=['user-123', 'onedrive-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
```
|
||||
```bash cURL
|
||||
|
|
@ -123,7 +123,7 @@ After user grants permissions, Microsoft redirects to your callback URL. The con
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "onedrive-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"provider": "onedrive"
|
||||
}'
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ After user grants permissions, Microsoft redirects to your callback URL. The con
|
|||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "onedrive-sync"],
|
||||
"containerTags": ["user-123"],
|
||||
"source": "onedrive"
|
||||
}'
|
||||
```
|
||||
|
|
@ -268,7 +268,7 @@ For production deployments, configure your own Microsoft application:
|
|||
// Then create connections using your custom app
|
||||
const connection = await client.connections.create('onedrive', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['org-456', 'user-789'],
|
||||
containerTag: 'user-789',
|
||||
metadata: { customApp: true }
|
||||
});
|
||||
```
|
||||
|
|
@ -284,7 +284,7 @@ For production deployments, configure your own Microsoft application:
|
|||
connection = client.connections.create(
|
||||
'onedrive',
|
||||
redirect_url='https://yourapp.com/callback',
|
||||
container_tags=['org-456', 'user-789'],
|
||||
container_tag='user-789',
|
||||
metadata={'customApp': True}
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Connect external platforms to automatically sync documents into supermemory. Sup
|
|||
## Supported Connectors
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Google Drive" icon="google-drive" href="/connectors/google-drive">
|
||||
<Card title="Google Drive" icon="/images/google-drive-icon.svg" href="/connectors/google-drive">
|
||||
**Google Docs, Slides, Sheets**
|
||||
|
||||
Real-time sync via webhooks. Supports shared drives, nested folders, and collaborative documents.
|
||||
|
|
@ -22,20 +22,20 @@ Connect external platforms to automatically sync documents into supermemory. Sup
|
|||
Real-time sync via Pub/Sub webhooks. Syncs threads with full conversation history and metadata.
|
||||
</Card>
|
||||
|
||||
<Card title="Notion" icon="notion" href="/connectors/notion">
|
||||
<Card title="Notion" icon="/images/notion-icon.svg" href="/connectors/notion">
|
||||
**Pages, Databases, Blocks**
|
||||
|
||||
Instant sync of workspace content. Handles rich formatting, embeds, and database properties.
|
||||
</Card>
|
||||
|
||||
<Card title="OneDrive" icon="microsoft" href="/connectors/onedrive">
|
||||
<Card title="OneDrive" icon="/images/microsoft-icon.svg" href="/connectors/onedrive">
|
||||
**Word, Excel, PowerPoint**
|
||||
|
||||
Scheduled sync every 4 hours. Supports personal and business accounts with file versioning.
|
||||
</Card>
|
||||
|
||||
|
||||
<Card title="GitHub" icon="github" href="/connectors/github">
|
||||
<Card title="GitHub" icon="/images/github-icon.svg" href="/connectors/github">
|
||||
**GitHub Repositories**
|
||||
|
||||
Real-time incremental sync via webhooks. Supports documentation files in repositories.
|
||||
|
|
@ -69,7 +69,7 @@ const client = new Supermemory({
|
|||
|
||||
const connection = await client.connections.create('notion', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['user-123', 'workspace-alpha'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 5000,
|
||||
metadata: { department: 'sales' }
|
||||
});
|
||||
|
|
@ -90,7 +90,7 @@ client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
|||
connection = client.connections.create(
|
||||
'notion',
|
||||
redirect_url='https://yourapp.com/callback',
|
||||
container_tags=['user-123', 'workspace-alpha'],
|
||||
container_tag='user-123',
|
||||
document_limit=5000,
|
||||
metadata={'department': 'sales'}
|
||||
)
|
||||
|
|
@ -108,7 +108,7 @@ curl -X POST "https://api.supermemory.ai/v3/connections/notion" \
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/callback",
|
||||
"containerTags": ["user-123", "workspace-alpha"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 5000,
|
||||
"metadata": {"department": "sales"}
|
||||
}'
|
||||
|
|
@ -140,7 +140,7 @@ const client = new Supermemory({
|
|||
|
||||
// List all connections using SDK
|
||||
const connections = await client.connections.list({
|
||||
containerTags: ['user-123', 'workspace-alpha']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
connections.forEach(conn => {
|
||||
|
|
@ -152,7 +152,7 @@ connections.forEach(conn => {
|
|||
|
||||
// List synced documents (memories) using SDK
|
||||
const memories = await client.documents.list({
|
||||
containerTags: ['user-123', 'workspace-alpha']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log(`Synced ${memories.memories.length} documents`);
|
||||
|
|
@ -167,7 +167,7 @@ client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
|||
|
||||
# List all connections using SDK
|
||||
connections = client.connections.list(
|
||||
container_tags=['user-123', 'workspace-alpha']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
for conn in connections:
|
||||
|
|
@ -177,7 +177,7 @@ for conn in connections:
|
|||
print(f'Created: {conn.created_at}')
|
||||
|
||||
# List synced documents (memories) using SDK
|
||||
memories = client.documents.list(container_tags=['user-123', 'workspace-alpha'])
|
||||
memories = client.documents.list(container_tags=['user-123'])
|
||||
|
||||
print(f'Synced {len(memories.memories)} documents')
|
||||
# Output: Synced 45 documents
|
||||
|
|
@ -188,7 +188,7 @@ print(f'Synced {len(memories.memories)} documents')
|
|||
curl -X POST "https://api.supermemory.ai/v3/connections/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user-123", "workspace-alpha"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response: [{"id": "conn_abc", "provider": "notion", "email": "user@example.com", ...}]
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ curl -X POST "https://api.supermemory.ai/v3/connections/list" \
|
|||
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", "workspace-alpha"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response: {"results": [...], "totalCount": 45}
|
||||
```
|
||||
|
|
@ -368,3 +368,18 @@ curl -X DELETE "https://api.supermemory.ai/v3/connections/conn_abc123?deleteDocu
|
|||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Custom OAuth Applications
|
||||
|
||||
By default, Supermemory uses its own OAuth applications to connect to third-party providers. You can configure your own OAuth app credentials via `PATCH /v3/settings` for tighter control over data access — useful for enterprise customers.
|
||||
|
||||
1. Create the OAuth application on the provider's developer console:
|
||||
- Google: [console.developers.google.com/apis/credentials/oauthclient](https://console.developers.google.com/apis/credentials/oauthclient)
|
||||
- Notion: [notion.so/my-integrations](https://www.notion.so/my-integrations)
|
||||
- OneDrive: [Azure Portal → App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsMenu)
|
||||
2. For Google Drive specifically: choose application type **Web application**, and enable the Google Drive API under "APIs and Services" in the Cloud Console. Google also requires verification/approval before custom keys work in production.
|
||||
3. Set the redirect URL to `https://api.supermemory.ai/v3/connections/auth/callback/{provider}` (for example, `.../auth/callback/google-drive`).
|
||||
|
||||
<Warning>
|
||||
Enabling custom keys for a provider applies to all new connections for that provider — existing connections will need to be re-authorized.
|
||||
</Warning>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "S3 Connector"
|
||||
description: "Connect Amazon S3 or S3-compatible storage to sync files into your Supermemory knowledge base"
|
||||
icon: "aws"
|
||||
icon: "database"
|
||||
---
|
||||
|
||||
Connect Amazon S3 buckets or S3-compatible storage services (MinIO, DigitalOcean Spaces, Cloudflare R2, Tigris) to sync files into your Supermemory knowledge base.
|
||||
|
|
@ -28,7 +28,7 @@ The S3 connector requires a **Scale Plan** or higher. You can also create S3 con
|
|||
bucket: 'my-documents-bucket',
|
||||
region: 'us-east-1'
|
||||
},
|
||||
containerTags: ['org-123']
|
||||
containerTag: 'org-123'
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -47,7 +47,7 @@ The S3 connector requires a **Scale Plan** or higher. You can also create S3 con
|
|||
'bucket': 'my-documents-bucket',
|
||||
'region': 'us-east-1'
|
||||
},
|
||||
container_tags=['org-123', 's3-sync']
|
||||
container_tag='org-123'
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -63,7 +63,7 @@ The S3 connector requires a **Scale Plan** or higher. You can also create S3 con
|
|||
"bucket": "my-documents-bucket",
|
||||
"region": "us-east-1"
|
||||
},
|
||||
"containerTags": ["org-123"]
|
||||
"containerTag": "org-123"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -82,7 +82,7 @@ For S3, provider-specific connection fields are passed inside the top-level `met
|
|||
| `endpoint` | `metadata.endpoint` | No | Custom endpoint for S3-compatible services |
|
||||
| `prefix` | `metadata.prefix` | No | Key prefix filter (e.g., `documents/`) |
|
||||
| `containerTagRegex` | `metadata.containerTagRegex` | No | Regex to extract container tags from file paths |
|
||||
| `containerTags` | top-level | No | Tags for organizing connections |
|
||||
| `containerTag` | top-level | No | Tag for organizing this connection |
|
||||
| `documentLimit` | top-level | No | Maximum documents to sync (default: 10,000) |
|
||||
|
||||
<Note>
|
||||
|
|
@ -103,7 +103,7 @@ const connection = await client.connections.create('s3', {
|
|||
region: 'auto',
|
||||
endpoint: 'https://minio.example.com'
|
||||
},
|
||||
containerTags: ['minio-sync']
|
||||
containerTag: 'minio-sync'
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ const connection = await client.connections.create('s3', {
|
|||
region: 'auto',
|
||||
endpoint: 'https://<account-id>.r2.cloudflarestorage.com'
|
||||
},
|
||||
containerTags: ['r2-sync']
|
||||
containerTag: 'r2-sync'
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ const connection = await client.connections.create('s3', {
|
|||
region: 'us-east-1',
|
||||
prefix: 'documents/engineering/' // Only syncs files under this path
|
||||
},
|
||||
containerTags: ['engineering-docs']
|
||||
containerTag: 'engineering-docs'
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ const connection = await client.connections.create('s3', {
|
|||
region: 'us-east-1',
|
||||
containerTagRegex: 'users/(?<userId>[^/]+)/'
|
||||
},
|
||||
containerTags: ['user-files']
|
||||
containerTag: 'user-files'
|
||||
});
|
||||
|
||||
// File: users/user-123/documents/notes.md → container tag: user-123
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
|||
// correct - exact match with OAuth app settings
|
||||
const connection = await client.connections.create('notion', {
|
||||
redirectUrl: 'https://yourapp.com/auth/notion/callback',
|
||||
containerTags: ['user-123']
|
||||
containerTag: 'user-123'
|
||||
});
|
||||
|
||||
// Wrong - URL doesn't match
|
||||
|
|
@ -122,7 +122,7 @@ await client.connections.deleteByProvider('google-drive', {
|
|||
|
||||
const newConnection = await client.connections.create('google-drive', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['user-123']
|
||||
containerTag: 'user-123'
|
||||
});
|
||||
|
||||
// User must re-authenticate
|
||||
|
|
@ -138,7 +138,7 @@ window.location.href = newConnection.authLink;
|
|||
```typescript
|
||||
const connection = await client.connections.create('onedrive', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['user-123'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 500 // Start with fewer documents
|
||||
});
|
||||
```
|
||||
|
|
@ -215,7 +215,7 @@ await client.connections.deleteByProvider('gmail', {
|
|||
|
||||
const newConnection = await client.connections.create('gmail', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['user-123']
|
||||
containerTag: 'user-123'
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ The web crawler connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
|
||||
const connection = await client.connections.create('web-crawler', {
|
||||
redirectUrl: 'https://yourapp.com/callback',
|
||||
containerTags: ['user-123', 'website-sync'],
|
||||
containerTag: 'user-123',
|
||||
documentLimit: 5000,
|
||||
metadata: {
|
||||
startUrl: 'https://docs.example.com'
|
||||
|
|
@ -48,7 +48,7 @@ The web crawler connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
connection = client.connections.create(
|
||||
'web-crawler',
|
||||
redirect_url='https://yourapp.com/callback',
|
||||
container_tags=['user-123', 'website-sync'],
|
||||
container_tag='user-123',
|
||||
document_limit=5000,
|
||||
metadata={
|
||||
'startUrl': 'https://docs.example.com'
|
||||
|
|
@ -68,7 +68,7 @@ The web crawler connector requires a **Scale Plan** or **Enterprise Plan**.
|
|||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"redirectUrl": "https://yourapp.com/callback",
|
||||
"containerTags": ["user-123", "website-sync"],
|
||||
"containerTag": "user-123",
|
||||
"documentLimit": 5000,
|
||||
"metadata": {
|
||||
"startUrl": "https://docs.example.com"
|
||||
|
|
@ -96,7 +96,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
```typescript
|
||||
// Check connection details
|
||||
const connection = await client.connections.getByTags('web-crawler', {
|
||||
containerTags: ['user-123', 'website-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log('Start URL:', connection.metadata?.startUrl);
|
||||
|
|
@ -104,7 +104,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
|
||||
// List synced web pages
|
||||
const documents = await client.connections.listDocuments('web-crawler', {
|
||||
containerTags: ['user-123', 'website-sync']
|
||||
containerTags: ['user-123']
|
||||
});
|
||||
|
||||
console.log(`Synced ${documents.length} web pages`);
|
||||
|
|
@ -115,7 +115,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
# Check connection details
|
||||
connection = client.connections.get_by_tags(
|
||||
'web-crawler',
|
||||
container_tags=['user-123', 'website-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
print(f'Start URL: {connection.metadata.get("startUrl")}')
|
||||
|
|
@ -124,7 +124,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
# List synced web pages
|
||||
documents = client.connections.list_documents(
|
||||
'web-crawler',
|
||||
container_tags=['user-123', 'website-sync']
|
||||
container_tags=['user-123']
|
||||
)
|
||||
|
||||
print(f'Synced {len(documents)} web pages')
|
||||
|
|
@ -136,7 +136,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
curl -X POST "https://api.supermemory.ai/v3/connections/web-crawler/connection" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user-123", "website-sync"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response includes connection details:
|
||||
# {
|
||||
|
|
@ -151,7 +151,7 @@ Unlike other connectors, the web crawler doesn't require OAuth authentication. T
|
|||
curl -X POST "https://api.supermemory.ai/v3/connections/web-crawler/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user-123", "website-sync"]}'
|
||||
-d '{"containerTags": ["user-123"]}'
|
||||
|
||||
# Response: Array of document objects
|
||||
# [
|
||||
|
|
|
|||
|
|
@ -1,354 +0,0 @@
|
|||
---
|
||||
title: "AI SDK Integration"
|
||||
description: "Complete examples showing how to use Supermemory with Vercel AI SDK for building intelligent applications"
|
||||
---
|
||||
|
||||
This page provides comprehensive examples of using Supermemory with the Vercel AI SDK, covering Memory Tools and User Profiles approaches.
|
||||
|
||||
## Personal Assistant with Memory Tools
|
||||
|
||||
Build an AI assistant that remembers user preferences and past interactions:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Next.js API Route
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
|
||||
system: `You are a helpful personal assistant. When users share information about themselves,
|
||||
remember it using the addMemory tool. When they ask questions, search your memories to provide
|
||||
personalized responses. Always be proactive about remembering important details.`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Client Component
|
||||
'use client'
|
||||
|
||||
import { useChat } from 'ai/react'
|
||||
|
||||
export default function PersonalAssistant() {
|
||||
const { messages, input, handleInputChange, handleSubmit } = useChat()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen max-w-2xl mx-auto p-4">
|
||||
<div className="flex-1 overflow-y-auto space-y-4">
|
||||
{messages.map((message) => (
|
||||
<div
|
||||
key={message.id}
|
||||
className={`p-4 rounded-lg ${
|
||||
message.role === 'user' ? 'bg-blue-100 ml-auto' : 'bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<p>{message.content}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="mt-4">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Tell me about yourself or ask me anything..."
|
||||
className="w-full p-2 border rounded"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
**Example conversation:**
|
||||
- User: "I'm allergic to peanuts and I love Italian food"
|
||||
- AI: *Uses addMemory tool* "I've remembered that you're allergic to peanuts and love Italian food!"
|
||||
- User: "Suggest a restaurant for dinner"
|
||||
- AI: *Uses searchMemories tool* "Based on what I know about you, I'd recommend an Italian restaurant that's peanut-free..."
|
||||
|
||||
## Customer Support with Context
|
||||
|
||||
Build a customer support system that remembers customer history:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, customerId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [customerId]
|
||||
}),
|
||||
system: `You are a customer support agent. Before responding to any query:
|
||||
1. Search for the customer's previous interactions and issues
|
||||
2. Remember any new information shared in this conversation
|
||||
3. Provide personalized help based on their history
|
||||
4. Always be empathetic and solution-focused`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Multi-User Learning Assistant
|
||||
|
||||
Build an assistant that learns from multiple users but keeps data separate:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, userId, courseId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-haiku-20240307'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [userId]
|
||||
}),
|
||||
system: `You are a learning assistant. Help students with their coursework by:
|
||||
1. Remembering their learning progress and struggles
|
||||
2. Searching for relevant information from their past sessions
|
||||
3. Providing personalized explanations based on their learning style
|
||||
4. Tracking topics they've mastered vs topics they need more help with`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Research Assistant with File Processing
|
||||
|
||||
Combine file upload with memory tools for research assistance:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript API Route
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, projectId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [projectId]
|
||||
}),
|
||||
system: `You are a research assistant. You can:
|
||||
1. Search through uploaded research papers and documents
|
||||
2. Remember key findings and insights from conversations
|
||||
3. Help synthesize information across multiple sources
|
||||
4. Track research progress and important discoveries`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
```typescript File Upload Handler
|
||||
import { addMemory } from '@supermemory/tools'
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const formData = await request.formData()
|
||||
const file = formData.get('file') as File
|
||||
const projectId = formData.get('projectId') as string
|
||||
|
||||
// Upload file and add to memory
|
||||
const memory = await addMemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!,
|
||||
content: file, // Supermemory handles file processing
|
||||
title: file.name,
|
||||
headers: {
|
||||
'x-sm-conversation-id': projectId
|
||||
}
|
||||
})
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "Document uploaded and processed for research",
|
||||
memoryId: memory.id
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Code Assistant with Project Memory
|
||||
|
||||
Create a coding assistant that remembers your codebase and preferences:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import {
|
||||
supermemoryTools,
|
||||
searchMemoriesTool,
|
||||
addMemoryTool
|
||||
} from '@supermemory/tools/ai-sdk'
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages, repositoryId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
messages,
|
||||
tools: {
|
||||
// Use individual tools for more control
|
||||
searchMemories: searchMemoriesTool(process.env.SUPERMEMORY_API_KEY!, {
|
||||
headers: {
|
||||
}
|
||||
}),
|
||||
addMemory: addMemoryTool(process.env.SUPERMEMORY_API_KEY!, {
|
||||
headers: {
|
||||
}
|
||||
}),
|
||||
// Add custom tools
|
||||
executeCode: {
|
||||
description: 'Execute code in a sandbox environment',
|
||||
parameters: z.object({
|
||||
code: z.string(),
|
||||
language: z.string()
|
||||
}),
|
||||
execute: async ({ code, language }) => {
|
||||
// Your code execution logic
|
||||
return { result: "Code executed successfully" }
|
||||
}
|
||||
}
|
||||
},
|
||||
system: `You are a coding assistant with memory. You can:
|
||||
1. Remember coding patterns and preferences from past conversations
|
||||
2. Search through previous code examples and solutions
|
||||
3. Track project architecture and design decisions
|
||||
4. Learn from debugging sessions and common issues`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced: Custom Tool Integration
|
||||
|
||||
Combine Supermemory tools with your own custom tools:
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
import { z } from 'zod'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
// Custom tool for calendar integration
|
||||
const calendarTool = {
|
||||
description: 'Create calendar events',
|
||||
parameters: z.object({
|
||||
title: z.string(),
|
||||
date: z.string(),
|
||||
duration: z.number()
|
||||
}),
|
||||
execute: async ({ title, date, duration }) => {
|
||||
// Your calendar API integration
|
||||
return { eventId: "cal_123", message: "Event created" }
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { messages } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: {
|
||||
// Spread Supermemory tools
|
||||
...supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
|
||||
// Add custom tools
|
||||
createEvent: calendarTool,
|
||||
},
|
||||
system: `You are a personal assistant that can remember information and
|
||||
manage calendars. When users mention events or appointments:
|
||||
1. Remember the details using addMemory
|
||||
2. Create calendar events using createEvent
|
||||
3. Search for conflicts using searchMemories`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
For all examples, ensure you have these environment variables:
|
||||
|
||||
```bash .env.local
|
||||
SUPERMEMORY_API_KEY=your_supermemory_key
|
||||
OPENAI_API_KEY=your_openai_key
|
||||
ANTHROPIC_API_KEY=your_anthropic_key
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Memory Tools
|
||||
- Use descriptive memory content for better search results
|
||||
- Include context in your system prompts about when to use each tool
|
||||
- Use project headers to separate different use cases
|
||||
- Implement error handling for tool failures
|
||||
|
||||
### General Tips
|
||||
- Start with simple examples and gradually add complexity
|
||||
- Use the search functionality to avoid duplicate memories
|
||||
- Implement proper authentication for production use
|
||||
- Consider rate limiting for high-volume applications
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory API" icon="database" href="/memory-api/overview">
|
||||
Advanced memory management with full API control
|
||||
</Card>
|
||||
|
||||
<Card title="User Profiles" icon="user" href="/user-profiles">
|
||||
Automatic personalization with user profiles
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "Chat with Google Drive"
|
||||
url: "https://supermemory.ai/blog/building-an-ai-compliance-chatbot-with-supermemory-and-google-drive/"
|
||||
---
|
||||
|
|
@ -1,877 +0,0 @@
|
|||
---
|
||||
title: "Document Q&A System"
|
||||
description: "Build a chatbot that answers questions from your documents with citations and source references"
|
||||
---
|
||||
|
||||
Create a powerful document Q&A system that can ingest PDFs, text files, and web pages, then answer questions with accurate citations. Perfect for documentation sites, research databases, or internal knowledge bases.
|
||||
|
||||
## What You'll Build
|
||||
|
||||
A document Q&A system that:
|
||||
- **Ingests multiple file types** (PDFs, DOCX, text, URLs)
|
||||
- **Answers questions accurately** with source citations
|
||||
- **Provides source references** with page numbers and document titles
|
||||
- **Handles follow-up questions** with conversation context
|
||||
- **Supports multiple document collections** for different topics
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 18+ or Python 3.8+
|
||||
- Supermemory API key
|
||||
- OpenAI API key
|
||||
- Basic understanding of file handling
|
||||
|
||||
## Implementation
|
||||
|
||||
### Step 1: Document Processing System
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Next.js">
|
||||
```typescript lib/document-processor.ts
|
||||
import { Supermemory } from 'supermemory'
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
})
|
||||
|
||||
interface DocumentUpload {
|
||||
file: File
|
||||
collection: string
|
||||
metadata?: Record<string, any>
|
||||
}
|
||||
|
||||
export class DocumentProcessor {
|
||||
async uploadDocument({ file, collection, metadata = {} }: DocumentUpload) {
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('containerTags', JSON.stringify([collection]))
|
||||
formData.append('metadata', JSON.stringify({
|
||||
originalName: file.name,
|
||||
fileType: file.type,
|
||||
uploadedAt: new Date().toISOString(),
|
||||
...metadata
|
||||
}))
|
||||
|
||||
const response = await fetch('/api/upload-document', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Upload failed: ${response.statusText}`)
|
||||
}
|
||||
|
||||
return await response.json()
|
||||
} catch (error) {
|
||||
console.error('Document upload error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async uploadURL({ url, collection, metadata = {} }: { url: string, collection: string, metadata?: Record<string, any> }) {
|
||||
try {
|
||||
const result = await client.add({
|
||||
content: url,
|
||||
containerTag: collection,
|
||||
metadata: {
|
||||
type: 'url',
|
||||
originalUrl: url,
|
||||
uploadedAt: new Date().toISOString(),
|
||||
...metadata
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('URL upload error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async getDocumentStatus(documentId: string) {
|
||||
try {
|
||||
const memory = await client.documents.get(documentId)
|
||||
return {
|
||||
id: memory.id,
|
||||
status: memory.status,
|
||||
title: memory.title,
|
||||
progress: memory.metadata?.progress || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Status check error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async listDocuments(collection: string) {
|
||||
try {
|
||||
const memories = await client.documents.list({
|
||||
containerTags: [collection],
|
||||
limit: 50,
|
||||
sort: 'updatedAt',
|
||||
order: 'desc'
|
||||
})
|
||||
|
||||
return memories.memories.map(memory => ({
|
||||
id: memory.id,
|
||||
title: memory.title || memory.metadata?.originalName || 'Untitled',
|
||||
type: memory.metadata?.fileType || memory.metadata?.type || 'unknown',
|
||||
uploadedAt: memory.metadata?.uploadedAt,
|
||||
status: memory.status,
|
||||
url: memory.metadata?.originalUrl
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('List documents error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```typescript app/api/upload-document/route.ts
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { Supermemory } from 'supermemory'
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const formData = await request.formData()
|
||||
const file = formData.get('file') as File
|
||||
const containerTags = JSON.parse(formData.get('containerTags') as string)
|
||||
const metadata = JSON.parse(formData.get('metadata') as string || '{}')
|
||||
|
||||
if (!file) {
|
||||
return NextResponse.json({ error: 'No file provided' }, { status: 400 })
|
||||
}
|
||||
|
||||
const result = await client.documents.uploadFile({
|
||||
file: file,
|
||||
containerTags: JSON.stringify(containerTags),
|
||||
metadata: JSON.stringify(metadata)
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
documentId: result.id,
|
||||
message: 'Document uploaded successfully'
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Upload failed', details: error.message },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
```python document_processor.py
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
import json
|
||||
from typing import Dict, List, Any, Optional
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
class DocumentProcessor:
|
||||
def __init__(self):
|
||||
self.client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
|
||||
|
||||
def upload_file(self, file_path: str, collection: str, metadata: Dict[str, Any] = None) -> Dict:
|
||||
"""Upload a local file to Supermemory"""
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
|
||||
try:
|
||||
with open(file_path, 'rb') as file:
|
||||
result = self.client.documents.upload_file(
|
||||
file=file,
|
||||
container_tags=collection,
|
||||
metadata=json.dumps({
|
||||
'originalName': os.path.basename(file_path),
|
||||
'fileType': os.path.splitext(file_path)[1],
|
||||
'uploadedAt': datetime.now().isoformat(),
|
||||
**metadata
|
||||
})
|
||||
)
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"File upload error: {e}")
|
||||
raise
|
||||
|
||||
def upload_url(self, url: str, collection: str, metadata: Dict[str, Any] = None) -> Dict:
|
||||
"""Upload URL content to Supermemory"""
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
|
||||
try:
|
||||
result = self.client.add(
|
||||
content=url,
|
||||
container_tag=collection,
|
||||
metadata={
|
||||
'type': 'url',
|
||||
'originalUrl': url,
|
||||
'uploadedAt': datetime.now().isoformat(),
|
||||
**metadata
|
||||
}
|
||||
)
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"URL upload error: {e}")
|
||||
raise
|
||||
|
||||
def get_document_status(self, document_id: str) -> Dict:
|
||||
"""Check document processing status"""
|
||||
try:
|
||||
memory = self.client.documents.get(document_id)
|
||||
return {
|
||||
'id': memory.id,
|
||||
'status': memory.status,
|
||||
'title': memory.title,
|
||||
'progress': memory.metadata.get('progress', 0) if memory.metadata else 0
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Status check error: {e}")
|
||||
raise
|
||||
|
||||
def list_documents(self, collection: str) -> List[Dict]:
|
||||
"""List all documents in a collection"""
|
||||
try:
|
||||
memories = self.client.documents.list(
|
||||
container_tags=[collection],
|
||||
limit=50,
|
||||
sort='updatedAt',
|
||||
order='desc'
|
||||
)
|
||||
|
||||
return [
|
||||
{
|
||||
'id': memory.id,
|
||||
'title': (memory.title or
|
||||
memory.metadata.get('originalName') or
|
||||
'Untitled' if memory.metadata else 'Untitled'),
|
||||
'type': (memory.metadata.get('fileType') or
|
||||
memory.metadata.get('type') or
|
||||
'unknown' if memory.metadata else 'unknown'),
|
||||
'uploadedAt': memory.metadata.get('uploadedAt') if memory.metadata else None,
|
||||
'status': memory.status,
|
||||
'url': memory.metadata.get('originalUrl') if memory.metadata else None
|
||||
}
|
||||
for memory in memories.memories
|
||||
]
|
||||
except Exception as e:
|
||||
print(f"List documents error: {e}")
|
||||
raise
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Step 2: Q&A API with Citations
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Next.js API Route">
|
||||
```typescript app/api/qa/route.ts
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { Supermemory } from 'supermemory'
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { question, collection, conversationHistory = [] } = await request.json()
|
||||
|
||||
try {
|
||||
// Search for relevant documents
|
||||
const searchResults = await client.search.documents({
|
||||
q: question,
|
||||
containerTags: [collection],
|
||||
limit: 8,
|
||||
rerank: true,
|
||||
includeFullDocs: false,
|
||||
includeSummary: true,
|
||||
onlyMatchingChunks: false,
|
||||
chunkThreshold: 0.7
|
||||
})
|
||||
|
||||
if (searchResults.results.length === 0) {
|
||||
return Response.json({
|
||||
answer: "I couldn't find any relevant information in the uploaded documents to answer your question.",
|
||||
sources: [],
|
||||
confidence: 0
|
||||
})
|
||||
}
|
||||
|
||||
// Prepare context from search results
|
||||
const context = searchResults.results.map((result, index) => {
|
||||
const chunks = result.chunks
|
||||
.filter(chunk => chunk.isRelevant)
|
||||
.slice(0, 3)
|
||||
.map(chunk => chunk.content)
|
||||
.join('\n\n')
|
||||
|
||||
return `[Document ${index + 1}: "${result.title}"]\n${chunks}`
|
||||
}).join('\n\n---\n\n')
|
||||
|
||||
// Prepare sources for citation
|
||||
const sources = searchResults.results.map((result, index) => ({
|
||||
id: result.documentId,
|
||||
title: result.title,
|
||||
type: result.type,
|
||||
relevantChunks: result.chunks.filter(chunk => chunk.isRelevant).length,
|
||||
score: result.score,
|
||||
citationNumber: index + 1
|
||||
}))
|
||||
|
||||
const messages = [
|
||||
...conversationHistory,
|
||||
{
|
||||
role: 'user' as const,
|
||||
content: question
|
||||
}
|
||||
]
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
system: `You are a helpful document Q&A assistant. Answer questions based ONLY on the provided document context.
|
||||
|
||||
CONTEXT FROM DOCUMENTS:
|
||||
${context}
|
||||
|
||||
INSTRUCTIONS:
|
||||
1. Answer the question using ONLY the information from the provided documents
|
||||
2. Include specific citations in your response using [Document X] format
|
||||
3. If the documents don't contain enough information, say so clearly
|
||||
4. Be accurate and quote directly when possible
|
||||
5. If multiple documents support a point, cite all relevant ones
|
||||
6. Maintain a helpful, professional tone
|
||||
|
||||
CITATION FORMAT:
|
||||
- Use [Document 1], [Document 2], etc. to cite sources
|
||||
- Place citations after the relevant information
|
||||
- Example: "The process involves three steps [Document 1]. However, some experts recommend a four-step approach [Document 3]."
|
||||
|
||||
If the question cannot be answered from the provided documents, respond with: "I don't have enough information in the provided documents to answer this question accurately."`,
|
||||
temperature: 0.1,
|
||||
maxTokens: 1000
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse({
|
||||
data: {
|
||||
sources,
|
||||
searchResultsCount: searchResults.results.length,
|
||||
totalResults: searchResults.total
|
||||
}
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('Q&A error:', error)
|
||||
return Response.json(
|
||||
{ error: 'Failed to process question', details: error.message },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python FastAPI">
|
||||
```python qa_api.py
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Dict, Any, Optional
|
||||
import openai
|
||||
from supermemory import Supermemory
|
||||
import json
|
||||
import os
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
openai_client = openai.AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
supermemory_client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
|
||||
|
||||
class QARequest(BaseModel):
|
||||
question: str
|
||||
collection: str
|
||||
conversationHistory: List[Dict[str, str]] = []
|
||||
|
||||
class QAResponse(BaseModel):
|
||||
answer: str
|
||||
sources: List[Dict[str, Any]]
|
||||
confidence: float
|
||||
searchResultsCount: int
|
||||
|
||||
@app.post("/qa")
|
||||
async def answer_question(request: QARequest):
|
||||
try:
|
||||
# Search for relevant documents
|
||||
search_results = supermemory_client.search.documents(
|
||||
q=request.question,
|
||||
container_tags=[request.collection],
|
||||
limit=8,
|
||||
rerank=True,
|
||||
include_full_docs=False,
|
||||
include_summary=True,
|
||||
only_matching_chunks=False,
|
||||
chunk_threshold=0.7
|
||||
)
|
||||
|
||||
if not search_results.results:
|
||||
return QAResponse(
|
||||
answer="I couldn't find any relevant information in the uploaded documents to answer your question.",
|
||||
sources=[],
|
||||
confidence=0,
|
||||
searchResultsCount=0
|
||||
)
|
||||
|
||||
# Prepare context from search results
|
||||
context_parts = []
|
||||
sources = []
|
||||
|
||||
for index, result in enumerate(search_results.results):
|
||||
relevant_chunks = [
|
||||
chunk.content for chunk in result.chunks
|
||||
if chunk.is_relevant
|
||||
][:3]
|
||||
|
||||
chunk_text = '\n\n'.join(relevant_chunks)
|
||||
context_parts.append(f'[Document {index + 1}: "{result.title}"]\n{chunk_text}')
|
||||
|
||||
sources.append({
|
||||
'id': result.document_id,
|
||||
'title': result.title,
|
||||
'type': result.type,
|
||||
'relevantChunks': len([c for c in result.chunks if c.is_relevant]),
|
||||
'score': result.score,
|
||||
'citationNumber': index + 1
|
||||
})
|
||||
|
||||
context = '\n\n---\n\n'.join(context_parts)
|
||||
|
||||
# Prepare messages
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": f"""You are a helpful document Q&A assistant. Answer questions based ONLY on the provided document context.
|
||||
|
||||
CONTEXT FROM DOCUMENTS:
|
||||
{context}
|
||||
|
||||
INSTRUCTIONS:
|
||||
1. Answer the question using ONLY the information from the provided documents
|
||||
2. Include specific citations in your response using [Document X] format
|
||||
3. If the documents don't contain enough information, say so clearly
|
||||
4. Be accurate and quote directly when possible
|
||||
5. If multiple documents support a point, cite all relevant ones
|
||||
6. Maintain a helpful, professional tone
|
||||
|
||||
CITATION FORMAT:
|
||||
- Use [Document 1], [Document 2], etc. to cite sources
|
||||
- Place citations after the relevant information
|
||||
- Example: "The process involves three steps [Document 1]. However, some experts recommend a four-step approach [Document 3]."
|
||||
|
||||
If the question cannot be answered from the provided documents, respond with: "I don't have enough information in the provided documents to answer this question accurately." """
|
||||
}
|
||||
]
|
||||
|
||||
# Add conversation history
|
||||
messages.extend(request.conversationHistory)
|
||||
messages.append({"role": "user", "content": request.question})
|
||||
|
||||
# Get AI response
|
||||
response = await openai_client.chat.completions.create(
|
||||
model="gpt-5",
|
||||
messages=messages,
|
||||
temperature=0.1,
|
||||
max_tokens=1000
|
||||
)
|
||||
|
||||
answer = response.choices[0].message.content
|
||||
|
||||
return QAResponse(
|
||||
answer=answer,
|
||||
sources=sources,
|
||||
confidence=min(search_results.results[0].score if search_results.results else 0, 1.0),
|
||||
searchResultsCount=len(search_results.results)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to process question: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Step 3: Frontend Interface
|
||||
|
||||
```tsx app/qa/page.tsx
|
||||
'use client'
|
||||
|
||||
import { useState, useRef } from 'react'
|
||||
import { useChat } from 'ai/react'
|
||||
import { DocumentProcessor } from '@/lib/document-processor'
|
||||
|
||||
interface Document {
|
||||
id: string
|
||||
title: string
|
||||
type: string
|
||||
status: string
|
||||
uploadedAt: string
|
||||
}
|
||||
|
||||
interface Source {
|
||||
id: string
|
||||
title: string
|
||||
citationNumber: number
|
||||
score: number
|
||||
relevantChunks: number
|
||||
}
|
||||
|
||||
export default function DocumentQA() {
|
||||
const [collection, setCollection] = useState('default-docs')
|
||||
const [documents, setDocuments] = useState<Document[]>([])
|
||||
const [sources, setSources] = useState<Source[]>([])
|
||||
const [isUploading, setIsUploading] = useState(false)
|
||||
const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({})
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
const processor = new DocumentProcessor()
|
||||
|
||||
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
|
||||
api: '/api/qa',
|
||||
body: {
|
||||
collection
|
||||
},
|
||||
onFinish: (message, { data }) => {
|
||||
if (data?.sources) {
|
||||
setSources(data.sources)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = event.target.files
|
||||
if (!files || files.length === 0) return
|
||||
|
||||
setIsUploading(true)
|
||||
const newProgress: Record<string, number> = {}
|
||||
|
||||
try {
|
||||
for (const file of Array.from(files)) {
|
||||
newProgress[file.name] = 0
|
||||
setUploadProgress({ ...newProgress })
|
||||
|
||||
await processor.uploadDocument({
|
||||
file,
|
||||
collection,
|
||||
metadata: {
|
||||
uploadedBy: 'user',
|
||||
category: 'qa-document'
|
||||
}
|
||||
})
|
||||
|
||||
newProgress[file.name] = 100
|
||||
setUploadProgress({ ...newProgress })
|
||||
}
|
||||
|
||||
// Refresh document list
|
||||
await loadDocuments()
|
||||
|
||||
// Clear file input
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = ''
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Upload failed:', error)
|
||||
alert('Upload failed: ' + error.message)
|
||||
} finally {
|
||||
setIsUploading(false)
|
||||
setUploadProgress({})
|
||||
}
|
||||
}
|
||||
|
||||
const loadDocuments = async () => {
|
||||
try {
|
||||
const docs = await processor.listDocuments(collection)
|
||||
setDocuments(docs)
|
||||
} catch (error) {
|
||||
console.error('Failed to load documents:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const formatSources = (sources: Source[]) => {
|
||||
if (!sources || sources.length === 0) return null
|
||||
|
||||
return (
|
||||
<div className="mt-4 p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
||||
<h3 className="text-sm font-semibold text-gray-700 mb-2">Sources:</h3>
|
||||
<div className="space-y-2">
|
||||
{sources.map((source) => (
|
||||
<div key={source.id} className="flex items-center space-x-2 text-sm">
|
||||
<span className="bg-blue-100 text-blue-800 px-2 py-1 rounded text-xs font-mono">
|
||||
Document {source.citationNumber}
|
||||
</span>
|
||||
<span className="text-gray-700">{source.title}</span>
|
||||
<span className="text-gray-500">
|
||||
({source.relevantChunks} relevant chunks, {(source.score * 100).toFixed(1)}% match)
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto p-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Document Management Panel */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Document Collection</h2>
|
||||
|
||||
{/* Collection Selector */}
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Collection Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={collection}
|
||||
onChange={(e) => setCollection(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
placeholder="e.g., company-docs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* File Upload */}
|
||||
<div className="mb-4">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
accept=".pdf,.docx,.txt,.md"
|
||||
onChange={handleFileUpload}
|
||||
className="hidden"
|
||||
/>
|
||||
<button
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={isUploading}
|
||||
className="w-full p-3 border-2 border-dashed border-gray-300 rounded-lg hover:border-blue-400 focus:ring-2 focus:ring-blue-500 disabled:opacity-50"
|
||||
>
|
||||
{isUploading ? 'Uploading...' : 'Upload Documents'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Upload Progress */}
|
||||
{Object.keys(uploadProgress).length > 0 && (
|
||||
<div className="mb-4 space-y-2">
|
||||
{Object.entries(uploadProgress).map(([filename, progress]) => (
|
||||
<div key={filename} className="text-sm">
|
||||
<div className="flex justify-between">
|
||||
<span className="truncate">{filename}</span>
|
||||
<span>{progress}%</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
||||
<div
|
||||
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Document List */}
|
||||
<div className="max-h-64 overflow-y-auto">
|
||||
{documents.map((doc) => (
|
||||
<div key={doc.id} className="mb-2 p-2 bg-gray-50 rounded text-sm">
|
||||
<div className="font-medium truncate">{doc.title}</div>
|
||||
<div className="text-gray-500 text-xs">
|
||||
{doc.type} • {doc.status}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={loadDocuments}
|
||||
className="w-full mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
Refresh Documents
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Q&A Interface */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Ask Questions</h2>
|
||||
|
||||
{/* Messages */}
|
||||
<div className="h-96 overflow-y-auto mb-4 space-y-4">
|
||||
{messages.length === 0 && (
|
||||
<div className="text-gray-500 text-center py-8">
|
||||
Upload documents and ask questions to get started!
|
||||
|
||||
<div className="mt-4 text-sm">
|
||||
<p className="font-medium">Try asking:</p>
|
||||
<ul className="mt-2 space-y-1">
|
||||
<li>"What are the main findings?"</li>
|
||||
<li>"Summarize the key points"</li>
|
||||
<li>"What does section 3 say about...?"</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{messages.map((message) => (
|
||||
<div
|
||||
key={message.id}
|
||||
className={`p-4 rounded-lg ${
|
||||
message.role === 'user'
|
||||
? 'bg-blue-500 text-white ml-8'
|
||||
: 'bg-gray-100 mr-8'
|
||||
}`}
|
||||
>
|
||||
<div className="whitespace-pre-wrap">{message.content}</div>
|
||||
|
||||
{message.role === 'assistant' && sources.length > 0 && (
|
||||
formatSources(sources)
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{isLoading && (
|
||||
<div className="bg-gray-100 p-4 rounded-lg mr-8">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600"></div>
|
||||
<span>Searching documents and generating answer...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Input */}
|
||||
<form onSubmit={handleSubmit} className="flex gap-2">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Ask a question about your documents..."
|
||||
className="flex-1 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
disabled={isLoading || documents.length === 0}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || !input.trim() || documents.length === 0}
|
||||
className="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Ask
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{documents.length === 0 && (
|
||||
<p className="text-sm text-gray-500 mt-2">
|
||||
Upload documents first to enable questions
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Your Q&A System
|
||||
|
||||
### Step 4: Test Document Processing
|
||||
|
||||
1. **Upload Test Documents**:
|
||||
- Upload a PDF manual or research paper
|
||||
- Add a few web articles via URL
|
||||
- Upload some text files with different topics
|
||||
|
||||
2. **Test Question Types**:
|
||||
```
|
||||
Factual: "What is the definition of X mentioned in the documents?"
|
||||
Analytical: "What are the pros and cons of approach Y?"
|
||||
Comparative: "How does method A compare to method B?"
|
||||
Summarization: "Summarize the main findings"
|
||||
```
|
||||
|
||||
3. **Verify Citations**:
|
||||
- Check that citations appear in responses
|
||||
- Verify citation numbers match source list
|
||||
- Ensure sources show relevant metadata
|
||||
|
||||
## Production Considerations
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
```typescript
|
||||
// Implement caching for frequently asked questions
|
||||
const cacheKey = `qa:${collection}:${hashQuery(question)}`
|
||||
const cachedResponse = await redis.get(cacheKey)
|
||||
|
||||
if (cachedResponse) {
|
||||
return JSON.parse(cachedResponse)
|
||||
}
|
||||
|
||||
// Cache response for 1 hour
|
||||
await redis.setex(cacheKey, 3600, JSON.stringify(response))
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
1. **Follow-up Questions**:
|
||||
```typescript
|
||||
// Track conversation context
|
||||
const conversationHistory = messages.slice(-6) // Last 3 exchanges
|
||||
```
|
||||
|
||||
2. **Answer Confidence Scoring**:
|
||||
```typescript
|
||||
const confidence = calculateConfidence({
|
||||
searchScore: searchResults.results[0]?.score || 0,
|
||||
resultCount: searchResults.results.length,
|
||||
chunkRelevance: avgChunkRelevance
|
||||
})
|
||||
```
|
||||
|
||||
3. **Multi-language Support**:
|
||||
```typescript
|
||||
// Detect document language and adapt search
|
||||
const detectedLanguage = await detectLanguage(question)
|
||||
const searchResults = await client.search.documents({
|
||||
q: question,
|
||||
filters: {
|
||||
AND: [{ key: 'language', value: detectedLanguage }]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
This recipe provides a complete foundation for building document Q&A systems with accurate citations and source tracking.
|
||||
|
||||
---
|
||||
|
||||
*Customize this recipe based on your specific document types and use cases.*
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "Extending context windows in LLMs"
|
||||
url: "https://supermemory.ai/blog/extending-context-windows-in-llms/"
|
||||
---
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
---
|
||||
title: "Cookbook"
|
||||
description: "Complete examples and recipes for building with Supermemory"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
The Supermemory Cookbook provides complete, production-ready examples that show how to build real applications with Supermemory. Each recipe includes full implementation details, best practices, and common patterns.
|
||||
|
||||
## Available Recipes
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Personal AI Assistant" icon="bot" href="/cookbook/personal-assistant">
|
||||
Build an AI assistant that remembers user preferences and context across conversations
|
||||
</Card>
|
||||
|
||||
<Card title="Document Q&A System" icon="file-text" href="/cookbook/document-qa">
|
||||
Create a chatbot that answers questions from your documents with citations
|
||||
</Card>
|
||||
|
||||
<Card title="Customer Support Bot" icon="headphones" href="/cookbook/customer-support">
|
||||
Build a support system that remembers customer history and provides personalized help
|
||||
</Card>
|
||||
|
||||
<Card title="AI SDK Integration" icon="triangle" href="/cookbook/ai-sdk-integration">
|
||||
Complete examples using Vercel AI SDK with Supermemory tools
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Coming Soon
|
||||
|
||||
We're working on more comprehensive recipes. Have a suggestion? [Let us know!](mailto:support@supermemory.ai)
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Research Assistant" icon="search" color="#gray">
|
||||
Organize and search through research papers and notes
|
||||
</Card>
|
||||
|
||||
<Card title="Learning Platform" icon="users" color="#gray">
|
||||
Build a personalized learning system with user isolation
|
||||
</Card>
|
||||
|
||||
<Card title="Code Documentation Bot" icon="code" color="#gray">
|
||||
Create an AI assistant for your codebase and documentation
|
||||
</Card>
|
||||
|
||||
<Card title="Meeting Intelligence" icon="calendar" color="#gray">
|
||||
Process and search through meeting recordings and notes
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Getting Help
|
||||
|
||||
Can't find what you're looking for?
|
||||
|
||||
- Browse [Search](/search) for specific feature usage
|
||||
- Check the [AI SDK Examples](/cookbook/ai-sdk-integration) for complete implementations
|
||||
- Reach out to [support](mailto:support@supermemory.ai) for help
|
||||
|
||||
## Contributing Recipes
|
||||
|
||||
Have a great Supermemory use case? We'd love to add it to the cookbook!
|
||||
|
||||
[Suggest a recipe →](mailto:support@supermemory.ai?subject=Cookbook%20Recipe%20Suggestion)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "Perplexity with memory"
|
||||
url: "https://supermemory.ai/blog/build-your-own-perplexity-in-15-minutes-with-supermemory/"
|
||||
---
|
||||
|
|
@ -1,864 +0,0 @@
|
|||
---
|
||||
title: "Personal AI Assistant"
|
||||
description: "Build an AI assistant that remembers user preferences, habits, and context across conversations"
|
||||
---
|
||||
|
||||
Build a personal AI assistant that learns and remembers everything about the user - their preferences, habits, work context, and conversation history.
|
||||
|
||||
## What You'll Build
|
||||
|
||||
A personal AI assistant that:
|
||||
- **Remembers user preferences** (dietary restrictions, work schedule, communication style)
|
||||
- **Maintains context** across multiple chat sessions
|
||||
- **Provides personalized recommendations** based on user history
|
||||
- **Handles multiple conversation topics** while maintaining context
|
||||
|
||||
## Choose Your Implementation
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Python + FastAPI" icon="python" href="#python-implementation">
|
||||
Thoroughly tested, production-ready. Uses FastAPI + Streamlit + OpenAI.
|
||||
</Card>
|
||||
<Card title="TypeScript + AI SDK" icon="triangle" href="#typescript-implementation">
|
||||
Modern React approach. Uses Next.js + Vercel AI SDK + Supermemory tools.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Python 3.8+** or **Node.js 18+**
|
||||
- **Supermemory API key** ([get one here](https://console.supermemory.ai))
|
||||
- **OpenAI API key** ([get one here](https://platform.openai.com/api-keys))
|
||||
|
||||
<Warning>
|
||||
Never hardcode API keys in your code. Use environment variables.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Python Implementation
|
||||
|
||||
### Step 1: Project Setup
|
||||
|
||||
```bash
|
||||
mkdir personal-ai && cd personal-ai
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
pip install supermemory openai fastapi uvicorn python-dotenv streamlit requests
|
||||
```
|
||||
|
||||
Create a `.env` file:
|
||||
|
||||
```bash
|
||||
SUPERMEMORY_API_KEY=your_supermemory_key_here
|
||||
OPENAI_API_KEY=your_openai_key_here
|
||||
```
|
||||
|
||||
### Step 2: Backend (FastAPI)
|
||||
|
||||
Create `main.py`. Let's build it step by step:
|
||||
|
||||
#### Import Dependencies
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
from openai import AsyncOpenAI
|
||||
from supermemory import Supermemory
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from dotenv import load_dotenv
|
||||
```
|
||||
|
||||
- **FastAPI**: Web framework for building the API endpoint
|
||||
- **StreamingResponse**: Enables real-time response streaming (words appear as they're generated)
|
||||
- **AsyncOpenAI**: OpenAI client that supports async/await for non-blocking operations
|
||||
- **Supermemory**: Client for storing and retrieving long-term memories
|
||||
- **uuid**: Creates stable, deterministic user IDs from emails
|
||||
|
||||
#### Initialize Application and Clients
|
||||
|
||||
```python
|
||||
load_dotenv()
|
||||
app = FastAPI()
|
||||
|
||||
openai_client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
supermemory_client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
|
||||
```
|
||||
|
||||
`load_dotenv()` loads API keys from your `.env` file into environment variables. We create two clients:
|
||||
- **OpenAI client**: Handles conversations and generates responses
|
||||
- **Supermemory client**: Stores and retrieves user-specific memories
|
||||
|
||||
These are separate because you can swap providers independently (e.g., switch from OpenAI to Anthropic without changing memory logic).
|
||||
|
||||
#### Define System Prompt
|
||||
|
||||
```python
|
||||
SYSTEM_PROMPT = """You are a highly personalized AI assistant.
|
||||
|
||||
MEMORY MANAGEMENT:
|
||||
1. When users share personal information, store it immediately
|
||||
2. Search for relevant context before responding
|
||||
3. Use past conversations to inform current responses
|
||||
|
||||
Always be helpful while respecting privacy."""
|
||||
```
|
||||
|
||||
This prompt guides the assistant's behavior. It tells the AI to:
|
||||
- Be proactive about learning user preferences
|
||||
- Always search memory before responding
|
||||
- Respect privacy boundaries
|
||||
|
||||
The system prompt is injected at the start of every conversation, so the AI consistently follows these rules.
|
||||
|
||||
#### Create Identity Helpers
|
||||
|
||||
```python
|
||||
def normalize_email(email: str) -> str:
|
||||
return (email or "").strip().lower()
|
||||
|
||||
def stable_user_id_from_email(email: str) -> str:
|
||||
norm = normalize_email(email)
|
||||
if not norm:
|
||||
raise ValueError("Email is required")
|
||||
return uuid.uuid5(uuid.NAMESPACE_DNS, norm).hex
|
||||
```
|
||||
|
||||
**Why normalize?** `"User@Mail.com"` and `" user@mail.com "` should map to the same person. We trim whitespace and lowercase to ensure consistency.
|
||||
|
||||
**Why UUIDv5?** It's deterministic—same email always produces the same ID. This means:
|
||||
- User memories persist across sessions
|
||||
- No raw emails in logs or database tags
|
||||
- Privacy-preserving yet stable identity
|
||||
|
||||
We use `uuid.NAMESPACE_DNS` as the namespace to ensure uniqueness.
|
||||
|
||||
#### Memory Search Function
|
||||
|
||||
```python
|
||||
async def search_user_memories(query: str, container_tag: str) -> str:
|
||||
try:
|
||||
results = supermemory_client.search.memories(
|
||||
q=query,
|
||||
container_tag=container_tag,
|
||||
limit=5
|
||||
)
|
||||
if results.results:
|
||||
context = "\n".join([r.memory for r in results.results])
|
||||
return f"Relevant memories:\n{context}"
|
||||
return "No relevant memories found."
|
||||
except Exception as e:
|
||||
return f"Error searching memories: {e}"
|
||||
```
|
||||
|
||||
This searches the user's memory store for context relevant to their current message.
|
||||
|
||||
**Parameters:**
|
||||
- `q`: The search query (usually the user's latest message)
|
||||
- `container_tag`: Isolates memories per user (e.g., `user_abc123`)
|
||||
- `limit=5`: Returns top 5 most relevant memories
|
||||
|
||||
**Why search before responding?** The AI can provide personalized answers based on what it knows about the user (e.g., dietary preferences, work context, communication style).
|
||||
|
||||
**Error handling:** If memory search fails, we return a fallback message instead of crashing. The conversation continues even if memory has a hiccup.
|
||||
|
||||
#### Memory Storage Function
|
||||
|
||||
```python
|
||||
async def add_user_memory(content: str, container_tag: str, email: str = None):
|
||||
try:
|
||||
supermemory_client.add(
|
||||
content=content,
|
||||
container_tag=container_tag,
|
||||
metadata={"type": "personal_info", "email": normalize_email(email) if email else None}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error adding memory: {e}")
|
||||
```
|
||||
|
||||
Stores new information about the user.
|
||||
|
||||
**Parameters:**
|
||||
- `content`: The text to remember
|
||||
- `container_tag`: User isolation tag
|
||||
- `metadata`: Additional context (type of info, associated email)
|
||||
|
||||
**Why metadata?** Makes it easier to filter and organize memories later (e.g., "show me all personal_info memories").
|
||||
|
||||
**Error handling:** We log errors but don't crash. Failing to save one memory shouldn't break the entire conversation.
|
||||
|
||||
#### Main Chat Endpoint
|
||||
|
||||
```python
|
||||
@app.post("/chat")
|
||||
async def chat_endpoint(data: dict):
|
||||
messages = data.get("messages", [])
|
||||
email = data.get("email")
|
||||
|
||||
if not messages:
|
||||
raise HTTPException(status_code=400, detail="No messages provided")
|
||||
if not email:
|
||||
raise HTTPException(status_code=400, detail="Email required")
|
||||
```
|
||||
|
||||
This endpoint receives the chat request. It expects:
|
||||
- `messages`: Full conversation history `[{role: "user", content: "..."}]`
|
||||
- `email`: User's email for identity
|
||||
|
||||
**Why require email?** Without it, we can't create a stable user ID, meaning no persistent personalization.
|
||||
|
||||
#### Derive User Identity
|
||||
|
||||
```python
|
||||
try:
|
||||
user_id = stable_user_id_from_email(email)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
container_tag = f"user_{user_id}"
|
||||
```
|
||||
|
||||
Convert email → stable user ID → container tag.
|
||||
|
||||
The container tag (`user_abc123`) isolates this user's memories from everyone else's. Each user has their own "memory box."
|
||||
|
||||
#### Search and Inject Memories
|
||||
|
||||
```python
|
||||
user_message = messages[-1]["content"]
|
||||
memory_context = await search_user_memories(user_message, container_tag)
|
||||
|
||||
enhanced_messages = [
|
||||
{"role": "system", "content": f"{SYSTEM_PROMPT}\n\n{memory_context}"}
|
||||
] + messages
|
||||
```
|
||||
|
||||
We take the user's latest message, search for relevant memories, then inject them into the system prompt.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Original: "What should I eat for breakfast?"
|
||||
|
||||
Enhanced system message:
|
||||
"You are a helpful assistant... [system prompt]
|
||||
|
||||
Relevant memories:
|
||||
- User is vegetarian
|
||||
- User works out at 6 AM
|
||||
- User prefers quick meals"
|
||||
```
|
||||
|
||||
Now the AI can answer: "Try overnight oats with plant-based protein—perfect for post-workout!"
|
||||
|
||||
#### Stream OpenAI Response
|
||||
|
||||
```python
|
||||
try:
|
||||
response = await openai_client.chat.completions.create(
|
||||
model="gpt-5",
|
||||
messages=enhanced_messages,
|
||||
temperature=0.7,
|
||||
stream=True
|
||||
)
|
||||
```
|
||||
|
||||
**Key parameters:**
|
||||
- `model="gpt-5"`: Fast, capable model
|
||||
- `messages`: Full conversation + memory context
|
||||
- `temperature=0.7`: Balanced creativity (0=deterministic, 1=creative)
|
||||
- `stream=True`: Enables word-by-word streaming
|
||||
|
||||
**Why stream?** Users see responses appear in real-time instead of waiting for the complete answer. Much better UX.
|
||||
|
||||
#### Handle Streaming
|
||||
|
||||
```python
|
||||
async def generate():
|
||||
try:
|
||||
async for chunk in response:
|
||||
if chunk.choices[0].delta.content:
|
||||
content = chunk.choices[0].delta.content
|
||||
yield f"data: {json.dumps({'content': content})}\n\n"
|
||||
except Exception as e:
|
||||
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
||||
```
|
||||
|
||||
This async generator:
|
||||
1. Receives chunks from OpenAI as they're generated
|
||||
2. Extracts the text content from each chunk
|
||||
3. Formats it as Server-Sent Events (SSE): `data: {...}\n\n`
|
||||
4. Yields it to the client
|
||||
|
||||
**SSE format** is a web standard for server→client streaming. The frontend can process each chunk as it arrives.
|
||||
|
||||
#### Optional Memory Storage
|
||||
|
||||
```python
|
||||
if "remember this" in user_message.lower():
|
||||
await add_user_memory(user_message, container_tag, email=email)
|
||||
```
|
||||
|
||||
After streaming completes, check if the user explicitly asked to remember something. If yes, store it.
|
||||
|
||||
**Why opt-in?** Gives users control over what gets remembered. You could also make this automatic based on content analysis.
|
||||
|
||||
#### Return Streaming Response
|
||||
|
||||
```python
|
||||
return StreamingResponse(generate(), media_type="text/plain")
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
```
|
||||
|
||||
`StreamingResponse` keeps the HTTP connection open and sends chunks as they're generated. The frontend receives them in real-time.
|
||||
|
||||
#### Local Development Server
|
||||
|
||||
```python
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
Run with `python main.py` and the server starts on port 8000. `0.0.0.0` means it accepts connections from any IP (useful for testing from other devices).
|
||||
|
||||
### Step 3: Frontend (Streamlit)
|
||||
|
||||
Create `streamlit_app.py`:
|
||||
|
||||
<Accordion title="Complete Frontend Code" defaultOpen>
|
||||
|
||||
```python
|
||||
import streamlit as st
|
||||
import requests
|
||||
import json
|
||||
import uuid
|
||||
|
||||
st.set_page_config(page_title="Personal AI Assistant", page_icon="🤖", layout="wide")
|
||||
|
||||
def normalize_email(email: str) -> str:
|
||||
return (email or "").strip().lower()
|
||||
|
||||
def stable_user_id_from_email(email: str) -> str:
|
||||
return uuid.uuid5(uuid.NAMESPACE_DNS, normalize_email(email)).hex
|
||||
|
||||
# Session state
|
||||
if 'messages' not in st.session_state:
|
||||
st.session_state.messages = []
|
||||
if 'user_name' not in st.session_state:
|
||||
st.session_state.user_name = None
|
||||
if 'email' not in st.session_state:
|
||||
st.session_state.email = None
|
||||
if 'user_id' not in st.session_state:
|
||||
st.session_state.user_id = None
|
||||
|
||||
st.title("🤖 Personal AI Assistant")
|
||||
st.markdown("*Your AI that learns and remembers*")
|
||||
|
||||
with st.sidebar:
|
||||
st.header("👤 User Profile")
|
||||
|
||||
if not st.session_state.user_name or not st.session_state.email:
|
||||
name = st.text_input("What should I call you?")
|
||||
email = st.text_input("Email", placeholder="you@example.com")
|
||||
|
||||
if st.button("Get Started"):
|
||||
if name and email:
|
||||
st.session_state.user_name = name
|
||||
st.session_state.email = normalize_email(email)
|
||||
st.session_state.user_id = stable_user_id_from_email(st.session_state.email)
|
||||
st.session_state.messages.append({
|
||||
"role": "user",
|
||||
"content": f"Hi! My name is {name}."
|
||||
})
|
||||
st.rerun()
|
||||
else:
|
||||
st.warning("Please enter both fields.")
|
||||
else:
|
||||
st.write(f"**Name:** {st.session_state.user_name}")
|
||||
st.write(f"**Email:** {st.session_state.email}")
|
||||
if st.button("Reset Conversation"):
|
||||
st.session_state.messages = []
|
||||
st.rerun()
|
||||
|
||||
if st.session_state.user_name and st.session_state.email:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
if prompt := st.chat_input("Message..."):
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
try:
|
||||
response = requests.post(
|
||||
"http://localhost:8000/chat",
|
||||
json={
|
||||
"messages": st.session_state.messages,
|
||||
"email": st.session_state.email
|
||||
},
|
||||
stream=True,
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
full_response = ""
|
||||
for line in response.iter_lines():
|
||||
if line:
|
||||
try:
|
||||
data = json.loads(line.decode('utf-8').replace('data: ', ''))
|
||||
if 'content' in data:
|
||||
full_response += data['content']
|
||||
except:
|
||||
continue
|
||||
|
||||
st.markdown(full_response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": full_response})
|
||||
else:
|
||||
st.error(f"Error: {response.status_code}")
|
||||
except Exception as e:
|
||||
st.error(f"Error: {e}")
|
||||
else:
|
||||
st.info("Please enter your profile in the sidebar")
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
### Step 4: Run It
|
||||
|
||||
Terminal 1 - Start backend:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
Terminal 2 - Start frontend:
|
||||
```bash
|
||||
streamlit run streamlit_app.py
|
||||
```
|
||||
|
||||
Open `http://localhost:8501` in your browser.
|
||||
|
||||
---
|
||||
|
||||
## TypeScript Implementation
|
||||
|
||||
### Step 1: Project Setup
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest personal-ai --typescript --tailwind --app
|
||||
cd personal-ai
|
||||
npm install @supermemory/tools ai @ai-sdk/openai
|
||||
```
|
||||
|
||||
Create `.env.local`:
|
||||
|
||||
```bash
|
||||
SUPERMEMORY_API_KEY=your_supermemory_key_here
|
||||
OPENAI_API_KEY=your_openai_key_here
|
||||
```
|
||||
|
||||
### Step 2: API Route
|
||||
|
||||
Create `app/api/chat/route.ts`. Let's break it down:
|
||||
|
||||
#### Import Dependencies
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
```
|
||||
|
||||
- **streamText**: Vercel AI SDK function that handles streaming responses and tool calling
|
||||
- **createOpenAI**: Factory function to create an OpenAI provider
|
||||
- **supermemoryTools**: Pre-built tools for memory search and storage
|
||||
|
||||
#### Initialize OpenAI Provider
|
||||
|
||||
```typescript
|
||||
const openai = createOpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY!
|
||||
})
|
||||
```
|
||||
|
||||
Creates an OpenAI provider configured with your API key. The `!` tells TypeScript "this definitely exists" (because we set it in `.env.local`).
|
||||
|
||||
This provider object will be passed to `streamText` to specify which AI model to use.
|
||||
|
||||
#### Define System Prompt
|
||||
|
||||
```typescript
|
||||
const SYSTEM_PROMPT = `You are a highly personalized AI assistant.
|
||||
|
||||
When users share personal information, remember it using the addMemory tool.
|
||||
Before responding, search your memories using searchMemories to provide personalized help.
|
||||
Always be helpful while respecting privacy.`
|
||||
```
|
||||
|
||||
This guides the AI's behavior and tells it:
|
||||
- **When to use tools**: Search memories before responding, add memories when users share info
|
||||
- **Personality**: Be helpful and personalized
|
||||
- **Boundaries**: Respect privacy
|
||||
|
||||
The AI SDK uses this to decide when to call `searchMemories` and `addMemory` tools automatically.
|
||||
|
||||
#### Create POST Handler
|
||||
|
||||
```typescript
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const { messages, email } = await req.json()
|
||||
```
|
||||
|
||||
Next.js App Router convention: export an async function named after the HTTP method. This handles POST requests to `/api/chat`.
|
||||
|
||||
We extract:
|
||||
- `messages`: Chat history array `[{role, content}]`
|
||||
- `email`: User identifier
|
||||
|
||||
#### Validate Input
|
||||
|
||||
```typescript
|
||||
if (!messages?.length) {
|
||||
return new Response('No messages provided', { status: 400 })
|
||||
}
|
||||
if (!email) {
|
||||
return new Response('Email required', { status: 400 })
|
||||
}
|
||||
```
|
||||
|
||||
**Why validate?** Prevents crashes from malformed requests. We need:
|
||||
- At least one message to respond to
|
||||
- An email to isolate user memories
|
||||
|
||||
Without email, we can't maintain personalization across sessions.
|
||||
|
||||
#### Create Container Tag
|
||||
|
||||
```typescript
|
||||
const containerTag = `user_${email.toLowerCase().trim()}`
|
||||
```
|
||||
|
||||
Convert email to a container tag for memory isolation.
|
||||
|
||||
**Simpler than Python**: We skip UUID generation here for simplicity. In production, you might want to hash the email for privacy:
|
||||
|
||||
```typescript
|
||||
// Optional: More privacy-preserving approach
|
||||
import crypto from 'crypto'
|
||||
const containerTag = `user_${crypto.createHash('sha256').update(email).digest('hex').slice(0, 16)}`
|
||||
```
|
||||
|
||||
#### Call streamText with Tools
|
||||
|
||||
```typescript
|
||||
const result = streamText({
|
||||
model: openai('gpt-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [containerTag]
|
||||
}),
|
||||
system: SYSTEM_PROMPT
|
||||
})
|
||||
```
|
||||
|
||||
This is where the magic happens! Let's break down each parameter:
|
||||
|
||||
**`model: openai('gpt-5')`**
|
||||
- Specifies which AI model to use
|
||||
- The AI SDK handles the API calls
|
||||
|
||||
**`messages`**
|
||||
- Full conversation history
|
||||
- Format: `[{role: "user"|"assistant", content: "..."}]`
|
||||
|
||||
**`tools: supermemoryTools(...)`**
|
||||
- Gives the AI access to memory operations
|
||||
- The AI SDK automatically:
|
||||
- Decides when to call tools based on the conversation
|
||||
- Calls `searchMemories` when it needs context
|
||||
- Calls `addMemory` when users share information
|
||||
- Handles tool execution and error handling
|
||||
|
||||
**`containerTags: [containerTag]`**
|
||||
- Scopes all memory operations to this specific user
|
||||
- Ensures User A can't access User B's memories
|
||||
|
||||
**`system: SYSTEM_PROMPT`**
|
||||
- Guides the AI's behavior and tool usage
|
||||
|
||||
**How tools work:**
|
||||
1. User: "Remember that I'm vegetarian"
|
||||
2. AI SDK detects this is memory-worthy
|
||||
3. Automatically calls `addMemory("User is vegetarian")`
|
||||
4. Stores in Supermemory with the user's container tag
|
||||
5. Responds: "Got it, I'll remember that!"
|
||||
|
||||
Later:
|
||||
1. User: "What should I eat?"
|
||||
2. AI SDK calls `searchMemories("food preferences")`
|
||||
3. Retrieves: "User is vegetarian"
|
||||
4. Responds: "How about a delicious veggie stir-fry?"
|
||||
|
||||
**No manual tool handling needed!** The AI SDK manages the entire flow.
|
||||
|
||||
#### Return Streaming Response
|
||||
|
||||
```typescript
|
||||
return result.toAIStreamResponse()
|
||||
```
|
||||
|
||||
`toAIStreamResponse()` 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
|
||||
|
||||
This returns immediately (doesn't wait for completion), and chunks stream to the client as they're generated.
|
||||
|
||||
#### Error Handling
|
||||
|
||||
```typescript
|
||||
} catch (error: any) {
|
||||
console.error('Chat error:', error)
|
||||
return new Response(error.message, { status: 500 })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Catches any errors (API failures, tool errors, etc.) and returns a clean error response.
|
||||
|
||||
**Why log to console?** In production, you'd send this to a monitoring service (Sentry, DataDog, etc.) to track issues.
|
||||
|
||||
---
|
||||
|
||||
**Key Differences from Python:**
|
||||
|
||||
| Aspect | Python | TypeScript |
|
||||
|--------|--------|------------|
|
||||
| **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 |
|
||||
| **Error Handling** | Try/catch in each function | AI SDK handles tool errors |
|
||||
|
||||
**Python = Manual Control**
|
||||
You explicitly search and add memories. More control, more code.
|
||||
|
||||
**TypeScript = AI-Driven**
|
||||
The AI decides when to use tools. Less code, more "magic."
|
||||
|
||||
### Step 3: Chat UI
|
||||
|
||||
Replace `app/page.tsx`:
|
||||
|
||||
<Accordion title="Complete Frontend Code" defaultOpen>
|
||||
|
||||
```typescript
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default function ChatPage() {
|
||||
const [email, setEmail] = useState('')
|
||||
const [userName, setUserName] = useState('')
|
||||
const [tempEmail, setTempEmail] = useState('')
|
||||
const [tempName, setTempName] = useState('')
|
||||
|
||||
const { messages, input, handleInputChange, handleSubmit } = useChat({
|
||||
api: '/api/chat',
|
||||
body: { email }
|
||||
})
|
||||
|
||||
if (!email) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen p-4">
|
||||
<div className="w-full max-w-md space-y-4 p-6 bg-white rounded-lg shadow-lg">
|
||||
<h1 className="text-2xl font-bold text-center">🤖 Personal AI Assistant</h1>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Your name"
|
||||
value={tempName}
|
||||
onChange={(e) => setTempName(e.target.value)}
|
||||
className="w-full px-4 py-2 border rounded-lg"
|
||||
/>
|
||||
<input
|
||||
type="email"
|
||||
placeholder="your@email.com"
|
||||
value={tempEmail}
|
||||
onChange={(e) => setTempEmail(e.target.value)}
|
||||
className="w-full px-4 py-2 border rounded-lg"
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (tempName && tempEmail) {
|
||||
setUserName(tempName)
|
||||
setEmail(tempEmail.toLowerCase().trim())
|
||||
}
|
||||
}}
|
||||
className="w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
||||
>
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen max-w-4xl mx-auto p-4">
|
||||
<div className="flex-1 overflow-y-auto space-y-4 mb-4">
|
||||
{messages.map((message) => (
|
||||
<div
|
||||
key={message.id}
|
||||
className={`p-4 rounded-lg ${
|
||||
message.role === 'user'
|
||||
? 'bg-blue-100 ml-auto max-w-[80%]'
|
||||
: 'bg-gray-100 mr-auto max-w-[80%]'
|
||||
}`}
|
||||
>
|
||||
<p className="whitespace-pre-wrap">{message.content}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="flex gap-2">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Tell me about yourself..."
|
||||
className="flex-1 p-3 border rounded-lg"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
### Step 4: Run It
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:3000`
|
||||
|
||||
---
|
||||
|
||||
## Testing Your Assistant
|
||||
|
||||
Try these conversations to test memory:
|
||||
|
||||
**Personal Preferences:**
|
||||
```
|
||||
User: "I'm Sarah, a product manager. I prefer brief responses."
|
||||
[Later]
|
||||
User: "What's a good way to prioritize features?"
|
||||
Assistant: [Should reference PM role and brevity preference]
|
||||
```
|
||||
|
||||
**Dietary & Lifestyle:**
|
||||
```
|
||||
User: "Remember I'm vegan and work out at 6 AM."
|
||||
[Later]
|
||||
User: "Suggest a quick breakfast."
|
||||
Assistant: [Should suggest vegan options for pre/post workout]
|
||||
```
|
||||
|
||||
**Work Context:**
|
||||
```
|
||||
User: "I'm working on a React project with TypeScript."
|
||||
[Later]
|
||||
User: "Help me with state management."
|
||||
Assistant: [Should suggest TypeScript-specific solutions]
|
||||
```
|
||||
|
||||
## Verify Memory Storage
|
||||
|
||||
### Python
|
||||
|
||||
Create `check_memories.py`:
|
||||
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
|
||||
|
||||
# Replace with your user_id from console logs
|
||||
user_id = "your_user_id_here"
|
||||
container_tag = f"user_{user_id}"
|
||||
|
||||
memories = client.documents.list(
|
||||
container_tags=[container_tag],
|
||||
limit=20,
|
||||
sort="updatedAt",
|
||||
order="desc"
|
||||
)
|
||||
|
||||
print(f"Found {len(memories.memories)} memories:")
|
||||
for i, memory in enumerate(memories.memories):
|
||||
full = client.documents.get(id=memory.id)
|
||||
print(f"\n{i + 1}. {full.content}")
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
Create `scripts/check-memories.ts`:
|
||||
|
||||
```typescript
|
||||
const userId = "your_user_id_here"
|
||||
const containerTag = `user_${userId}`
|
||||
|
||||
const response = await fetch('https://api.supermemory.ai/v3/memories', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTags: [containerTag],
|
||||
limit: 20,
|
||||
sort: 'updatedAt',
|
||||
order: 'desc'
|
||||
})
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
console.log(`Found ${data.memories?.length || 0} memories`)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Memory not persisting?**
|
||||
- Verify container tags are consistent
|
||||
- Check API key has write permissions
|
||||
- Ensure email is properly normalized
|
||||
|
||||
**Responses not personalized?**
|
||||
- Increase search limit to find more memories
|
||||
- Check that memories are being added
|
||||
- Verify system prompt guides tool usage
|
||||
|
||||
**Performance issues?**
|
||||
- Reduce search limits
|
||||
- Implement caching for frequent queries
|
||||
- Use appropriate thresholds
|
||||
|
||||
---
|
||||
|
||||
*Built with Supermemory. Customize based on your needs.*
|
||||
|
|
@ -3,9 +3,10 @@
|
|||
"api": {
|
||||
"examples": {
|
||||
"defaults": "required",
|
||||
"languages": ["javascript", "python", "curl"]
|
||||
"languages": ["typescript", "python", "bash"],
|
||||
"prefill": true
|
||||
},
|
||||
"openapi": "https://api.supermemory.ai/v3/openapi"
|
||||
"openapi": "https://api.supermemory.ai/v4/openapi"
|
||||
},
|
||||
"colors": {
|
||||
"dark": "#1E3A8A",
|
||||
|
|
@ -13,7 +14,7 @@
|
|||
"primary": "#1E3A8A"
|
||||
},
|
||||
"contextual": {
|
||||
"options": ["copy", "view", "chatgpt", "claude"]
|
||||
"options": ["copy", "view", "assistant", "chatgpt", "claude"]
|
||||
},
|
||||
"favicon": "/favicon.png",
|
||||
"fonts": {
|
||||
|
|
@ -43,6 +44,10 @@
|
|||
"name": "supermemory | Memory API for the AI era",
|
||||
"navbar": {
|
||||
"links": [
|
||||
{
|
||||
"href": "https://supermemory.ai/changelog",
|
||||
"label": "Changelog"
|
||||
},
|
||||
{
|
||||
"href": "mailto:support@supermemory.com",
|
||||
"label": "Support"
|
||||
|
|
@ -56,29 +61,23 @@
|
|||
},
|
||||
"navigation": {
|
||||
"tabs": [
|
||||
{
|
||||
"tab": "Overview",
|
||||
"pages": ["index"]
|
||||
},
|
||||
{
|
||||
"icon": "code",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "Your Dashboard",
|
||||
"href": "https://console.supermemory.ai",
|
||||
"icon": "play"
|
||||
},
|
||||
{
|
||||
"anchor": "Developer Platform",
|
||||
"anchor": "Developer Platform (API)",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"pages": ["intro", "quickstart", "vibe-coding"]
|
||||
},
|
||||
{
|
||||
"group": "Self-Hosting",
|
||||
"pages": [
|
||||
"self-hosting/overview",
|
||||
"self-hosting/quickstart",
|
||||
"self-hosting/configuration",
|
||||
"self-hosting/embeddings",
|
||||
"self-hosting/local-vs-enterprise"
|
||||
"overview/what-is-supermemory",
|
||||
"overview/comparison",
|
||||
"quickstart",
|
||||
"agents-and-mcp"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -87,41 +86,47 @@
|
|||
"concepts/how-it-works",
|
||||
"concepts/graph-memory",
|
||||
"concepts/content-types",
|
||||
"concepts/super-rag",
|
||||
"concepts/memory-vs-rag",
|
||||
"concepts/container-tags",
|
||||
"concepts/filtering",
|
||||
"concepts/user-profiles",
|
||||
"concepts/customization",
|
||||
"authentication"
|
||||
{
|
||||
"group": "Retrieval",
|
||||
"icon": "search",
|
||||
"pages": ["concepts/super-rag", "concepts/memory-vs-rag"]
|
||||
},
|
||||
{
|
||||
"group": "Multi-tenancy and filtering",
|
||||
"icon": "users",
|
||||
"pages": [
|
||||
"concepts/multi-tenancy",
|
||||
"concepts/multi-tenancy-examples",
|
||||
"concepts/container-tags",
|
||||
"concepts/filtering"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "User Profiles",
|
||||
"icon": "id-card",
|
||||
"pages": ["concepts/user-profiles", "user-profiles/buckets"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Using supermemory",
|
||||
"pages": [
|
||||
"add-memories",
|
||||
"search",
|
||||
"user-profiles",
|
||||
"using-supermemory",
|
||||
"authentication",
|
||||
"concepts/customization",
|
||||
{
|
||||
"group": "Manage Content",
|
||||
"icon": "folder-cog",
|
||||
"group": "Ingestion",
|
||||
"icon": "download",
|
||||
"pages": [
|
||||
"document-operations",
|
||||
"memory-operations",
|
||||
"memory-review"
|
||||
"ingestion/add-memories",
|
||||
"ingestion/document-operations"
|
||||
]
|
||||
},
|
||||
"overview/use-cases"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Connectors and sync",
|
||||
"pages": [
|
||||
"connectors/overview",
|
||||
{
|
||||
"group": "Connectors",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"connectors/overview",
|
||||
"connectors/notion",
|
||||
"connectors/google-drive",
|
||||
"connectors/gmail",
|
||||
|
|
@ -129,11 +134,80 @@
|
|||
"connectors/s3",
|
||||
"connectors/granola",
|
||||
"connectors/github",
|
||||
"connectors/web-crawler"
|
||||
"connectors/web-crawler",
|
||||
"connectors/troubleshooting",
|
||||
"connectors/managing-resources"
|
||||
]
|
||||
},
|
||||
"connectors/troubleshooting",
|
||||
"memory-api/connectors/managing-resources"
|
||||
{
|
||||
"group": "Recall",
|
||||
"icon": "upload",
|
||||
"pages": [
|
||||
"recall/search",
|
||||
"recall/user-profiles",
|
||||
"recall/memory-operations",
|
||||
"recall/memory-review"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "SMFS",
|
||||
"icon": "database",
|
||||
"pages": [
|
||||
"smfs/overview",
|
||||
"smfs/install",
|
||||
"smfs/mount",
|
||||
"smfs/bash-tool",
|
||||
"smfs/bash-tool-python",
|
||||
{
|
||||
"group": "Providers",
|
||||
"icon": "cloud",
|
||||
"pages": [
|
||||
"smfs/providers/daytona",
|
||||
"smfs/providers/e2b",
|
||||
"smfs/providers/vercel",
|
||||
"smfs/providers/cloudflare"
|
||||
]
|
||||
},
|
||||
"smfs/examples"
|
||||
]
|
||||
},
|
||||
"concepts/rules"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Deployment",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Supermemory local",
|
||||
"icon": "server",
|
||||
"pages": [
|
||||
"self-hosting/overview",
|
||||
"self-hosting/quickstart",
|
||||
"self-hosting/configuration",
|
||||
"self-hosting/embeddings",
|
||||
"self-hosting/providers",
|
||||
"self-hosting/local-vs-enterprise"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Other resources",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Benchmarking",
|
||||
"icon": "flask-conical",
|
||||
"pages": [
|
||||
"memorybench/overview",
|
||||
"memorybench/extend-benchmark",
|
||||
"memorybench/extend-provider",
|
||||
"memorybench/memscore"
|
||||
]
|
||||
},
|
||||
"overview/billing",
|
||||
"overview/security",
|
||||
"overview/use-cases",
|
||||
"overview/analytics"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -148,49 +222,9 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"anchor": "Supermemory MCP",
|
||||
"icon": "terminal",
|
||||
"pages": [
|
||||
"supermemory-mcp/mcp",
|
||||
"supermemory-mcp/setup",
|
||||
{
|
||||
"group": "Setups",
|
||||
"icon": "layers",
|
||||
"pages": ["supermemory-mcp/claude-desktop"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"anchor": "SMFS",
|
||||
"icon": "database",
|
||||
"pages": [
|
||||
"smfs/overview",
|
||||
"smfs/install",
|
||||
"smfs/mount",
|
||||
"smfs/bash-tool",
|
||||
"smfs/bash-tool-python",
|
||||
{
|
||||
"group": "Providers",
|
||||
"icon": "cloud",
|
||||
"pages": [
|
||||
"smfs/providers/daytona",
|
||||
"smfs/providers/e2b",
|
||||
"smfs/providers/vercel",
|
||||
"smfs/providers/cloudflare"
|
||||
]
|
||||
},
|
||||
"smfs/examples"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tab": "Developer Platform"
|
||||
},
|
||||
{
|
||||
"icon": "plug",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "API Integrations",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"integrations/supermemory-sdk",
|
||||
"integrations/ai-sdk",
|
||||
|
|
@ -207,6 +241,7 @@
|
|||
"integrations/memory-graph",
|
||||
"integrations/claude-memory",
|
||||
"integrations/pipecat",
|
||||
"integrations/cartesia",
|
||||
"integrations/n8n",
|
||||
"integrations/viasocket",
|
||||
"integrations/zapier",
|
||||
|
|
@ -216,123 +251,214 @@
|
|||
"pages": ["migration/tools-v2-upgrade"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"anchor": "API Reference",
|
||||
"icon": "unplug",
|
||||
"openapi": "https://api.supermemory.ai/v4/openapi",
|
||||
"pages": [
|
||||
"api-reference/overview",
|
||||
"authentication",
|
||||
{
|
||||
"group": "Ingest",
|
||||
"icon": "download",
|
||||
"pages": [
|
||||
"api-reference/ingest",
|
||||
"POST /v3/documents",
|
||||
"POST /v3/documents/file",
|
||||
"POST /v3/documents/batch",
|
||||
"POST /v4/conversations",
|
||||
"GET /v3/documents/{id}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Recall",
|
||||
"icon": "search",
|
||||
"pages": [
|
||||
"api-reference/search",
|
||||
"POST /v4/search",
|
||||
"POST /v3/search",
|
||||
"api-reference/profiles",
|
||||
"POST /v4/profile",
|
||||
"POST /v4/profile/buckets"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Documents",
|
||||
"icon": "file-text",
|
||||
"pages": [
|
||||
"api-reference/documents",
|
||||
"POST /v3/documents/list",
|
||||
"GET /v3/documents/processing",
|
||||
"PATCH /v3/documents/{id}",
|
||||
"DELETE /v3/documents/{id}",
|
||||
"DELETE /v3/documents/bulk",
|
||||
"GET /v3/documents/{id}/chunks",
|
||||
"GET /v3/documents/{id}/file-url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Memories",
|
||||
"icon": "database",
|
||||
"pages": [
|
||||
"api-reference/memories",
|
||||
"POST /v4/memories",
|
||||
"POST /v4/memories/list",
|
||||
"PATCH /v4/memories",
|
||||
"DELETE /v4/memories",
|
||||
"POST /v4/memories/forget-matching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Container tags",
|
||||
"icon": "tags",
|
||||
"pages": [
|
||||
"api-reference/container-tags",
|
||||
"GET /v3/container-tags/{containerTag}",
|
||||
"PATCH /v3/container-tags/{containerTag}",
|
||||
"DELETE /v3/container-tags/{containerTag}",
|
||||
"POST /v3/container-tags/merge",
|
||||
"GET /v3/container-tags/merge/{mergeId}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Connections",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"api-reference/connections",
|
||||
"POST /v3/connections/{provider}",
|
||||
"POST /v3/connections/list",
|
||||
"GET /v3/connections/{connectionId}",
|
||||
"POST /v3/connections/{connectionId}/configure",
|
||||
"GET /v3/connections/{connectionId}/resources",
|
||||
"POST /v3/connections/{provider}/import",
|
||||
"POST /v3/connections/{provider}/documents",
|
||||
"POST /v3/connections/{provider}/connection",
|
||||
"DELETE /v3/connections/{connectionId}",
|
||||
"DELETE /v3/connections/{provider}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Settings",
|
||||
"icon": "settings",
|
||||
"pages": [
|
||||
"api-reference/settings",
|
||||
"GET /v3/settings",
|
||||
"PATCH /v3/settings",
|
||||
"POST /v3/settings/suggest-buckets",
|
||||
"POST /v3/settings/reset"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tab": "API Integrations"
|
||||
"tab": "Developer Platform"
|
||||
},
|
||||
{
|
||||
"icon": "puzzle",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "Plugins",
|
||||
"anchor": "Plugins and MCP",
|
||||
"icon": "puzzle",
|
||||
"pages": [
|
||||
"integrations/openclaw",
|
||||
"integrations/claude-code",
|
||||
"integrations/opencode",
|
||||
"integrations/codex",
|
||||
"integrations/hermes"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tab": "Plugins"
|
||||
},
|
||||
{
|
||||
"icon": "book-open",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "API Reference",
|
||||
"icon": "unplug",
|
||||
"openapi": "https://api.supermemory.ai/v3/openapi"
|
||||
}
|
||||
],
|
||||
"tab": "API Reference"
|
||||
},
|
||||
{
|
||||
"icon": "flask-conical",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "MemoryBench",
|
||||
"icon": "flask-conical",
|
||||
"pages": [
|
||||
"memorybench/overview",
|
||||
"memorybench/github",
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"pages": ["memorybench/installation", "memorybench/quickstart"]
|
||||
},
|
||||
{
|
||||
"group": "Development",
|
||||
"group": "Supermemory MCP",
|
||||
"icon": "terminal",
|
||||
"pages": [
|
||||
"memorybench/architecture",
|
||||
"memorybench/extend-provider",
|
||||
"memorybench/extend-benchmark",
|
||||
"memorybench/contributing"
|
||||
"supermemory-mcp/mcp",
|
||||
"supermemory-mcp/setup",
|
||||
{
|
||||
"group": "Setups",
|
||||
"icon": "layers",
|
||||
"pages": ["supermemory-mcp/claude-desktop"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Reference",
|
||||
"group": "Plugins",
|
||||
"icon": "puzzle",
|
||||
"pages": [
|
||||
"memorybench/memscore",
|
||||
"memorybench/cli",
|
||||
"memorybench/integrations"
|
||||
"integrations/openclaw",
|
||||
"integrations/claude-code",
|
||||
"integrations/opencode",
|
||||
"integrations/codex",
|
||||
"integrations/hermes"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tab": "MemoryBench"
|
||||
"tab": "Plugins and MCP"
|
||||
},
|
||||
{
|
||||
"icon": "chef-hat",
|
||||
"anchors": [
|
||||
"tab": "Company Brain",
|
||||
"groups": [
|
||||
{
|
||||
"anchor": "Cookbook",
|
||||
"icon": "chef-hat",
|
||||
"group": "Concepts",
|
||||
"pages": [
|
||||
"cookbook/overview",
|
||||
{
|
||||
"group": "Quick Start Recipes",
|
||||
"pages": [
|
||||
"cookbook/personal-assistant",
|
||||
"cookbook/document-qa",
|
||||
"cookbook/customer-support",
|
||||
"cookbook/ai-sdk-integration",
|
||||
"cookbook/perplexity-supermemory",
|
||||
"cookbook/chat-with-gdrive"
|
||||
]
|
||||
}
|
||||
"company-brain/overview",
|
||||
"company-brain/setup",
|
||||
"company-brain/permissions",
|
||||
"company-brain/connectors",
|
||||
"company-brain/automations",
|
||||
"company-brain/outside-slack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "What you can do",
|
||||
"pages": [
|
||||
"company-brain/use-cases/overview",
|
||||
"company-brain/use-cases/support",
|
||||
"company-brain/use-cases/incidents",
|
||||
"company-brain/use-cases/support-escalation",
|
||||
"company-brain/use-cases/meeting-recall",
|
||||
"company-brain/use-cases/knowledge-recall",
|
||||
"company-brain/use-cases/acting-in-tools",
|
||||
"company-brain/use-cases/greeting",
|
||||
"company-brain/use-cases/sandbox-debugging",
|
||||
"company-brain/use-cases/long-horizon-research",
|
||||
"company-brain/use-cases/meeting-scheduling"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tab": "Cookbook"
|
||||
},
|
||||
{
|
||||
"icon": "list-ordered",
|
||||
"anchors": [
|
||||
{
|
||||
"anchor": "Changelog",
|
||||
"pages": ["changelog/overview", "changelog/plugins"]
|
||||
}
|
||||
],
|
||||
"tab": "Changelog"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"redirects": [
|
||||
{
|
||||
"destination": "/changelog/overview",
|
||||
"destination": "/agents-and-mcp",
|
||||
"permanent": true,
|
||||
"source": "/vibe-coding"
|
||||
},
|
||||
{
|
||||
"destination": "/overview/what-is-supermemory",
|
||||
"permanent": true,
|
||||
"source": "/intro"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/changelog/developer-platform"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/changelog/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/changelog/plugins"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/openclaw",
|
||||
"permanent": true,
|
||||
"source": "/integrations/clawdbot"
|
||||
},
|
||||
{
|
||||
"destination": "/intro",
|
||||
"permanent": false,
|
||||
"source": "/"
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/introduction"
|
||||
},
|
||||
{
|
||||
"destination": "/concepts/how-it-works",
|
||||
|
|
@ -425,62 +551,62 @@
|
|||
"source": "/search/filtering"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/add-memories/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/add-memories/parameters"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/ingesting"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/add-memories/examples/basic"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/add-memories/examples/file-upload"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/parameters"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/response-schema"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/query-rewriting"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/reranking"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/examples/document-search"
|
||||
},
|
||||
{
|
||||
"destination": "/search",
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search/examples/memory-search"
|
||||
},
|
||||
|
|
@ -490,12 +616,12 @@
|
|||
"source": "/user-profiles/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/user-profiles",
|
||||
"destination": "/recall/user-profiles",
|
||||
"permanent": true,
|
||||
"source": "/user-profiles/api"
|
||||
},
|
||||
{
|
||||
"destination": "/user-profiles",
|
||||
"destination": "/recall/user-profiles",
|
||||
"permanent": true,
|
||||
"source": "/user-profiles/examples"
|
||||
},
|
||||
|
|
@ -505,37 +631,37 @@
|
|||
"source": "/user-profiles/use-cases"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/update-delete-memories/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/track-progress"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/list-memories/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/list-memories/examples/basic"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/list-memories/examples/filtering"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/list-memories/examples/pagination"
|
||||
},
|
||||
{
|
||||
"destination": "/document-operations",
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/list-memories/examples/monitoring"
|
||||
},
|
||||
|
|
@ -545,13 +671,288 @@
|
|||
"source": "/org-settings"
|
||||
},
|
||||
{
|
||||
"destination": "/add-memories",
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/ai-sdk/examples"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/ai-sdk/npm"
|
||||
},
|
||||
{
|
||||
"destination": "/connectors/overview",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/connectors/advanced/bring-your-own-key"
|
||||
},
|
||||
{
|
||||
"destination": "/connectors/overview",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/connectors/creating-connection"
|
||||
},
|
||||
{
|
||||
"destination": "/connectors/overview",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/connectors/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/connectors/google-drive",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/connectors/google-drive"
|
||||
},
|
||||
{
|
||||
"destination": "/connectors/managing-resources",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/connectors/managing-resources"
|
||||
},
|
||||
{
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/creation/adding-memories"
|
||||
},
|
||||
{
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/creation/status"
|
||||
},
|
||||
{
|
||||
"destination": "/concepts/content-types",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/features/auto-multi-modal"
|
||||
},
|
||||
{
|
||||
"destination": "/concepts/customization",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/features/content-cleaner"
|
||||
},
|
||||
{
|
||||
"destination": "/concepts/filtering",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/features/filtering"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/features/query-rewriting"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/features/reranking"
|
||||
},
|
||||
{
|
||||
"destination": "/overview/what-is-supermemory",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/introduction"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/claude-memory",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/sdks/anthropic-claude-memory"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/supermemory-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/sdks/python"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/supermemory-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/sdks/typescript"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/supermemory-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/sdks/supermemory-npm"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/supermemory-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/sdks/supermemory-pypi"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/memory-api/searching/searching-memories"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/memory-graph",
|
||||
"permanent": true,
|
||||
"source": "/memory-graph/npm"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-router/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-router/usage"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/memory-router/with-memory-api"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/model-enhancement/context-extender"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/model-enhancement/getting-started"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/ai-sdk",
|
||||
"permanent": true,
|
||||
"source": "/model-enhancement/identifying-users"
|
||||
},
|
||||
{
|
||||
"destination": "/integrations/openai",
|
||||
"permanent": true,
|
||||
"source": "/openai-sdks/usage"
|
||||
},
|
||||
{
|
||||
"destination": "/overview/comparison",
|
||||
"permanent": true,
|
||||
"source": "/overview/why-supermemory"
|
||||
},
|
||||
{
|
||||
"destination": "/supermemory-mcp/mcp",
|
||||
"permanent": true,
|
||||
"source": "/supermemory-mcp/introduction"
|
||||
},
|
||||
{
|
||||
"destination": "/supermemory-mcp/mcp",
|
||||
"permanent": true,
|
||||
"source": "/supermemory-mcp/technology"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/overview"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/document-qa"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/ai-sdk-integration"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/customer-support"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/personal-assistant"
|
||||
},
|
||||
{
|
||||
"destination": "https://supermemory.ai/blog/building-an-ai-compliance-chatbot-with-supermemory-and-google-drive/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/chat-with-gdrive"
|
||||
},
|
||||
{
|
||||
"destination": "https://supermemory.ai/blog/extending-context-windows-in-llms/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/inf-chat-blog"
|
||||
},
|
||||
{
|
||||
"destination": "https://supermemory.ai/blog/build-your-own-perplexity-in-15-minutes-with-supermemory/",
|
||||
"permanent": true,
|
||||
"source": "/cookbook/perplexity-supermemory"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/architecture"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/cli"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/contributing"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/github"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/installation"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/integrations"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/quickstart"
|
||||
},
|
||||
{
|
||||
"destination": "/",
|
||||
"permanent": true,
|
||||
"source": "/memorybench/supported-models"
|
||||
},
|
||||
{
|
||||
"destination": "/ingestion/add-memories",
|
||||
"permanent": true,
|
||||
"source": "/add-memories"
|
||||
},
|
||||
{
|
||||
"destination": "/ingestion/document-operations",
|
||||
"permanent": true,
|
||||
"source": "/document-operations"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/search",
|
||||
"permanent": true,
|
||||
"source": "/search"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/user-profiles",
|
||||
"permanent": true,
|
||||
"source": "/user-profiles"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/memory-operations",
|
||||
"permanent": true,
|
||||
"source": "/memory-operations"
|
||||
},
|
||||
{
|
||||
"destination": "/recall/memory-review",
|
||||
"permanent": true,
|
||||
"source": "/memory-review"
|
||||
},
|
||||
{
|
||||
"destination": "/overview/analytics",
|
||||
"permanent": true,
|
||||
"source": "/analytics"
|
||||
}
|
||||
],
|
||||
"styling": {
|
||||
"eyebrows": "breadcrumbs"
|
||||
},
|
||||
"theme": "mint"
|
||||
"theme": "aspen"
|
||||
}
|
||||
|
|
|
|||
BIN
apps/docs/images/building-blocks/brain-head.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
74
apps/docs/images/building-blocks/connectors.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg width="1196" height="845" viewBox="0 0 1196 845" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1195.28 458.279V502.485L1145.47 533.716L1139.47 556.498L966.245 661.353V596.817L1195.28 458.279Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1195.28 458.279L966.245 596.817L737.212 735.356L368.841 603.276L0.46875 471.196L217.323 349.186L434.178 227.176L814.727 342.727L1195.28 458.279Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M737.212 804.908V844.485L0.46875 573.3V471.196L368.841 603.276L737.212 735.356V765.331L458.065 665.569V703.507L737.212 804.908Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M941.421 678.215L737.212 804.908V765.331L941.421 641.682V678.215Z" fill="#0049AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M458.065 665.569L737.212 765.331V804.908L458.065 703.507V665.569Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1145.47 533.716L1195.28 502.485V522.716V560.186L737.212 844.485V804.908L941.421 678.215V641.682L737.212 765.331V735.356L966.245 596.817V661.353L1139.47 556.498L1145.47 533.716Z" fill="#E4E4E5"/>
|
||||
<path d="M217.323 349.186L434.178 227.176L814.727 342.727L1195.28 458.279V502.485M1195.28 458.279L966.245 596.817M1195.28 502.485L1145.47 533.716L1139.47 556.498L966.245 661.353V596.817M217.323 349.186L0.46875 471.196V573.3L737.212 844.485L1195.28 560.186V522.716V502.485M966.245 596.817L737.212 735.356M966.245 596.817L591.784 473.001M0.46875 471.196L368.841 603.276L737.212 735.356M737.212 735.356V765.331M368.841 603.276L591.784 473.001M217.323 349.186L550.333 459.296L591.784 473.001M814.727 342.727L591.784 473.001M737.212 804.908V844.485M737.212 804.908L458.065 703.507V665.569L737.212 765.331M737.212 804.908L941.421 678.215V641.682L737.212 765.331M737.212 804.908V765.331" stroke="black" stroke-width="0.936737"/>
|
||||
<path d="M697.991 296.884L690.396 293.756V266.951L697.991 265.164V270.078V296.884Z" fill="#0263EF"/>
|
||||
<path d="M690.396 266.951V293.756L697.991 296.884V265.164L690.396 266.951ZM690.396 266.951L697.991 270.078" stroke="black" stroke-width="0.625454"/>
|
||||
<path d="M697.991 345.204L690.396 342.077V315.271L697.991 313.484V318.399V345.204Z" fill="#0263EF"/>
|
||||
<path d="M690.396 315.271V342.077L697.991 345.204V313.484L690.396 315.271ZM690.396 315.271L697.991 318.399" stroke="black" stroke-width="0.625454"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M854.565 150.797L696.596 233.658V485.147L646.686 512.768V541.115V569.462L786.241 616.949V561.709L835.182 533.941L856.503 521.844L991.212 445.413L938.879 428.938V447.351L786.241 536.027V262.732L938.879 178.902L854.565 150.797ZM907.383 235.111L820.161 285.022V319.669V481.529L907.383 429.165V271.42V235.111Z" fill="white"/>
|
||||
<path d="M907.383 235.111L820.161 285.022V319.669V481.529L907.383 429.165V271.42V235.111Z" fill="#E4E4E5"/>
|
||||
<path d="M760.074 296.248L718.402 283.083V472.064L760.074 487.086V296.248Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M588.538 573.338L646.686 541.115V569.462L786.241 616.949L835.182 588.14L856.503 575.589L991.212 496.292V467.703L1052.27 488.539L786.241 643.6L588.538 573.338Z" fill="white"/>
|
||||
<path d="M856.503 521.844L991.212 445.413V467.703V496.292L856.503 575.589L835.182 588.14L786.241 616.949V561.709L835.182 533.941L856.503 521.844Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M786.241 684.304V643.6L1052.27 488.539V528.274L786.241 684.304Z" fill="#0049AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M786.241 262.732L938.879 178.902V428.938V447.351L786.241 536.027V262.732ZM820.161 285.022L907.383 235.111V271.42V429.165L820.161 481.529V319.669V285.022Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M588.538 573.338L786.241 643.6V684.304L588.538 612.104V573.338Z" fill="#0263EF"/>
|
||||
<path d="M696.596 485.147V233.658L854.565 150.797L938.879 178.902V428.938M696.596 233.658L786.241 262.732M646.686 541.115V512.768L696.596 485.147M938.879 428.938V447.351L786.241 536.027L696.596 503.076V485.147M646.686 512.768L786.241 561.709M991.212 467.703V496.292L856.503 575.589L835.182 588.14L786.241 616.949L646.686 569.462V541.115M991.212 467.703L1052.27 488.539V528.274L786.241 684.304L588.538 612.104V573.338L646.686 541.115M786.241 616.949V561.709M786.241 561.709L835.182 533.941L856.503 521.844L991.212 445.413M991.212 467.703V445.413L938.879 428.938M786.241 536.027V262.732M786.241 262.732L938.879 178.902M588.538 573.338L786.241 643.6M1052.27 488.539L786.241 643.6M786.241 643.6V684.304M820.161 319.669V285.022L907.383 235.111V271.42M820.161 319.669V481.529L907.383 429.165V271.42M820.161 319.669L907.383 271.42M820.16 355.41L907.382 307.16M820.16 391.15L907.382 342.901M820.16 424.21L907.382 375.96M760.074 296.248L718.402 283.083V472.064L760.074 487.086V296.248Z" stroke="black" stroke-width="0.625454"/>
|
||||
<circle cx="5.80779" cy="5.80779" r="5.45039" transform="matrix(0.866025 -0.5 0 1 830.678 439.84)" fill="#0263EF" stroke="black" stroke-width="0.714805"/>
|
||||
<circle cx="5.80779" cy="5.80779" r="5.45039" transform="matrix(0.866025 -0.5 0 1 845.381 431.352)" fill="#0263EF" stroke="black" stroke-width="0.714805"/>
|
||||
<circle cx="5.80779" cy="5.80779" r="5.45039" transform="matrix(0.866025 -0.5 0 1 860.082 422.863)" fill="#0263EF" stroke="black" stroke-width="0.714805"/>
|
||||
<circle cx="5.80779" cy="5.80779" r="5.45039" transform="matrix(0.866025 -0.5 0 1 874.785 414.375)" fill="#0263EF" stroke="black" stroke-width="0.714805"/>
|
||||
<circle cx="5.80779" cy="5.80779" r="5.45039" transform="matrix(0.866025 -0.5 0 1 889.486 405.887)" fill="#0263EF" stroke="black" stroke-width="0.714805"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M260.434 76.8792L406.075 0.484375L483.81 26.3961L343.083 103.684V355.653L483.81 273.897V256.921L532.059 272.11L407.862 342.577V392.128L532.059 319.019V292.661L588.35 311.871L343.083 454.832L160.808 390.053L214.418 360.344V334.209L260.434 308.744V76.8792ZM343.083 379.331V430.261L388.205 403.7V353.73L343.083 379.331Z" fill="white"/>
|
||||
<path d="M343.083 492.359V454.832L588.35 311.871V348.505L343.083 492.359Z" fill="#0049AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M532.059 272.11V292.661V319.019L407.862 392.128V342.577L532.059 272.11Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M160.808 390.053L343.083 454.832V492.359L160.808 425.793V390.053Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M343.083 430.261V379.331L388.205 353.73V403.7L343.083 430.261Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M483.81 256.921V273.897L343.083 355.653V103.684L483.81 26.3961V256.921ZM374.356 124.235L454.771 78.2194V259.601L374.356 302.936V124.235Z" fill="#E4E4E5"/>
|
||||
<path d="M454.771 78.2194L374.356 124.235V302.936L454.771 259.601V78.2194Z" fill="#E4E4E5"/>
|
||||
<path d="M260.434 308.744V76.8792L406.075 0.484375L483.81 26.3961V256.921M260.434 76.8792L343.083 103.684M483.81 26.3961L343.083 103.684M343.083 103.684V355.653M260.434 308.744V325.274L343.083 355.653L483.81 273.897V256.921M532.059 292.661V272.11L483.81 256.921M532.059 272.11L407.862 342.577M407.862 342.577V392.128M407.862 342.577L388.205 353.73M407.862 392.128L532.059 319.019V292.661M214.418 360.344V386.479L343.083 430.261L388.205 403.7L407.862 392.128M214.418 360.344L160.808 390.053V425.793L343.083 492.359L588.35 348.505V311.871L532.059 292.661M588.35 311.871L343.083 454.832M343.083 454.832L160.808 390.053M343.083 454.832V492.359M260.434 308.744L214.418 334.209V360.344M214.418 334.209L343.083 379.331M343.083 379.331V430.261M343.083 379.331L388.205 353.73M388.205 403.7V353.73M374.356 124.235L454.771 78.2194V259.601L374.356 302.936V124.235Z" stroke="black" stroke-width="0.893506"/>
|
||||
<path d="M281.431 116.641L318.958 129.15V313.212L281.431 299.363L281.431 116.641Z" fill="#0263EF"/>
|
||||
<path d="M281.431 116.641L318.958 129.15V313.212L281.431 299.363L281.431 116.641Z" stroke="black" stroke-width="0.893506"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.648 364.181L402.602 360.264V368.849L395.648 373.195V364.181Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.648 364.181V373.195L393.287 372.122V362.893L395.648 364.181Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M402.602 360.264L395.648 364.181L393.287 362.893L400.455 358.977L402.602 360.264Z" fill="#0263EF"/>
|
||||
<path d="M400.541 358.833L402.687 360.121L402.768 360.17V368.942L402.69 368.992L395.736 373.338L395.66 373.385L395.578 373.348L393.217 372.275L393.119 372.23V362.799L400.455 358.781L400.541 358.833ZM393.454 362.988V372.014L395.634 373.006L402.434 368.756V360.359L400.455 359.172L393.454 362.988Z" fill="black"/>
|
||||
<path d="M312.607 282.949L303.454 278.874V270.164L300.496 268.848V278.297C300.496 279.301 300.858 280.426 301.501 281.423L308.975 293.001L311.067 291.624L305.546 283.072L312.609 286.216V282.952L312.607 282.949Z" fill="white"/>
|
||||
<path d="M289.486 267.956L295.006 276.508L287.943 273.363V276.628L297.097 280.703V289.413L300.054 290.729V281.28C300.054 280.276 299.692 279.151 299.049 278.154L291.577 266.579L289.486 267.956Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.648 381.158L402.602 377.241V385.826L395.648 390.172V381.158Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.648 381.158V390.172L393.287 389.099V379.87L395.648 381.158Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M402.602 377.241L395.648 381.158L393.287 379.87L400.455 375.953L402.602 377.241Z" fill="#0263EF"/>
|
||||
<path d="M400.541 375.81L402.687 377.098L402.768 377.146V385.919L402.69 385.968L395.736 390.314L395.66 390.362L395.578 390.325L393.217 389.251L393.119 389.207V379.775L400.455 375.758L400.541 375.81ZM393.454 379.964V388.991L395.634 389.982L402.434 385.733V377.335L400.455 376.148L393.454 379.964Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 134.751V161.613L411.165 153.058V126.574L395.083 134.751Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 134.751L411.165 126.574L404.164 124.682L388.651 133.006L395.083 134.751Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 161.613V134.751L388.651 133.006V160.1L395.083 161.613Z" fill="#0263EF"/>
|
||||
<path d="M395.083 134.751V161.613M395.083 134.751L411.165 126.574M395.083 134.751L388.651 133.006M388.651 133.006L404.164 124.682L411.165 126.574V153.058L395.083 161.613L388.651 160.1V133.006Z" stroke="black" stroke-width="0.529686"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 182.551V209.414L411.165 200.859V174.375L395.083 182.551Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 182.551L411.165 174.375L404.164 172.483L388.651 180.807L395.083 182.551Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.083 209.414V182.551L388.651 180.807V207.901L395.083 209.414Z" fill="#0263EF"/>
|
||||
<path d="M395.083 182.551V209.414M395.083 182.551L411.165 174.375M395.083 182.551L388.651 180.807M388.651 180.807L404.164 172.483L411.165 174.375V200.859L395.083 209.414L388.651 207.901V180.807Z" stroke="black" stroke-width="0.529686"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M428.143 116.88L421.711 115.135V142.229L428.143 143.742V116.88Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M421.711 115.135L428.143 116.88L444.225 108.703L437.223 106.811L421.711 115.135Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M428.143 116.88V143.742L444.225 135.187V108.703L428.143 116.88Z" fill="white"/>
|
||||
<path d="M428.143 116.88L421.711 115.135M428.143 116.88V143.742M428.143 116.88L444.225 108.703M444.225 108.703V135.187L428.143 143.742L421.711 142.229V115.135L437.223 106.811L444.225 108.703Z" stroke="black" stroke-width="0.529686"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M430.901 164.551L424.469 162.807V189.901L430.901 191.414V164.551Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M424.469 162.807L430.901 164.551L446.983 156.375L439.981 154.483L424.469 162.807Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M430.901 164.551V191.414L446.983 182.859V156.375L430.901 164.551Z" fill="white"/>
|
||||
<path d="M430.901 164.551L424.469 162.807M430.901 164.551V191.414M430.901 164.551L446.983 156.375M446.983 156.375V182.859L430.901 191.414L424.469 189.901V162.807L439.981 154.483L446.983 156.375Z" stroke="black" stroke-width="0.529686"/>
|
||||
<path d="M565.974 273.576C499.301 259.662 420.295 158.892 405.543 140.067C404.801 139.121 401.785 139.711 400.924 141.931C400.166 143.885 401.091 145.697 402.244 147.046C408.373 154.226 424.684 178.1 437.896 191.876C463.745 218.828 478.45 234.609 506.88 253.453C530.257 268.947 543.848 278.393 568.941 282.832C591.688 286.857 603.209 287.453 625.338 288.435L626.056 288.467C646.763 289.386 679.71 289.272 690.589 286.857V273.978C675.78 276.894 622.375 285.346 565.974 273.576Z" fill="#24E9FF" stroke="black" stroke-width="0.536104"/>
|
||||
<path d="M565.974 321.38C499.301 307.467 420.295 206.697 405.543 187.872C404.801 186.925 401.785 187.516 400.924 189.736C400.166 191.69 401.091 193.501 402.244 194.851C408.373 202.03 424.684 225.905 437.896 239.681C463.745 266.632 478.45 282.414 506.88 301.257C530.257 316.752 543.848 326.198 568.941 330.637C591.688 334.661 603.209 335.257 625.338 336.239L626.056 336.271C646.763 337.191 679.71 337.076 690.589 334.661V321.783C675.78 324.699 622.375 333.15 565.974 321.38Z" fill="#24E9FF" stroke="black" stroke-width="0.536104"/>
|
||||
<path d="M592.539 251.641C529.137 238.017 452.225 140.264 438.197 121.832C437.325 120.686 434.275 121.55 433.456 123.723C432.735 125.636 433.964 127.344 435.059 128.665C440.888 135.695 458.18 158.154 470.745 171.644C495.325 198.033 509.309 213.486 536.344 231.937C558.574 247.109 571.499 256.357 595.36 260.704C616.992 264.645 627.948 263.652 648.99 264.614L649.674 264.645C669.601 263.165 686.118 259.618 696.463 257.254V247.306C682.381 250.161 646.173 263.165 592.539 251.641Z" fill="#24E9FF" stroke="black" stroke-width="0.536104"/>
|
||||
<path d="M594.211 303.966C531.827 289.803 456.149 188.176 442.346 169.014C441.469 168.486 438.487 168.72 437.681 170.98C436.971 172.969 437.39 174.112 438.469 175.486C444.204 182.794 462.008 206.776 474.371 220.8C498.557 248.235 512.317 264.3 538.918 283.482C560.791 299.255 573.509 308.87 596.988 313.389C618.272 317.486 629.052 316.454 649.757 317.454L650.43 317.486C670.038 315.947 686.289 312.26 696.469 309.802V299.46C682.612 302.428 646.985 315.948 594.211 303.966Z" fill="#24E9FF" stroke="black" stroke-width="0.527503"/>
|
||||
<path d="M843.532 285.719L829.48 294.149V300.238L843.532 291.808V285.719Z" fill="#0263EF" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M843.532 320.848L829.48 329.278V335.367L843.532 326.936V320.848Z" fill="#0263EF" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M843.532 356.445L829.48 364.876V370.965L843.532 362.534V356.445Z" fill="#0263EF" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M843.532 392.039L829.48 400.47V406.558L843.532 398.128V392.039Z" fill="#0263EF" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M555.953 346.403V352.492L562.51 348.483V342.395L555.953 346.403Z" fill="white" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M565.321 340.782V346.871L571.878 342.862V336.773L565.321 340.782Z" fill="white" stroke="black" stroke-width="0.562042"/>
|
||||
<path d="M0.46875 543.325V505.387L140.043 555.268V594.025L0.46875 543.325Z" fill="#0263EF" stroke="black" stroke-width="0.936737"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
71
apps/docs/images/building-blocks/document-retrieval.svg
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<svg width="791" height="747" viewBox="0 0 791 747" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M210.202 541.298L237.517 524.391L249.856 531.709V587.953V610.752L76.3906 503.433V462.453L210.202 541.298Z" fill="#F4F4F7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M283.239 496.453L296.23 504.571L249.73 532.152L237.391 524.834L283.239 496.453Z" fill="#F4F4F7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M131.221 312.128V364.317L119.027 357.182V289.203L323.884 409.678V478.059L320.469 476.064L311.202 470.648V468.697V451.625V437.968V420.409L179.021 340.885L173.168 337.364L152.194 324.746L147.805 322.105L131.221 312.128Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M283.4 499.01L294.131 492.368L386.316 549.664L553.616 451.625L564.834 457.966L386.316 563.321L296.391 507.128L283.4 499.01Z" fill="#E9E9F0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M257.253 182.873L239.99 172.63L327.786 120.245L386.316 85.3223V105.808L257.253 182.873Z" fill="#BDBFC8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 85.3223L449.236 122.009L536.057 172.63L518.391 182.873L386.316 105.808V85.3223Z" fill="#E9E9F0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M89.7619 374.072L106.346 384.803L99.1153 389.193L70.7395 371.34L89.7619 359.684V374.072Z" fill="#E9E9F0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M119.027 357.182L131.221 364.317L147.805 353.661L152.194 350.841L173.168 337.364L179.021 340.885L143.171 363.138L106.346 384.803L89.7619 374.072V359.684V340.056L119.027 357.182Z" fill="#002F73"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M147.805 322.105L152.194 324.746V350.841L147.805 353.661V322.105Z" fill="#1149A3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M152.194 324.746L173.168 337.364L152.194 350.841V324.746Z" fill="#000C1C"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M131.221 364.317V312.128L147.805 322.105V353.661L131.221 364.317Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 259.45L452.353 221.162L550.689 279.846L386.316 380.901L225.845 286.277L327.786 224.722L386.316 259.45Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M536.057 172.63L449.236 122.009L518.391 77.9883L702.868 186.287L564.834 271.15L550.689 279.846L452.353 221.162L518.391 182.873L536.057 172.63Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M239.99 172.63L257.253 182.873L327.786 224.722L225.845 286.277L65.3742 191.653L257.253 77.3417L327.786 120.245L239.99 172.63Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M327.786 120.245L257.253 77.3417L386.316 0.453125L518.391 77.9883L449.236 122.009L386.316 85.3223L327.786 120.245Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M119.027 289.203V357.182L89.7619 340.056L65.3742 325.785V191.653L225.845 286.277L386.316 380.901V514.546L323.884 478.059V409.678L119.027 289.203Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M553.616 410.783L386.316 514.546V380.901L550.689 279.846L564.834 271.15V403.825L553.616 410.783Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M275.108 549.664L386.316 615.023V697.453L275.596 629.655L275.108 549.664Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.7395 371.34L99.1153 389.193L65.3742 409.678V423.336L24.8906 399.436L70.7395 371.34Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M564.834 271.15L702.868 186.287V343.832V375.048L564.834 457.966V403.825V271.15Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M320.469 476.064L323.884 478.059L386.316 514.546L553.616 410.783V451.625L386.316 549.664L294.131 492.368L320.469 476.064Z" fill="#002F73"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M564.834 457.966L553.616 451.625V410.783L564.834 403.825V457.966Z" fill="#BDBFC8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M311.202 420.409V437.968L210.237 497.474L65.3742 409.678L99.1153 389.193L106.346 384.803L143.171 363.138L179.021 340.885L311.202 420.409Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M65.3742 427.238V423.336V409.678L210.237 497.474V514.546L65.3742 427.238Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M65.3742 443.09V427.238L210.237 514.546V530.154L65.3742 443.09Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M311.202 451.625V468.697L210.237 530.154V514.546L311.202 451.625Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M311.202 437.968V451.625L210.237 514.546V497.474L311.202 437.968Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M311.202 470.648L320.469 476.064L294.131 492.368L283.4 499.01L237.551 527.391L210.237 544.298V530.154L311.202 468.697V470.648Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M65.3742 458.942V443.09L210.237 530.154V544.298L76.4252 465.453L65.3742 458.942Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 105.808L518.391 182.873L452.353 221.162L386.316 259.45L327.786 224.722L257.253 182.873L386.316 105.808Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.390625 474.55L386.316 712.953V745.953L0.390625 502.953V474.55Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M275.596 629.655L386.316 697.453L758.472 457.966L762.862 455.04V437.953L789.891 451.625L386.316 712.953L0.390625 474.55L24.8906 461.453L24.8906 474.55L76.4252 506.433L249.891 613.752L275.596 629.655Z" fill="#E9E9F0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 745.953V712.953L789.891 451.625V482.453L386.316 745.953Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 563.321L564.834 457.966L702.868 375.048V343.832L762.862 380.901L386.316 615.023L275.108 549.664L249.891 534.709L237.551 527.391L283.4 499.01L296.391 507.128L386.316 563.321Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M386.316 697.453V615.023L762.862 380.901V437.953V455.04L758.472 457.966L386.316 697.453Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M275.108 549.664L275.596 629.655L249.891 613.752L76.4252 506.433L24.8906 474.55L24.8906 461.453L24.8906 399.436L65.3742 423.336V427.238V443.09V458.942L76.4252 465.453L210.237 544.298L237.551 527.391L249.891 534.709L275.108 549.664Z" fill="white"/>
|
||||
<path d="M131.221 364.317V312.128L147.805 322.105M147.805 353.661L131.221 364.317L119.027 357.182M119.027 357.182V289.203L323.884 409.678V478.059M119.027 357.182L89.7619 340.056M564.834 403.825L553.616 410.783L386.316 514.546L323.884 478.059L320.469 476.064L311.202 470.648V468.697M283.4 499.01L294.131 492.368L320.469 476.064M311.202 468.697V451.625M311.202 468.697L210.237 530.154M311.202 451.625V437.968M311.202 451.625L210.237 514.546M311.202 437.968V420.409L179.021 340.885M311.202 437.968L210.237 497.474M147.805 322.105L152.194 324.746L173.168 337.364L179.021 340.885M179.021 340.885L143.171 363.138L106.346 384.803M147.805 353.661L152.194 350.841L173.168 337.364M152.194 324.746V350.841M147.805 322.105V353.661M702.868 343.832C702.868 353.654 702.868 363.986 702.868 375.048L564.834 457.966L386.316 563.321L296.391 507.128L283.4 499.01M283.4 499.01L237.551 527.391M294.131 492.368L386.316 549.664L553.616 451.625M553.616 451.625L564.834 457.966M553.616 451.625V410.783M564.834 457.966V403.825M452.353 221.162L386.316 259.45L327.786 224.722L257.253 182.873L239.99 172.63L327.786 120.245L386.316 85.3223L449.236 122.009L536.057 172.63L518.391 182.873M257.253 182.873L386.316 105.808M327.786 120.245L257.253 77.3417M386.316 85.3223V105.808M386.316 105.808L518.391 182.873M449.236 122.009L518.391 77.9883M518.391 182.873L452.353 221.162M106.346 384.803L89.7619 374.072V359.684M65.3742 423.336V409.678L99.1153 389.193L106.346 384.803M99.1153 389.193L70.7395 371.34M24.8906 461.453L24.8906 399.436L70.7395 371.34L89.7619 359.684M89.7619 359.684V340.056M702.868 343.832V186.287L518.391 77.9883L386.316 0.453125L257.253 77.3417L65.3742 191.653V325.785L89.7619 340.056M452.353 221.162L550.689 279.846M702.868 186.287L564.834 271.15L550.689 279.846L386.316 380.901M65.3742 191.653L225.845 286.277L386.316 380.901M386.316 380.901V514.546M225.845 286.277L327.786 224.722M702.868 186.287C702.868 248.941 702.868 288.199 702.868 343.832M564.834 271.15V403.825M275.108 549.664L386.316 615.023M275.108 549.664L275.596 629.655M275.108 549.664L249.891 534.709L237.551 527.391M386.316 615.023V697.453M386.316 615.023L762.862 380.901M762.862 437.953V455.04L758.472 457.966L386.316 697.453L275.596 629.655L249.891 613.752L76.4252 506.433L24.8906 474.55C24.8906 474.55 24.8906 469.486 24.8906 461.453M65.3742 409.678L210.237 497.474M65.3742 423.336L24.8906 399.436M65.3742 423.336V427.238M24.8906 399.436C24.8906 421.412 24.8906 446.546 24.8906 461.453M702.868 343.832V375.048M762.862 437.953V380.901L702.868 343.832M210.237 497.474V514.546M65.3742 427.238L210.237 514.546M65.3742 427.238V443.09M210.237 514.546V530.154M65.3742 443.09L210.237 530.154M237.551 527.391L210.237 544.298L76.4252 465.453L65.3742 458.942V443.09M210.237 530.154V544.298M0.390625 474.55L386.316 712.953M24.8906 461.453L0.390625 474.55V502.953L386.316 745.953L789.891 482.453V451.625L762.862 437.953M386.316 712.953V745.953M386.316 712.953L789.891 451.625M24.8906 461.453L24.8906 474.55" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M211.213 451.065L195.117 461.795L211.213 471.55L227.309 461.795L211.213 451.065Z" fill="#7EBCFF"/>
|
||||
<path d="M470.367 396.436C470.367 399.13 468.475 402.406 466.143 403.753C463.81 405.1 461.918 404.008 461.918 401.314C461.918 398.62 463.81 395.344 466.143 393.998C468.475 392.651 470.367 393.743 470.367 396.436Z" fill="#0263EF"/>
|
||||
<path d="M498.656 376.926C498.656 379.62 496.765 382.896 494.432 384.243C492.099 385.589 490.208 384.498 490.208 381.804C490.208 379.11 492.099 375.834 494.432 374.487C496.765 373.141 498.656 374.232 498.656 376.926Z" fill="#0263EF"/>
|
||||
<path d="M484.999 386.681C484.999 389.375 483.108 392.651 480.775 393.998C478.442 395.344 476.551 394.253 476.551 391.559C476.551 388.865 478.442 385.589 480.775 384.243C483.108 382.896 484.999 383.987 484.999 386.681Z" fill="#0263EF"/>
|
||||
<path d="M452.249 200.75L414.213 178.79L447.274 159.702L434.985 152.607L399.112 173.318C395.303 175.517 393.148 178.498 393.125 181.598L392.861 217.613L410.314 217.57L410.508 190.971L439.855 207.914L452.249 200.759L452.249 200.75Z" fill="#0263EF"/>
|
||||
<path d="M374.005 134.98L373.811 161.58L344.463 144.636L332.07 151.792L370.106 173.752L337.045 192.84L349.334 199.935L385.206 179.225C389.017 177.025 391.172 174.044 391.194 170.944L391.458 134.938L374.005 134.98Z" fill="#0263EF"/>
|
||||
<path d="M512.313 367.171C512.313 369.865 510.422 373.141 508.089 374.487C505.756 375.834 503.865 374.742 503.865 372.049C503.865 369.355 505.756 366.079 508.089 364.732C510.422 363.385 512.313 364.477 512.313 367.171Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M211.213 451.065L195.117 461.795L211.213 471.55L227.309 461.795L211.213 451.065Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M470.367 396.436C470.367 399.13 468.475 402.406 466.143 403.753C463.81 405.1 461.918 404.008 461.918 401.314C461.918 398.62 463.81 395.344 466.143 393.998C468.475 392.651 470.367 393.743 470.367 396.436Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M498.656 376.926C498.656 379.62 496.765 382.896 494.432 384.243C492.099 385.589 490.208 384.498 490.208 381.804C490.208 379.11 492.099 375.834 494.432 374.487C496.765 373.141 498.656 374.232 498.656 376.926Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M484.999 386.681C484.999 389.375 483.108 392.651 480.775 393.998C478.442 395.344 476.551 394.253 476.551 391.559C476.551 388.865 478.442 385.589 480.775 384.243C483.108 382.896 484.999 383.987 484.999 386.681Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M452.249 200.75L414.213 178.79L447.274 159.702L434.985 152.607L399.112 173.318C395.303 175.517 393.148 178.498 393.125 181.598L392.861 217.613L410.314 217.57L410.508 190.971L439.855 207.914L452.249 200.759L452.249 200.75Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M374.005 134.98L373.811 161.58L344.463 144.636L332.07 151.792L370.106 173.752L337.045 192.84L349.334 199.935L385.206 179.225C389.017 177.025 391.172 174.044 391.194 170.944L391.458 134.938L374.005 134.98Z" stroke="black" stroke-width="0.780406"/>
|
||||
<path d="M170.897 439.373L113.342 402.792H111.391V404.743L168.458 441.324H170.897V439.373Z" fill="#B4D3FF"/>
|
||||
<path d="M205.527 436.447L131.389 390.11H129.438V392.061L203.088 438.398H205.527V436.447Z" fill="#B4D3FF"/>
|
||||
<path d="M253.327 439.373L152.85 376.453H150.899V378.404L250.888 441.324H253.327V439.373Z" fill="#B4D3FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M615.28 288.906L671.28 254.906V354.906L615.28 389.906V288.906Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M615.28 288.906V389.906L609.78 387.406V285.906L615.28 288.906Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M671.28 254.906L615.28 288.906L609.78 285.906L666.28 251.906L671.28 254.906Z" fill="#0263EF"/>
|
||||
<path d="M615.28 288.906L671.28 254.906M615.28 288.906V389.906M615.28 288.906L609.78 285.906M609.78 285.906V387.406L615.28 389.906L671.28 354.906V254.906L666.28 251.906L609.78 285.906Z" stroke="black" stroke-width="0.4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M671.17 239.953L650.011 251.596L645.757 249.245L667.024 237.453L671.17 239.953Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M650.011 251.596L671.17 239.953V251.688L645.391 267.453L650.011 251.596Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M645.757 249.245L650.011 251.596L645.391 267.453L641.391 263.953L645.757 249.245Z" fill="#0263EF"/>
|
||||
<path d="M671.17 239.953L650.011 251.596M645.391 267.453L641.391 263.953L645.757 249.245L667.024 237.453L671.17 239.953V251.688L645.391 267.453ZM650.011 251.596L645.757 249.245M650.011 251.596L645.391 267.453M671.17 251.688L670.98 251.574" stroke="black" stroke-width="0.4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M370.491 621.653L351.601 610.318V621.113L370.491 632.987V621.653Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M370.491 621.653V632.987L373.46 631.637V620.033L370.491 621.653Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M351.601 610.318L370.491 621.653L373.46 620.033L354.3 608.699L351.601 610.318Z" fill="#0263EF"/>
|
||||
<path d="M354.191 608.518L351.493 610.138L351.391 610.199V621.229L351.489 621.291L370.379 633.165L370.475 633.224L370.578 633.178L373.547 631.829L373.67 631.772V619.914L354.3 608.453L354.191 608.518ZM373.249 620.151V631.501L370.507 632.747L351.811 620.995V610.436L354.3 608.944L373.249 620.151Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M347.491 607.653L328.601 596.318V607.113L347.491 618.987V607.653Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M347.491 607.653V618.987L350.46 617.637V606.033L347.491 607.653Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M328.601 596.318L347.491 607.653L350.46 606.033L331.3 594.699L328.601 596.318Z" fill="#0263EF"/>
|
||||
<path d="M331.191 594.518L328.493 596.138L328.391 596.199V607.229L328.489 607.291L347.379 619.165L347.475 619.224L347.578 619.178L350.547 617.829L350.67 617.772V605.914L331.3 594.453L331.191 594.518ZM350.249 606.151V617.501L347.507 618.747L328.811 606.995V596.436L331.3 594.944L350.249 606.151Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
68
apps/docs/images/building-blocks/extractor.svg
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<svg width="691" height="769" viewBox="0 0 691 769" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M357.531 747.071V647.107L523.678 577.477L689.825 507.847V614.015L684.999 615.947L357.531 747.071Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M689.825 507.847L523.678 577.477L432.676 543.696L498.859 514.741V502.331L427.298 477.492L510.924 441.663L689.825 507.847Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M523.678 577.477L357.531 647.107L179.671 583.585L265.15 546.962L357.531 577.477L395.103 560.586L432.676 543.696L523.678 577.477Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M265.15 546.962L179.671 583.585L1.81054 520.064L166.917 447.772L250.756 478.253C250.756 478.253 207.431 496.29 179.671 507.847C179.671 512.423 179.671 519.566 179.671 519.566L265.15 546.962Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M510.924 441.663L427.298 477.492L332.023 444.421L250.756 478.253L166.917 447.772L332.023 375.48L510.924 441.663Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M357.531 647.107V747.071L4.55441 615.556L0.417969 614.015L1.81054 520.064L179.671 583.585L357.531 647.107Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M357.531 747.071L684.999 615.947V630.561L357.531 768.442L4.55441 636.076V615.556L357.531 747.071Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M427.298 477.492L498.859 502.331L483.616 509.172L418.245 538.509L357.531 565.757L280.115 540.551L195.345 512.95L179.671 507.847L250.756 478.253L332.023 444.421L427.298 477.492Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M498.859 514.741L432.676 543.696L395.103 560.586L357.531 577.477V565.757L418.245 538.509L483.616 509.172L498.859 502.331V514.741Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M357.531 577.477L265.15 546.962L179.671 519.566V507.847L195.345 512.95L280.115 540.551L357.531 565.757V577.477Z" fill="white"/>
|
||||
<path d="M357.531 747.071V647.107M4.55441 615.556L357.531 747.071L684.999 615.947M689.825 507.847L523.678 577.477L357.531 647.107M1.81054 520.064L179.671 583.585L357.531 647.107M523.678 577.477L432.676 543.696M510.924 441.663L689.825 507.847V614.015L684.999 615.947M684.999 615.947V630.561L357.531 768.442L4.55441 636.076V615.556M179.671 507.847C179.671 512.423 179.671 519.566 179.671 519.566L265.15 546.962L357.531 577.477L395.103 560.586L432.676 543.696L498.859 514.741V502.331L427.298 477.492M498.859 502.331L483.616 509.172L418.245 538.509L357.531 565.757M427.298 477.492L510.924 441.663M179.671 507.847C207.431 496.29 250.756 478.253 250.756 478.253L332.023 444.421L427.298 477.492M1.81054 520.064L166.917 447.772L332.023 375.48L510.924 441.663M179.671 583.585L265.15 546.962M357.531 577.477V565.757M1.81054 520.064L0.417969 614.015L4.55441 615.556M1.81054 520.064L0.417969 519.566M166.917 447.772L250.756 478.253M179.671 519.566V507.847L250.756 478.253M179.671 507.847L195.345 512.95M357.531 565.757L280.115 540.551L195.345 512.95C195.345 512.95 185.792 509.84 179.671 507.847" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M420.214 166.583L481.363 187.808L468.338 193.653L412.479 218.722L360.599 242.005L294.448 220.466L222.013 196.882L208.619 192.521L269.361 167.233L338.802 138.324L420.214 166.583Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M407.168 321.706V391.46L406.479 391.785L392.704 398.275L360.599 412.708V242.005L412.479 218.722L468.338 193.653L481.363 187.808L407.168 321.706Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M360.599 412.708L283.075 387.101L281.661 386.634V383.753V316.881L208.619 192.521L222.013 196.882L294.448 220.466L360.599 242.005V412.708Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M392.704 398.275L406.479 391.785V394.783L360.599 415.466L283.075 389.958V387.101L360.599 412.708L392.704 398.275Z" fill="#0263EF"/>
|
||||
<path d="M283.075 387.101L360.599 412.708L392.704 398.275L406.479 391.785L407.168 391.46V321.706L481.363 187.808L420.214 166.583L338.802 138.324L269.361 167.233M481.363 187.808L468.338 193.653L412.479 218.722L360.599 242.005M208.619 192.521L222.013 196.882L294.448 220.466L360.599 242.005M360.599 242.005V412.708M222.013 196.882C222.013 196.882 213.85 194.224 208.619 192.521M281.661 316.881C281.661 316.881 208.619 196.432 208.619 192.521L269.361 167.233M283.075 387.101L281.661 386.634V383.753V316.881L208.619 192.521M208.619 192.521C232.34 182.645 269.361 167.233 269.361 167.233M406.479 391.785V394.783L360.599 415.466L283.075 389.958V387.101" stroke="black" stroke-width="0.37277"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M647.08 140.687L521.573 195.597L450.321 227.628L379.07 259.658V237.433L494.207 185.762L618.174 130.127L647.08 117.155V140.687Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M379.07 259.658L203.882 201.792L41.7812 149.839V127.614L71.5066 137.292L232.262 189.633L379.07 237.433V259.658Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M511.374 70.0501L638.898 114.315L379.07 227.628L51.4329 122.127L176.586 71.4933L330.697 7.33547L511.374 70.0501Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M71.5066 137.292L41.7812 127.614V119.019L47.6015 120.894L51.4329 122.127L379.07 227.628V237.433L232.262 189.633L71.5066 137.292Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M494.207 185.762L379.07 237.433V227.628L638.898 114.315L647.08 110.746V117.155L618.174 130.127L494.207 185.762Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M176.586 71.4933L51.4329 122.127L47.6015 120.894L41.7812 119.019L330.697 0.441406V7.33547L176.586 71.4933Z" fill="#BDBFC8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M638.898 114.315L511.374 70.0501L330.697 7.33547V0.441406L647.08 110.746L638.898 114.315Z" fill="#E4E4E5"/>
|
||||
<path d="M41.7812 127.614V149.839L203.882 201.792L379.07 259.658L450.321 227.628L521.573 195.597L647.08 140.687V117.155M379.07 259.658V237.433M379.07 237.433L494.207 185.762L618.174 130.127L647.08 117.155M379.07 237.433L232.262 189.633L71.5066 137.292M379.07 237.433V227.628M41.7812 127.614V119.019L330.697 0.441406L647.08 110.746V117.155M41.7812 149.839C41.7812 149.839 41.7812 136.293 41.7812 127.614M41.7812 127.614L71.5066 137.292M41.7812 127.614C53.3897 131.393 71.5066 137.292 71.5066 137.292M638.898 114.315L511.374 70.0501L330.697 7.33547M647.08 110.746L638.898 114.315L379.07 227.628M41.7812 119.019L47.6015 120.894L51.4329 122.127L379.07 227.628M51.4329 122.127L176.586 71.4933L330.697 7.33547M330.697 7.33547V0.441406" stroke="black" stroke-width="0.827288"/>
|
||||
<path d="M440.258 514.051L416.129 523.703L392 514.051V447.179L416.129 436.148L440.258 447.179V514.051Z" fill="#7EBCFF"/>
|
||||
<path d="M392 447.179L416.129 436.148L440.258 447.179V514.051L416.129 523.703L392 514.051V447.179ZM416.129 523.703V456.831M416.129 456.831L440.258 447.179M416.129 456.831L392 447.179" stroke="black" stroke-width="0.827288"/>
|
||||
<path d="M345.121 484.404L325.817 492.677L312.029 486.473V466.512L330.643 458.207L345.121 463.722V484.404Z" fill="#F67EFF"/>
|
||||
<path d="M312.029 466.512L330.643 458.207L345.121 463.722V484.404L325.817 492.677L312.029 486.473V466.512ZM325.817 492.677V472.685M325.817 472.685L345.121 463.722M325.817 472.685L312.029 466.512" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M466.457 110.057L365.803 159.005L229.301 114.194L330.644 62.4883L466.457 110.057Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M365.803 159.005V172.104L229.301 127.292V114.194L365.803 159.005Z" fill="#F67EFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M365.803 159.005L466.457 110.057V123.845L365.803 172.104V159.005Z" fill="#E4E4E5"/>
|
||||
<path d="M466.457 110.057L365.803 159.005M365.803 172.104L229.301 127.292V114.194L330.644 62.4883L466.457 110.057V123.845L365.803 172.104ZM365.803 159.005L229.301 114.194M365.803 159.005V172.104" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M462.321 104.542L361.668 153.49L225.165 108.678L326.508 56.9727L462.321 104.542Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M361.668 153.49V166.588L225.165 121.777V108.678L361.668 153.49Z" fill="#EFC702"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M361.668 153.49L462.321 104.542V118.33L361.668 166.588V153.49Z" fill="#E4E4E5"/>
|
||||
<path d="M462.321 104.542L361.668 153.49M361.668 166.588L225.165 121.777V108.678L326.508 56.9727L462.321 104.542V118.33L361.668 166.588ZM361.668 153.49L225.165 108.678M361.668 153.49V166.588" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M471.971 96.2683L371.318 145.216L234.815 100.405L336.158 48.6992L471.971 96.2683Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M371.318 145.216V158.315L234.815 113.503V100.405L371.318 145.216Z" fill="#7EE3FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M371.318 145.216L471.971 96.2683V110.056L371.318 158.315V145.216Z" fill="#E4E4E5"/>
|
||||
<path d="M471.971 96.2683L371.318 145.216M371.318 158.315L234.815 113.503V100.405L336.158 48.6992L471.971 96.2683V110.056L371.318 158.315ZM371.318 145.216L234.815 100.405M371.318 145.216V158.315" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M466.457 68.6901L365.803 117.638L229.301 72.8266L330.644 21.1211L466.457 68.6901Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M365.803 117.638V130.737L229.301 85.9253V72.8266L365.803 117.638Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M365.803 117.638L466.457 68.6901V82.4783L365.803 130.737V117.638Z" fill="#E4E4E5"/>
|
||||
<path d="M466.457 68.6901L365.803 117.638M365.803 130.737L229.301 85.9253V72.8266L330.644 21.1211L466.457 68.6901V82.4783L365.803 130.737ZM365.803 117.638L229.301 72.8266M365.803 117.638V130.737" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M481.624 68.6901L380.97 117.638L244.468 72.8266L345.811 21.1211L481.624 68.6901Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M380.97 117.638V130.737L244.468 85.9253V72.8266L380.97 117.638Z" fill="#7EBCFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M380.97 117.638L481.624 68.6901V82.4783L380.97 130.737V117.638Z" fill="#E4E4E5"/>
|
||||
<path d="M481.624 68.6901L380.97 117.638M380.97 130.737L244.468 85.9253V72.8266L345.811 21.1211L481.624 68.6901V82.4783L380.97 130.737ZM380.97 117.638L244.468 72.8266M380.97 117.638V130.737" stroke="black" stroke-width="0.827288"/>
|
||||
<path d="M261.014 475.442L289.969 462.344L323.06 477.511V510.602L292.726 524.39L261.014 510.602V475.442Z" fill="#EFC802"/>
|
||||
<path d="M292.726 524.39L323.06 510.602V477.511L289.969 462.344L261.014 475.442V510.602L292.726 524.39ZM261.014 475.442L292.726 489.92M323.06 477.511L292.726 489.92M292.726 489.92V524.39" stroke="black" stroke-width="0.827288"/>
|
||||
<path d="M389.242 479.579L360.287 466.48L299.619 495.436V528.527L329.953 542.315L389.242 514.739V479.579Z" fill="#0263EF"/>
|
||||
<path d="M329.953 542.315L299.619 528.527V495.436L360.287 466.48L389.242 479.579V514.739L329.953 542.315ZM389.242 479.579L329.953 507.845M299.619 495.436L329.953 507.845M329.953 507.845V542.315" stroke="black" stroke-width="0.827288"/>
|
||||
<path d="M383.728 488.167L365.114 495.434L346.5 488.167V456.86L365.114 448.555L383.728 456.86V488.167Z" fill="#7EE3FF"/>
|
||||
<path d="M346.5 456.86L365.114 448.555L383.728 456.86V488.167L365.114 495.434L346.5 488.167V456.86ZM365.114 495.434V464.127M365.114 464.127L383.728 456.86M365.114 464.127L346.5 456.86" stroke="black" stroke-width="0.827288"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M290.047 669.189L272.468 663.367V685.736L290.047 692.676V669.189Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M290.047 669.189V692.676L296.016 688.392V665.364L290.047 669.189Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M272.468 663.367L290.047 669.189L296.016 665.364L277.894 658.659L272.468 663.367Z" fill="#0263EF"/>
|
||||
<path d="M277.675 658.341L272.249 663.049L272.044 663.227V686.084L272.242 686.163L289.821 693.103L290.014 693.179L290.221 693.031L296.19 688.747L296.438 688.568V665.01L277.893 658.151L277.675 658.341ZM295.592 665.629V688.217L290.079 692.174L272.89 685.388V663.509L277.893 659.168L295.592 665.629Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M320.666 680.052L303.087 674.23V696.599L320.666 703.539V680.052Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M320.666 680.052V703.539L326.635 699.255V676.228L320.666 680.052Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M303.087 674.23L320.666 680.052L326.635 676.228L308.513 669.522L303.087 674.23Z" fill="#0263EF"/>
|
||||
<path d="M308.295 669.204L302.869 673.912L302.663 674.09V696.947L302.861 697.026L320.441 703.967L320.633 704.042L320.84 703.894L326.809 699.61L327.057 699.431V675.873L308.512 669.014L308.295 669.204ZM326.211 676.492V699.08L320.698 703.037L303.509 696.251V674.372L308.512 670.031L326.211 676.492Z" fill="black"/>
|
||||
<path d="M67.1047 590.026L50.5425 582.652V566.894L45.1914 564.512V581.61C45.1914 583.426 45.8463 585.461 47.0104 587.265L60.5338 608.215L64.3175 605.722L54.3292 590.249L67.1078 595.938V590.031L67.1047 590.026Z" fill="#0263EF"/>
|
||||
<path d="M25.2689 562.904L35.2572 578.377L22.4785 572.688V578.595L39.0407 585.969V601.727L44.3918 604.109V587.011C44.3918 585.195 43.7369 583.16 42.5729 581.357L29.0525 560.411L25.2689 562.904Z" fill="#0263EF"/>
|
||||
<path d="M307.779 68.4922L347.414 46.1438" stroke="#0263EF" stroke-opacity="0.77" stroke-width="4.13644"/>
|
||||
<path d="M320.303 69.0742L349.258 52.9338" stroke="#0263EF" stroke-opacity="0.77" stroke-width="4.13644"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
135
apps/docs/images/building-blocks/file-systems.svg
Normal file
|
After Width: | Height: | Size: 28 KiB |
1
apps/docs/images/building-blocks/hermes.svg
Normal file
|
After Width: | Height: | Size: 19 KiB |
101
apps/docs/images/building-blocks/memory-router.svg
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<svg width="671" height="747" viewBox="0 0 671 747" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.529 191.45L177.261 157.905V184.388L122.529 217.933V191.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.529 191.45V217.933L66.4734 184.388V157.905L122.529 191.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M177.261 157.905L122.529 191.45L66.4734 157.905L122.529 124.359L177.261 157.905Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.529 426.267L177.261 393.163V399.342L122.529 432.888L66.4734 398.46V393.163L122.529 426.267Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M66.4734 184.388L122.529 217.933V426.267L66.4734 393.163V357.411V184.388Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.529 217.933L177.261 184.388V294.226V304.445V393.163L122.529 426.267V217.933Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M169.096 499.978L0.265625 398.46V497.771L337.925 702.574V601.497L169.096 499.978Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M337.925 713.609L0.265625 509.247V540.144L337.925 746.271V713.609Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M551.556 191.45L606.288 157.905V184.388L551.556 217.933V191.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M551.556 191.45V217.933L495.5 184.388V157.905L551.556 191.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M606.288 157.905L551.556 191.45L495.5 157.905L551.556 124.359L606.288 157.905Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M551.556 426.267L606.288 393.163V399.342L551.556 432.888L495.5 398.46V393.163L551.556 426.267Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M495.5 184.388L551.556 217.933V326.946V426.267L495.5 393.163V303.646V293.477V184.388Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M551.556 217.933L606.288 184.388V359.624V393.163L551.556 426.267V326.946V217.933Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M337.925 601.497V702.574L632.33 523.899L641.599 503.509L670.289 485.854V399.342L504.107 500.42L337.925 601.497Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M337.925 713.609L670.289 511.896V543.676L337.925 746.271V713.609Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M337.925 601.497L169.096 499.978L257.152 447.233L337.043 495.123L416.271 446.791L504.107 500.42L337.925 601.497Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.529 432.888L177.261 399.342L257.152 447.233L169.096 499.978L0.265625 398.46L66.4734 357.411V393.163V398.46L122.529 432.888Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M177.261 399.342V393.163V304.445L257.593 350.128L177.261 399.342Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M177.261 304.445V294.226L337.925 199.395L495.5 293.477V303.646L460.41 324.151L416.713 349.687L337.925 300.914L257.593 350.128L177.261 304.445Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M606.288 399.342V393.163V359.624L608.495 360.942L670.289 399.342L504.107 500.42L416.271 446.791L495.5 398.46L551.556 432.888L606.288 399.342Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M495.5 393.163V398.46L416.713 349.687L460.41 324.151L495.5 303.646V393.163Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M337.043 495.123L257.152 447.233L177.261 399.342L257.593 350.128L337.925 300.914L416.713 349.687L495.5 398.46L416.271 446.791L337.043 495.123Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.265625 497.771L337.925 702.574L632.33 523.899L641.599 503.509L670.289 485.854V500.861V511.896L337.925 713.609L0.265625 509.247V497.771Z" fill="#0263EF"/>
|
||||
<path d="M122.529 191.45L177.261 157.905M122.529 191.45V217.933M122.529 191.45L66.4734 157.905M66.4734 184.388V157.905L122.529 124.359L177.261 157.905V184.388M177.261 184.388L122.529 217.933M177.261 184.388V294.226M122.529 217.933L66.4734 184.388M122.529 217.933V426.267M66.4734 184.388V357.411M66.4734 393.163L122.529 426.267L177.261 393.163M177.261 393.163V399.342M177.261 393.163V304.445M177.261 399.342L122.529 432.888L66.4734 398.46V393.163M495.5 398.46L416.271 446.791L337.043 495.123L257.152 447.233L177.261 399.342M177.261 399.342L257.593 350.128M66.4734 393.163V357.411M0.265625 497.771V398.46L66.4734 357.411M177.261 294.226V304.445M177.261 294.226L337.925 199.395L495.5 293.477M177.261 304.445L257.593 350.128M169.096 499.978L0.265625 398.46M169.096 499.978L337.925 601.497M169.096 499.978L257.152 447.233M670.289 485.854L641.599 503.509L632.33 523.899L337.925 702.574L0.265625 497.771M0.265625 497.771V509.247M337.925 702.574V601.497M337.925 601.497L504.107 500.42M337.925 713.609L0.265625 509.247M337.925 713.609V746.271M337.925 713.609L670.289 511.896M670.289 511.896V543.676L337.925 746.271L0.265625 540.144V509.247M551.556 191.45L606.288 157.905M551.556 191.45V217.933M551.556 191.45L495.5 157.905M495.5 184.388V157.905L551.556 124.359L606.288 157.905V184.388M606.288 184.388L551.556 217.933M606.288 184.388V359.624M551.556 217.933L495.5 184.388M551.556 217.933V326.946V426.267M495.5 184.388V293.477M495.5 393.163L551.556 426.267L606.288 393.163M606.288 393.163V399.342L551.556 432.888L495.5 398.46M606.288 393.163V359.624M495.5 398.46V393.163M495.5 398.46L416.713 349.687M495.5 393.163V303.646M495.5 303.646V293.477M495.5 303.646L460.41 324.151L416.713 349.687M670.289 485.854V399.342L608.495 360.942L606.288 359.624M670.289 485.854V500.861V511.896M670.289 399.342L504.107 500.42M504.107 500.42L416.271 446.791M257.593 350.128L337.925 300.914L416.713 349.687" stroke="black" stroke-width="0.529663"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M613.066 460.462L629.742 450.457V459.986L613.066 470.468V460.462Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M613.066 460.462V470.468L610.445 469.276V459.033L613.066 460.462Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M629.742 450.457L613.066 460.462L610.445 459.033L627.359 449.027L629.742 450.457Z" fill="#0263EF"/>
|
||||
<path d="M627.455 448.866L629.837 450.296L629.927 450.35V460.087L629.84 460.141L613.165 470.623L613.08 470.676L612.989 470.635L610.369 469.444L610.26 469.394V458.926L627.359 448.809L627.455 448.866ZM610.631 459.136V469.154L613.051 470.255L629.556 459.88V450.559L627.359 449.242L610.631 459.136Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M635.136 446.337L651.812 436.332V445.861L635.136 456.343V446.337Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M635.136 446.337V456.343L632.516 455.151V444.908L635.136 446.337Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M651.812 436.332L635.136 446.337L632.516 444.908L649.43 434.902L651.812 436.332Z" fill="#0263EF"/>
|
||||
<path d="M649.525 434.741L651.907 436.171L651.998 436.225V445.962L651.911 446.016L635.235 456.498L635.15 456.551L635.059 456.51L632.439 455.319L632.33 455.269V444.801L649.43 434.684L649.525 434.741ZM632.701 445.011V455.029L635.122 456.13L651.626 445.755V436.434L649.43 435.117L632.701 445.011Z" fill="black"/>
|
||||
<circle cx="9.38022" cy="9.38022" r="9.07125" transform="matrix(-0.866025 -0.5 0 1 208.6 567.758)" fill="#7EBCFF" stroke="black" stroke-width="0.61794"/>
|
||||
<circle cx="9.38022" cy="9.38022" r="9.07125" transform="matrix(-0.866025 -0.5 0 1 184.854 554.051)" fill="#7EBCFF" stroke="black" stroke-width="0.61794"/>
|
||||
<circle cx="9.38022" cy="9.38022" r="9.07125" transform="matrix(-0.866025 -0.5 0 1 161.107 540.34)" fill="#0263EF" stroke="black" stroke-width="0.61794"/>
|
||||
<circle cx="9.38022" cy="9.38022" r="9.07125" transform="matrix(-0.866025 -0.5 0 1 137.363 526.629)" fill="#0263EF" stroke="black" stroke-width="0.61794"/>
|
||||
<circle cx="9.38022" cy="9.38022" r="9.07125" transform="matrix(-0.866025 -0.5 0 1 113.617 512.922)" fill="#0263EF" stroke="black" stroke-width="0.61794"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.159 67.45L390.891 33.9047V60.3878L336.159 93.9331V67.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.159 67.45V93.9331L280.104 60.3878V33.9047L336.159 67.45Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.159 302.267L390.891 269.163V275.342L336.159 308.888L280.104 274.46V269.163L336.159 302.267Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M280.104 60.3878L336.159 93.9331V302.267L280.104 269.163V230.321V60.3878Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.159 93.9331L390.891 60.3878V269.163L336.159 302.267V93.9331Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M390.891 33.9047L336.159 67.45L280.104 33.9047L336.159 0.359375L390.891 33.9047Z" fill="white"/>
|
||||
<path d="M336.159 67.45L390.891 33.9047M336.159 67.45V93.9331M336.159 67.45L280.104 33.9047M280.104 60.3878V33.9047L336.159 0.359375L390.891 33.9047V60.3878M390.891 60.3878L336.159 93.9331M390.891 60.3878V269.163M336.159 93.9331L280.104 60.3878M336.159 93.9331V302.267M280.104 60.3878V230.321V269.163M280.104 269.163L336.159 302.267L390.891 269.163M390.891 269.163V275.342L336.159 308.888L280.104 274.46V269.163" stroke="black" stroke-width="0.61794"/>
|
||||
<path d="M177.703 210.459V183.976V164.114L299.967 90.4023L317.181 98.7887V126.155L177.703 210.459Z" fill="white"/>
|
||||
<path d="M317.181 98.7887L299.967 90.4023L177.703 164.114V183.976V210.459L317.181 126.155V98.7887ZM177.703 183.976L317.181 98.7887" stroke="black" stroke-width="0.61794"/>
|
||||
<path d="M495.5 210.459V183.976V164.114L373.236 90.4023L356.022 98.7887V126.155L495.5 210.459Z" fill="white"/>
|
||||
<path d="M356.022 98.7887L373.236 90.4023L495.5 164.114V183.976V210.459L356.022 126.155V98.7887ZM495.5 183.976L356.022 98.7887" stroke="black" stroke-width="0.61794"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.855 338.169L412.952 291.527V377.446L336.855 424.088V338.169Z" fill="#E0E1E3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M336.855 338.169V424.088L258.918 377.446V319.479V296.086V291.527L336.855 338.169Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M412.952 291.527L336.855 338.169L258.918 291.527L272.601 283.338L336.855 244.885L412.952 291.527Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M258.918 291.527V296.086L228.904 277.217L198.89 258.347L138.861 220.609L156.075 210.457L272.601 283.338L258.918 291.527Z" fill="white"/>
|
||||
<path d="M258.918 296.086V319.479L138.861 247.533V220.609L198.89 258.347L228.904 277.217L258.918 296.086Z" fill="white"/>
|
||||
<path d="M336.855 338.169L412.952 291.527M336.855 338.169V424.088M336.855 338.169L258.918 291.527M272.601 283.338L336.855 244.885L412.952 291.527V377.446L336.855 424.088L258.918 377.446V319.479M258.918 319.479V296.086M272.601 283.338L156.075 210.457L138.861 220.609V247.533L258.918 319.479M272.601 283.338L258.918 291.527V296.086M258.918 296.086L228.904 277.217L198.89 258.347L138.861 220.609" stroke="black" stroke-width="0.61794"/>
|
||||
<path d="M412.961 296.086V321.245L533.018 247.533V220.609L515.804 210.457L399.278 283.338L412.961 291.527V296.086Z" fill="white"/>
|
||||
<path d="M533.018 220.609L515.804 210.457L399.278 283.338L412.961 291.527V296.086V321.245L533.018 247.533V220.609ZM412.961 296.086L533.018 220.609" stroke="black" stroke-width="0.61794"/>
|
||||
<g filter="url(#filter0_d_6411_8838)">
|
||||
<path d="M366.016 300.868L346.928 289.847L363.52 280.268L357.352 276.707L339.35 287.101C337.438 288.205 336.357 289.701 336.345 291.256L336.213 309.33L344.971 309.309L345.069 295.96L359.797 304.463L366.016 300.872L366.016 300.868Z" fill="#0263EF"/>
|
||||
<path d="M326.75 267.861L326.652 281.21L311.925 272.707L305.705 276.298L324.793 287.319L308.202 296.898L314.369 300.459L332.371 290.065C334.284 288.961 335.365 287.465 335.376 285.91L335.509 267.84L326.75 267.861Z" fill="#0263EF"/>
|
||||
<path d="M366.016 300.868L346.928 289.847L363.52 280.268L357.352 276.707L339.35 287.101C337.438 288.205 336.357 289.701 336.345 291.256L336.213 309.33L344.971 309.309L345.069 295.96L359.797 304.463L366.016 300.872L366.016 300.868Z" stroke="black" stroke-width="0.529663"/>
|
||||
<path d="M326.75 267.861L326.652 281.21L311.925 272.707L305.705 276.298L324.793 287.319L308.202 296.898L314.369 300.459L332.371 290.065C334.284 288.961 335.365 287.465 335.376 285.91L335.509 267.84L326.75 267.861Z" stroke="black" stroke-width="0.529663"/>
|
||||
</g>
|
||||
<path d="M295.902 107.398L295.902 102.04L286.621 102.04" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M282.906 109.543L295.773 102.114" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M251.902 275.184L251.902 280.542L242.621 280.542" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M238.906 273.039L251.773 280.468" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M485.902 162.184L485.902 167.542L476.621 167.542" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M472.906 160.039L485.773 167.468" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M410.906 280.184L410.906 285.542L420.187 285.542" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M423.902 278.039L411.036 285.468" stroke="#0263EF" stroke-width="1.32416" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M140.897 163.637C142.604 163.141 144.109 162.441 145.312 161.583C146.515 160.726 147.388 159.73 147.873 158.663C148.622 157.06 148.471 155.361 147.441 153.811C146.411 152.261 144.555 150.94 142.141 150.037C142.268 148.66 141.766 147.287 140.683 146.057C139.601 144.828 137.977 143.784 135.975 143.031C133.973 142.278 131.664 141.842 129.278 141.768C126.892 141.693 124.514 141.983 122.383 142.606C120.786 141.999 118.983 141.596 117.095 141.422C115.207 141.249 113.276 141.309 111.431 141.6C108.647 142.026 106.17 142.951 104.356 144.243C102.543 145.535 101.488 147.126 101.343 148.787C99.6323 149.28 98.1242 149.979 96.9191 150.836C95.714 151.693 94.8398 152.688 94.355 153.756C93.605 155.36 93.7567 157.06 94.7883 158.611C95.8198 160.163 97.678 161.485 100.095 162.387C99.9832 163.488 100.279 164.591 100.963 165.622C101.646 166.652 102.702 167.587 104.059 168.364C106.096 169.541 108.728 170.315 111.575 170.573C114.423 170.831 117.338 170.56 119.902 169.8C121.499 170.406 123.302 170.81 125.19 170.983C127.078 171.157 129.008 171.096 130.853 170.805C133.622 170.374 136.084 169.449 137.888 168.161C139.691 166.874 140.745 165.291 140.897 163.637ZM106.552 166.925C104.881 165.963 103.849 164.692 103.637 163.335L103.989 163.39L115.956 165.243C116.256 165.287 116.57 165.286 116.868 165.24C117.167 165.193 117.439 165.103 117.66 164.978L128.357 158.802L129.709 161.725C129.717 161.739 129.72 161.753 129.716 161.768C129.712 161.782 129.702 161.796 129.687 161.807L120.823 166.925C118.927 168.015 116.362 168.626 113.687 168.626C111.013 168.626 108.447 168.015 106.552 166.925ZM97.7655 154.288C98.3734 152.97 99.7672 151.818 101.702 151.034L101.792 151.242L105.006 158.156C105.083 158.328 105.239 158.485 105.456 158.611C105.674 158.737 105.946 158.826 106.244 158.871L120.87 161.139L117.168 163.277C117.148 163.287 117.124 163.295 117.098 163.3C117.072 163.305 117.044 163.306 117.017 163.303L104.901 161.425C102.317 161.023 100.115 160.046 98.777 158.708C97.4393 157.37 97.0755 155.78 97.7655 154.288ZM112.29 143.592C114.589 143.24 117.028 143.368 119.179 143.952L110.166 149.156C109.946 149.28 109.787 149.437 109.706 149.608C109.626 149.78 109.626 149.961 109.707 150.132L113.614 158.537L108.553 157.756C108.526 157.751 108.503 157.743 108.483 157.732C108.464 157.72 108.449 157.706 108.44 157.691L105.195 150.71C104.506 149.217 104.869 147.627 106.207 146.289C107.544 144.951 109.745 143.973 112.328 143.57L112.29 143.592ZM132.521 162.34L128.638 153.888L133.685 154.668C133.711 154.673 133.735 154.682 133.755 154.693C133.774 154.704 133.789 154.718 133.798 154.733L137.035 161.719C137.532 162.787 137.493 163.914 136.921 164.97C136.35 166.025 135.27 166.965 133.808 167.679C132.346 168.393 130.562 168.852 128.664 169.003C126.767 169.153 124.835 168.989 123.093 168.529L132.108 163.324C132.319 163.195 132.468 163.036 132.54 162.864C132.613 162.691 132.606 162.511 132.521 162.34ZM140.512 161.411L140.423 161.204L137.261 154.278C137.182 154.105 137.025 153.947 136.806 153.821C136.587 153.694 136.314 153.604 136.014 153.558L121.396 151.295L125.1 149.156C125.117 149.145 125.139 149.136 125.164 149.131C125.189 149.125 125.215 149.124 125.241 149.126L137.335 150.999C139.187 151.287 140.859 151.873 142.155 152.69C143.451 153.506 144.318 154.518 144.654 155.608C144.991 156.699 144.783 157.822 144.055 158.846C143.326 159.871 142.108 160.754 140.543 161.394L140.512 161.411ZM113.878 153.615L112.519 150.696C112.512 150.681 112.512 150.666 112.517 150.651C112.522 150.636 112.533 150.621 112.549 150.609L121.388 145.506C122.746 144.725 124.462 144.183 126.334 143.943C128.206 143.704 130.157 143.777 131.96 144.154C133.763 144.531 135.342 145.196 136.515 146.072C137.687 146.948 138.403 147.999 138.58 149.101L138.228 149.044L126.262 147.193C125.963 147.148 125.648 147.149 125.35 147.195C125.051 147.242 124.778 147.332 124.557 147.457L113.878 153.615ZM119.375 152.453L125.888 153.463L127.645 157.228L122.884 159.977L116.379 158.971L114.621 155.206L119.375 152.453Z" fill="black"/>
|
||||
<path d="M317.501 29.3024L329.199 31.2013L329.691 31.0632L329.768 30.8732L329.403 30.6624L328.227 29.8948L324.061 27.356L320.502 25.123L317.098 22.9346L316.385 22.3007L316.655 21.1649L317.301 20.8932L318.574 21.0372L319.569 21.7216L321.814 23.2078L325.18 25.4393L327.649 27.0427L331.131 29.5192L331.748 29.8755L332.085 29.782L332.028 29.5711L332.018 29.387L330.812 25.7629L329.441 21.8775L328.863 19.7619L328.497 18.6483L328.652 17.8912L330.002 16.8237L332.19 16.7628L333.494 17.6254L333.756 17.8867L334.083 19.3343L334.767 22.4343L335.808 26.3969L335.906 27.0086L336.302 27.0472L336.446 26.9967L336.621 26.5958L338.357 23.1113L340.015 19.505L340.632 17.9698L341.345 17.2468C341.653 16.9588 341.923 16.7227 342.337 16.4837L345.133 16.2387L345.999 16.4956L347.37 17.5304L347.457 18.249L346.192 20.1137L344.245 23.0757L341.903 27.2788L341.198 28.52L340.262 29.5058L340.002 29.8221L340.252 29.9661L340.483 29.8325L343.397 28.3849L347.1 26.6805L351.747 24.4193L353.079 23.7957L355.121 23.3058L357.088 23.5389L357.571 24.3287L357.242 25.3977L356.432 25.7436L353.038 27.1808L347.542 29.3291L343.878 30.7767L344.215 30.9712L344.986 30.9712L348.62 30.6757L354.521 30.2972L356.98 30.214L359.767 30.1635L361.318 30.2689L362.956 31.2147L362.37 32.9458L359.978 33.703L356.152 33.9643L352.94 34.2034L348.234 34.6042L344.822 35.1283L344.765 35.2946L345.092 35.4505L350.587 37.5097L353.477 38.6678L356.9 40.0649L357.605 41.1843L357.121 41.6297L355.319 42.0707L351.423 40.7122L347.025 39.0197L340.278 36.6145L340.162 36.6041L340.144 36.7036L342.371 38.2565L343.366 38.8964L345.94 40.3826L350.376 43.3564L350.8 44.5575L350.538 45.576L349.641 45.9487L346.73 45.4023L344.744 43.5435L340.116 39.2023L338.552 37.6998L338.264 37.5335L338.092 37.633L338.13 39.615L338.439 43.1099L338.719 47.5477L338.007 48.1935L336.773 48.3152L336.31 47.9589L335.443 44.418L335.279 42.9541L334.795 39.7026L334.592 39.5853L334.322 39.7412L333.995 40.7434L332.123 46.1209L330.601 47.2225L329.773 47.3888L328.472 47.0265L327.605 46.3035L328.485 43.2807L329.68 39.9951L330.953 37.1668L330.606 37.1118L318.013 43.1471L316.923 43.1975L315.323 42.7848L315.092 41.8049L315.766 40.825L318.62 39.7679L322.295 38.359L325.226 37.2455L328.698 35.7637L329.971 35.3406L330.02 35.2916L329.77 35.1803L324.37 35.6702L316.231 36.3725L310.561 36.4838L309.645 36.2552L309.098 35.259L310.255 34.7126L311.826 34.5389L320.438 33.9435L325.712 33.5382L328.914 33.3942L329.153 33.2442L329.066 33.1938L312.461 31.1553L310.437 30.2541L310.389 29.3915L311.669 28.762L312.42 28.7501L317.53 29.295L317.509 29.295L317.501 29.3024Z" fill="#D97757"/>
|
||||
<path d="M568.979 164.163C567.307 161.766 566.444 159.206 566.439 156.622C566.445 153.015 568.124 149.475 571.302 146.37C571.443 146.232 571.502 146.071 571.467 145.912C571.433 145.754 571.308 145.606 571.112 145.493C570.916 145.38 570.66 145.307 570.385 145.287C570.11 145.268 569.831 145.301 569.593 145.383C564.212 147.216 558.081 148.185 551.834 148.189C547.358 148.186 542.924 147.688 538.773 146.723C537.142 146.348 535.577 145.9 534.075 145.383C533.837 145.3 533.557 145.265 533.281 145.284C533.004 145.304 532.747 145.376 532.55 145.49C532.353 145.603 532.228 145.752 532.195 145.911C532.161 146.071 532.221 146.232 532.366 146.37C533.263 147.236 534.036 148.138 534.688 149.081C536.361 151.478 537.223 154.038 537.228 156.622C537.222 160.229 535.543 163.77 532.366 166.876C532.221 167.013 532.161 167.175 532.195 167.334C532.228 167.494 532.353 167.643 532.55 167.756C532.747 167.87 533.004 167.942 533.281 167.961C533.557 167.981 533.837 167.946 534.075 167.863C535.577 167.344 537.139 166.897 538.773 166.521C542.924 165.555 547.358 165.057 551.834 165.054C558.081 165.058 564.213 166.028 569.593 167.863C569.831 167.945 570.11 167.978 570.385 167.958C570.66 167.938 570.916 167.866 571.112 167.753C571.308 167.64 571.433 167.492 571.467 167.333C571.502 167.174 571.443 167.014 571.302 166.876C570.403 166.009 569.627 165.101 568.979 164.163Z" fill="#3186FF"/>
|
||||
<path d="M568.979 164.163C567.307 161.766 566.444 159.206 566.439 156.622C566.445 153.015 568.124 149.475 571.302 146.37C571.443 146.232 571.502 146.071 571.467 145.912C571.433 145.754 571.308 145.606 571.112 145.493C570.916 145.38 570.66 145.307 570.385 145.287C570.11 145.268 569.831 145.301 569.593 145.383C564.212 147.216 558.081 148.185 551.834 148.189C547.358 148.186 542.924 147.688 538.773 146.723C537.142 146.348 535.577 145.9 534.075 145.383C533.837 145.3 533.557 145.265 533.281 145.284C533.004 145.304 532.747 145.376 532.55 145.49C532.353 145.603 532.228 145.752 532.195 145.911C532.161 146.071 532.221 146.232 532.366 146.37C533.263 147.236 534.036 148.138 534.688 149.081C536.361 151.478 537.223 154.038 537.228 156.622C537.222 160.229 535.543 163.77 532.366 166.876C532.221 167.013 532.161 167.175 532.195 167.334C532.228 167.494 532.353 167.643 532.55 167.756C532.747 167.87 533.004 167.942 533.281 167.961C533.557 167.981 533.837 167.946 534.075 167.863C535.577 167.344 537.139 166.897 538.773 166.521C542.924 165.555 547.358 165.057 551.834 165.054C558.081 165.058 564.213 166.028 569.593 167.863C569.831 167.945 570.11 167.978 570.385 167.958C570.66 167.938 570.916 167.866 571.112 167.753C571.308 167.64 571.433 167.492 571.467 167.333C571.502 167.174 571.443 167.014 571.302 166.876C570.403 166.009 569.627 165.101 568.979 164.163Z" fill="url(#paint0_linear_6411_8838)"/>
|
||||
<path d="M568.979 164.163C567.307 161.766 566.444 159.206 566.439 156.622C566.445 153.015 568.124 149.475 571.302 146.37C571.443 146.232 571.502 146.071 571.467 145.912C571.433 145.754 571.308 145.606 571.112 145.493C570.916 145.38 570.66 145.307 570.385 145.287C570.11 145.268 569.831 145.301 569.593 145.383C564.212 147.216 558.081 148.185 551.834 148.189C547.358 148.186 542.924 147.688 538.773 146.723C537.142 146.348 535.577 145.9 534.075 145.383C533.837 145.3 533.557 145.265 533.281 145.284C533.004 145.304 532.747 145.376 532.55 145.49C532.353 145.603 532.228 145.752 532.195 145.911C532.161 146.071 532.221 146.232 532.366 146.37C533.263 147.236 534.036 148.138 534.688 149.081C536.361 151.478 537.223 154.038 537.228 156.622C537.222 160.229 535.543 163.77 532.366 166.876C532.221 167.013 532.161 167.175 532.195 167.334C532.228 167.494 532.353 167.643 532.55 167.756C532.747 167.87 533.004 167.942 533.281 167.961C533.557 167.981 533.837 167.946 534.075 167.863C535.577 167.344 537.139 166.897 538.773 166.521C542.924 165.555 547.358 165.057 551.834 165.054C558.081 165.058 564.213 166.028 569.593 167.863C569.831 167.945 570.11 167.978 570.385 167.958C570.66 167.938 570.916 167.866 571.112 167.753C571.308 167.64 571.433 167.492 571.467 167.333C571.502 167.174 571.443 167.014 571.302 166.876C570.403 166.009 569.627 165.101 568.979 164.163Z" fill="url(#paint1_linear_6411_8838)"/>
|
||||
<path d="M568.979 164.163C567.307 161.766 566.444 159.206 566.439 156.622C566.445 153.015 568.124 149.475 571.302 146.37C571.443 146.232 571.502 146.071 571.467 145.912C571.433 145.754 571.308 145.606 571.112 145.493C570.916 145.38 570.66 145.307 570.385 145.287C570.11 145.268 569.831 145.301 569.593 145.383C564.212 147.216 558.081 148.185 551.834 148.189C547.358 148.186 542.924 147.688 538.773 146.723C537.142 146.348 535.577 145.9 534.075 145.383C533.837 145.3 533.557 145.265 533.281 145.284C533.004 145.304 532.747 145.376 532.55 145.49C532.353 145.603 532.228 145.752 532.195 145.911C532.161 146.071 532.221 146.232 532.366 146.37C533.263 147.236 534.036 148.138 534.688 149.081C536.361 151.478 537.223 154.038 537.228 156.622C537.222 160.229 535.543 163.77 532.366 166.876C532.221 167.013 532.161 167.175 532.195 167.334C532.228 167.494 532.353 167.643 532.55 167.756C532.747 167.87 533.004 167.942 533.281 167.961C533.557 167.981 533.837 167.946 534.075 167.863C535.577 167.344 537.139 166.897 538.773 166.521C542.924 165.555 547.358 165.057 551.834 165.054C558.081 165.058 564.213 166.028 569.593 167.863C569.831 167.945 570.11 167.978 570.385 167.958C570.66 167.938 570.916 167.866 571.112 167.753C571.308 167.64 571.433 167.492 571.467 167.333C571.502 167.174 571.443 167.014 571.302 166.876C570.403 166.009 569.627 165.101 568.979 164.163Z" fill="url(#paint2_linear_6411_8838)"/>
|
||||
<defs>
|
||||
<filter id="filter0_d_6411_8838" x="305.176" y="267.574" width="63.1839" height="44.094" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="2.07451" dy="2.07451"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.921931 0 0 0 0 0.921931 0 0 0 0 0.921931 0 0 0 0.72 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_6411_8838"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_6411_8838" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_6411_8838" x1="536.934" y1="155.104" x2="549.965" y2="156.609" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#08B962"/>
|
||||
<stop offset="1" stop-color="#08B962" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_6411_8838" x1="556.216" y1="145.995" x2="555.009" y2="155.399" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F94543"/>
|
||||
<stop offset="1" stop-color="#F94543" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_6411_8838" x1="534.304" y1="149.537" x2="549.499" y2="170.762" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FABC12"/>
|
||||
<stop offset="0.46" stop-color="#FABC12" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 27 KiB |
31
apps/docs/images/building-blocks/qualitative-analysis.svg
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<svg width="822" height="591" viewBox="0 0 822 591" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M497.301 70.832L460.301 51.832V148.332L588.051 208.351L685.301 166.87L497.301 70.832Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M257.301 136.832L460.301 51.832L497.301 70.832L685.301 166.87L588.051 208.351L490.801 249.832L534.801 272.332L784.801 159.832L460.301 0.332031L206.801 111.332L257.301 136.832Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M391.801 571.832V463.332L171.208 353.332V400.832V452.641L391.801 571.832Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M391.801 463.332L606.551 367.332L821.301 271.332L784.801 252.832V265.832L534.801 376.332L490.801 353.332L391.801 397.832L242.301 322.117L171.208 353.332L391.801 463.332Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M460.301 148.332L257.301 235.832L206.801 209.832V177.832L0.300781 268.332L19.8008 277.832L38.3008 287.057L78.8008 307.253L171.208 353.332L242.301 322.117L391.801 397.832L490.801 353.332V249.832L588.051 208.351L460.301 148.332Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M171.208 452.641V400.832V353.332L78.8008 307.253L38.3008 287.057L19.8008 277.832L0.300781 268.332V311.832V328.832V353.332V359.832L2.80078 361.19L171.208 452.641Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M814.801 379.291L606.551 474.082L391.801 571.832V590.332L814.801 397.832V379.291Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M534.801 272.332L490.801 249.832V353.332L534.801 376.332V324.332V272.332Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M460.301 51.832L257.301 136.832V184.832V235.832L460.301 148.332V51.832Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M257.301 136.832L206.801 111.332V177.832V209.832L257.301 235.832V184.832V136.832Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M784.801 159.832L534.801 272.332V324.332V376.332L784.801 265.832V252.832V159.832Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M821.301 271.332L606.551 367.332L391.801 463.332V571.832L606.551 474.082L814.801 379.291L821.301 376.332V271.332Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M391.801 571.832L171.208 452.641L2.80078 361.19V375.832L391.801 590.332V571.832Z" fill="#0263EF"/>
|
||||
<path d="M257.301 136.832L460.301 51.832L497.301 70.832L685.301 166.87L588.051 208.351M460.301 51.832V148.332M460.301 148.332L588.051 208.351M206.801 177.832V209.832L257.301 235.832L460.301 148.332M490.801 353.332V249.832L588.051 208.351M257.301 136.832L206.801 111.332M257.301 136.832V184.832V235.832M490.801 249.832L534.801 272.332M534.801 272.332L784.801 159.832M534.801 272.332V324.332V376.332M784.801 252.832V159.832L460.301 0.332031L206.801 111.332V177.832M391.801 571.832V463.332M0.300781 311.832V328.832V353.332V359.832L2.80078 361.19L171.208 452.641L391.801 571.832M391.801 571.832V590.332M391.801 571.832L606.551 474.082M391.801 463.332L171.208 353.332M391.801 463.332L606.551 367.332M171.208 353.332L242.301 322.117L391.801 397.832L490.801 353.332M171.208 353.332L78.8008 307.253L38.3008 287.057L19.8008 277.832L0.300781 268.332M171.208 353.332V400.832M171.208 452.641V400.832M814.801 379.291L821.301 376.332V271.332L784.801 252.832M821.301 271.332L606.551 367.332M490.801 353.332L534.801 376.332L784.801 265.832V252.832M0.300781 311.832V268.332L206.801 177.832M814.801 379.291V397.832L391.801 590.332L2.80078 375.832V361.19M814.801 379.291L606.551 474.082M606.551 367.332V474.082M0.300781 311.832L54.8008 340.332L171.208 400.832" stroke="black" stroke-width="0.6"/>
|
||||
<path d="M448.301 126.832L499.301 101.332L543.801 122.332V218.832L493.801 244.832L448.301 222.832V126.832Z" fill="#F67EFF"/>
|
||||
<path d="M493.801 244.832L543.801 218.832V122.332L499.301 101.332L448.301 126.832L448.301 222.832L493.801 244.832ZM448.301 126.832L493.801 146.332M543.801 122.332L493.801 146.332M493.801 146.332V244.832" stroke="black" stroke-width="0.6"/>
|
||||
<path d="M381.301 97.832L432.301 72.332L476.801 93.332V251.832L426.801 277.832L381.301 255.832V97.832Z" fill="#DEFF09"/>
|
||||
<path d="M426.801 277.832L476.801 251.832V93.332L432.301 72.332L381.301 97.832V255.832L426.801 277.832ZM381.301 97.832L426.801 117.332M476.801 93.332L426.801 117.332M426.801 117.332V277.832" stroke="black" stroke-width="0.6"/>
|
||||
<path d="M309.301 30.832L360.301 5.33203L404.801 26.332V290.832L354.801 316.832L309.301 294.832V30.832Z" fill="#0263EF"/>
|
||||
<path d="M354.801 316.832L404.801 290.832V26.332L360.301 5.33203L309.301 30.832V294.832L354.801 316.832ZM309.301 30.832L354.801 50.332M404.801 26.332L354.801 50.332M354.801 50.332V316.832" stroke="black" stroke-width="0.6"/>
|
||||
<circle cx="8.145" cy="8.145" r="7.78865" transform="matrix(0.866025 0.5 0 1 309.301 469.332)" fill="#0263EF" stroke="black" stroke-width="0.712687"/>
|
||||
<path d="M337.516 485.979C341.241 488.13 344.262 493.361 344.262 497.662C344.262 501.964 341.242 503.707 337.516 501.557C333.791 499.406 330.772 494.175 330.772 489.874C330.772 485.572 333.791 483.829 337.516 485.979Z" stroke="black" stroke-width="0.712687"/>
|
||||
<circle cx="8.145" cy="8.145" r="7.78865" transform="matrix(0.866025 0.5 0 1 351.623 493.77)" stroke="black" stroke-width="0.712687"/>
|
||||
<path d="M343.964 75.32L334.811 71.2446V62.5355L331.854 61.2188V70.6683C331.854 71.672 332.215 72.797 332.859 73.7936L340.333 85.3721L342.424 83.9947L336.904 75.4431L343.966 78.5874V75.3227L343.964 75.32Z" fill="white"/>
|
||||
<path d="M320.843 60.3271L326.363 68.8788L319.301 65.7344V68.9992L328.454 73.0745V81.7836L331.412 83.1004V73.6508C331.412 72.6471 331.05 71.5221 330.406 70.5255L322.934 58.9497L320.843 60.3271Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M741.206 372.506L797.355 347.791V368.153L741.206 393.887V372.506Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M741.206 372.506V393.887L735.691 390.369V368.48L741.206 372.506Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M797.355 347.791L741.206 372.506L735.691 368.48L792.342 343.852L797.355 347.791Z" fill="#0263EF"/>
|
||||
<path d="M792.542 343.549L797.556 347.487L797.746 347.636V368.443L797.562 368.528L741.414 394.261L741.235 394.342L741.045 394.221L735.53 390.704L735.301 390.557V368.187L792.342 343.39L792.542 343.549ZM736.082 368.773V390.183L741.176 393.432L796.964 367.863V347.946L792.342 344.316L736.082 368.773Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
57
apps/docs/images/building-blocks/user-profiles.svg
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<svg width="647" height="912" viewBox="0 0 647 912" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M334.85 810.6L22.7952 635.483V653.809L334.85 829.436V810.6Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M334.85 810.6L22.7952 635.483L32.9765 628.865L334.85 793.801L479.336 708.279L611.78 629.883L625.525 639.555L334.85 810.6Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M625.525 639.555V657.882L480.188 743.659L334.85 829.436V810.6L625.525 639.555Z" fill="#0049AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M207.33 266.922L315.506 203.798V219.579L113.917 337.681L99.1546 330.046L207.33 266.922Z" fill="#BDBFC8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M315.506 219.579V203.798L431.063 266.922L488.842 298.484L546.62 330.046L532.876 338.239L315.506 219.579Z" fill="#E9E9F0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M315.506 219.579L113.917 337.681L217.002 393.169L334.85 456.293L440.735 393.169L532.876 338.239L315.506 219.579ZM235.796 294.109L402.296 386.609L420.796 375.609L253.396 283.109L235.796 294.109Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M488.842 298.484L431.063 266.922L463.643 247.577L611.78 330.046L473.315 412.514L440.735 393.169L532.876 338.239L546.62 330.046L488.842 298.484Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M334.85 456.293L440.735 393.169L473.315 412.514L334.85 494.982L183.913 412.514L217.002 393.169L334.85 456.293Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M99.1546 330.046L113.917 337.681L217.002 393.169L183.913 412.514L32.9765 330.046L174.241 247.577L207.33 266.922L99.1546 330.046Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M315.506 203.798L207.33 266.922L174.241 247.577L315.506 165.109L463.643 247.577L431.063 266.922L315.506 203.798Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M479.336 708.279L334.85 793.801V494.982L473.315 412.514L479.336 708.279Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M611.78 629.883L479.336 708.279L473.315 412.514L611.78 330.046V607.484V629.883Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M334.85 844.707L646.396 660.936V721.514L334.85 911.395V844.707Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M646.396 627.847L625.525 639.555L611.78 629.883V607.484L646.396 627.847Z" fill="#E4E4E5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.7952 635.483L0.396484 622.247L32.9765 602.394V628.865L22.7952 635.483Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.396484 654.318L334.85 844.707V911.395L0.396484 716.933V654.318Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M334.85 494.982V793.801L32.9765 628.865V602.394V596.285V330.046L183.913 412.514L334.85 494.982Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.7952 635.483V653.809L334.85 829.436L480.188 743.659L625.525 657.882V639.555L646.396 627.847V660.936L334.85 844.707L0.396484 654.318V622.247L22.7952 635.483Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M402.296 386.609L235.796 294.109L253.396 283.109L420.796 375.609L402.296 386.609Z" fill="#2B7EF1"/>
|
||||
<path d="M334.85 810.6L22.7952 635.483M334.85 810.6V829.436M334.85 810.6L625.525 639.555M625.525 639.555V657.882L480.188 743.659L334.85 829.436L22.7952 653.809V635.483M22.7952 635.483L32.9765 628.865M22.7952 635.483L0.396484 622.247M479.336 708.279L334.85 793.801L32.9765 628.865M32.9765 628.865V602.394M334.85 793.801V494.982M479.336 708.279L611.78 629.883M479.336 708.279L473.315 412.514M611.78 629.883L625.525 639.555M611.78 629.883V607.484M625.525 639.555L646.396 627.847M431.063 266.922L315.506 203.798L207.33 266.922M207.33 266.922L99.1546 330.046L113.917 337.681M207.33 266.922L174.241 247.577M315.506 203.798V219.579M315.506 219.579L113.917 337.681M315.506 219.579L532.876 338.239M113.917 337.681L217.002 393.169M431.063 266.922L488.842 298.484L546.62 330.046L532.876 338.239M431.063 266.922L463.643 247.577M532.876 338.239L440.735 393.169M217.002 393.169L334.85 456.293L440.735 393.169M217.002 393.169L183.913 412.514M440.735 393.169L473.315 412.514M174.241 247.577L315.506 165.109L463.643 247.577L611.78 330.046V607.484M611.78 330.046L473.315 412.514M473.315 412.514L334.85 494.982M334.85 494.982L183.913 412.514M183.913 412.514L32.9765 330.046M32.9765 602.394V596.285V330.046L174.241 247.577M646.396 660.936V627.847L611.78 607.484M334.85 844.707L646.396 660.936M334.85 844.707V911.395M334.85 844.707L0.396484 654.318M0.396484 654.318V716.933L334.85 911.395L646.396 721.514V660.936M0.396484 654.318V622.247L32.9765 602.394M235.796 294.109L402.296 386.609L420.796 375.609L253.396 283.109L235.796 294.109Z" stroke="black" stroke-width="0.794137"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M540.889 632.893L597.904 598.277V618.64L540.889 654.274V632.893Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M540.889 632.893V654.274L535.289 651.729V629.839L540.889 632.893Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M597.904 598.277L540.889 632.893L535.289 629.839L592.813 595.223L597.904 598.277Z" fill="#0263EF"/>
|
||||
<path d="M593.017 594.881L598.108 597.935L598.301 598.051V618.858L598.115 618.975L541.1 654.609L540.919 654.722L540.725 654.634L535.125 652.089L534.893 651.983V629.613L592.813 594.758L593.017 594.881ZM535.686 630.061V651.471L540.858 653.822L597.507 618.416V598.499L592.813 595.683L535.686 630.061Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M281.295 840.557L268.155 833.156V849.379L281.295 857.592V840.557Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M281.295 840.557V857.592L285.756 855.564V838.124L281.295 840.557Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M268.155 833.156L281.295 840.557L285.756 838.124L272.21 830.723L268.155 833.156Z" fill="#0263EF"/>
|
||||
<path d="M272.048 830.45L267.993 832.883L267.839 832.975V849.552L267.987 849.646L281.127 857.858L281.271 857.948L281.426 857.878L285.887 855.85L286.072 855.765V837.943L272.211 830.352L272.048 830.45ZM285.44 838.3V855.357L281.319 857.231L268.471 849.201V833.332L272.211 831.089L285.44 838.3Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M261.361 830.425L248.221 823.023V839.246L261.361 847.459V830.425Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M261.361 830.425V847.459L265.822 845.431V827.991L261.361 830.425Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M248.221 823.023L261.361 830.425L265.822 827.991L252.277 820.59L248.221 823.023Z" fill="#0263EF"/>
|
||||
<path d="M252.115 820.317L248.059 822.75L247.905 822.842V839.419L248.053 839.513L261.193 847.725L261.338 847.815L261.492 847.745L265.953 845.717L266.139 845.633V827.81L252.277 820.219L252.115 820.317ZM265.507 828.167V845.225L261.386 847.098L248.537 839.068V823.2L252.277 820.956L265.507 828.167Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M301.472 852.663L288.332 845.262V861.485L301.472 869.697V852.663Z" fill="#0054C9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M301.472 852.663V869.697L305.934 867.669V850.229L301.472 852.663Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M288.332 845.262L301.472 852.663L305.934 850.229L292.388 842.828L288.332 845.262Z" fill="#0263EF"/>
|
||||
<path d="M292.226 842.555L288.17 844.989L288.017 845.081V861.658L288.165 861.751L301.305 869.964L301.449 870.053L301.603 869.983L306.065 867.956L306.25 867.871V850.048L292.388 842.457L292.226 842.555ZM305.618 850.406V867.463L301.497 869.336L288.649 861.306V845.438L292.388 843.195L305.618 850.406Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M60.4473 605.447V391.641L65.0288 394.194V602.392L60.4473 605.447Z" fill="#BDBFC8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M60.4473 605.447L65.0288 602.392L304.288 740.348V746.457L60.4473 605.447Z" fill="#E9E9F0"/>
|
||||
<path d="M304.288 740.348V746.457L60.4473 605.447V391.641L65.0288 394.194M60.4473 605.447L65.0288 602.392M65.0288 394.194V602.392M65.0288 394.194L304.288 527.56V740.348M65.0288 602.392L304.288 740.348" stroke="black" stroke-width="1.01812"/>
|
||||
<path d="M196.396 634.302L278.865 682.663L286.501 687.106V560.106L196.396 511.109V634.302Z" fill="#7EBCFF"/>
|
||||
<circle cx="18.3262" cy="18.3262" r="18.3262" transform="matrix(0.866025 0.5 0 1 225.307 553.234)" fill="white"/>
|
||||
<path d="M212.964 620.432C212.964 616.153 213.694 612.338 215.112 609.204C216.53 606.07 218.608 603.678 221.228 602.165C223.848 600.653 226.959 600.049 230.382 600.388C233.805 600.727 237.474 602.003 241.179 604.142C244.885 606.281 248.554 609.242 251.977 612.856C255.4 616.469 258.511 620.665 261.131 625.203C263.751 629.741 265.829 634.532 267.247 639.304C268.665 644.075 269.395 648.733 269.395 653.012L241.179 636.722L212.964 620.432Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M401.219 98.2741V328.451L248.396 238.833V10.5428L401.219 98.2741Z" fill="#7EBCFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M401.219 98.2741L248.396 10.5428L262.547 1.10938L415.369 88.8406L401.219 98.2741Z" fill="#2B7EF1"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M401.219 328.451V98.2741L415.369 88.8406V321.847L401.219 328.451Z" fill="#2B7EF1"/>
|
||||
<path d="M248.396 238.833L401.219 328.451L415.369 321.847V88.8406L262.547 1.10938L248.396 10.5428V238.833Z" stroke="black" stroke-width="1.88669"/>
|
||||
<circle cx="33.9605" cy="33.9605" r="33.3001" transform="matrix(0.866025 0.5 0 1 293.91 80.3477)" fill="white" stroke="black" stroke-width="1.32069"/>
|
||||
<path d="M271.612 204.54C271.685 196.965 273.018 190.202 275.544 184.619C278.143 178.875 281.953 174.492 286.754 171.719C291.556 168.947 297.258 167.84 303.532 168.461C309.806 169.083 316.531 171.42 323.322 175.341C330.113 179.262 336.838 184.69 343.112 191.313C349.386 197.936 355.087 205.626 359.889 213.943C364.691 222.261 368.5 231.042 371.099 239.788C373.625 248.287 374.959 256.591 375.032 264.25L271.612 204.54Z" fill="white" stroke="black" stroke-width="1.32069"/>
|
||||
<path d="M85.3965 494.443L154.533 534.359L157.239 535.921L173.739 545.447V560.903L85.3965 509.899V494.443Z" fill="#0263EF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M173.739 537.154V545.447L157.239 535.921L163.417 531.154L173.739 537.154Z" fill="#0263EF"/>
|
||||
<rect x="0.440861" y="0.763593" width="100.991" height="14.4377" transform="matrix(0.866025 0.5 0 1 85.4555 534.408)" fill="#D9D9D9" stroke="black" stroke-width="1.01812"/>
|
||||
<rect x="0.440861" y="0.763593" width="100.991" height="14.4377" transform="matrix(0.866025 0.5 0 1 85.4555 556.045)" fill="#D9D9D9" stroke="black" stroke-width="1.01812"/>
|
||||
<circle cx="8.145" cy="8.145" r="7.78865" transform="matrix(0.866025 0.5 0 1 91.3965 455.109)" fill="#0263EF" stroke="black" stroke-width="0.712687"/>
|
||||
<path d="M119.612 471.757C123.337 473.908 126.357 479.138 126.357 483.439C126.357 487.741 123.337 489.485 119.612 487.334C115.887 485.183 112.867 479.952 112.867 475.651C112.868 471.35 115.887 469.606 119.612 471.757Z" fill="#0263EF" stroke="black" stroke-width="0.712687"/>
|
||||
<circle cx="8.145" cy="8.145" r="7.78865" transform="matrix(0.866025 0.5 0 1 133.719 479.547)" stroke="black" stroke-width="0.712687"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
BIN
apps/docs/images/company-brain/cursor-icon.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
apps/docs/images/company-brain/dhravya-slack-icon.jpg
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
apps/docs/images/company-brain/plain-icon.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
apps/docs/images/company-brain/signup-company-domain.png
Normal file
|
After Width: | Height: | Size: 321 KiB |
BIN
apps/docs/images/company-brain/signup-research-complete.png
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
apps/docs/images/company-brain/signup-research-connect.png
Normal file
|
After Width: | Height: | Size: 680 KiB |
BIN
apps/docs/images/company-brain/signup-team-toggle.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/docs/images/company-brain/slack-create-workspace.png
Normal file
|
After Width: | Height: | Size: 389 KiB |
BIN
apps/docs/images/company-brain/supermemory-slack-icon.png
Normal file
|
After Width: | Height: | Size: 323 KiB |
1
apps/docs/images/github-icon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" rx="4.5" fill="#ffffff"/><g fill="#171717" transform="translate(2.5,2.5) scale(0.7917)"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></g></svg>
|
||||
|
After Width: | Height: | Size: 988 B |
1
apps/docs/images/google-drive-icon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" rx="4.5" fill="#ffffff"/><g fill="#171717" transform="translate(2.5,2.5) scale(0.7917)"><path d="M12.01 1.485c-2.082 0-3.754.02-3.743.047.01.02 1.708 3.001 3.774 6.62l3.76 6.574h3.76c2.081 0 3.753-.02 3.742-.047-.005-.02-1.708-3.001-3.775-6.62l-3.76-6.574zm-4.76 1.73a789.828 789.861 0 0 0-3.63 6.319L0 15.868l1.89 3.298 1.885 3.297 3.62-6.335 3.618-6.33-1.88-3.287C8.1 4.704 7.255 3.22 7.25 3.214zm2.259 12.653-.203.348c-.114.198-.96 1.672-1.88 3.287a423.93 423.948 0 0 1-1.698 2.97c-.01.026 3.24.042 7.222.042h7.244l1.796-3.157c.992-1.734 1.85-3.23 1.906-3.323l.104-.167h-7.249z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 759 B |
BIN
apps/docs/images/intro-company-brain-card.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
apps/docs/images/intro-company-brain.jpg
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
apps/docs/images/intro-developer-platform.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/docs/images/intro-plugins-full.jpg
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
apps/docs/images/intro-plugins.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |