mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-29 06:36:43 +00:00
docs: full drift audit (2026-10-27) (#1855)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
parent
0da13138fa
commit
0f2b24b0f2
49 changed files with 599 additions and 428 deletions
|
|
@ -13,6 +13,7 @@ v5 calls these **namespaces**. Same values. New integrations should use [v5 name
|
|||
|
||||
| Endpoint | Use when |
|
||||
| --- | --- |
|
||||
| `GET /v3/container-tags/list` | List every container tag |
|
||||
| `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 |
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ Same `containerTag` scopes ingest, search, and profiles — one engine, multiple
|
|||
## Suggested order
|
||||
|
||||
1. **Ingest** — `POST /v3/documents` (SDK: `client.add`)
|
||||
2. **Documents** — `GET /v3/documents/{id}` until `status: "done"`
|
||||
2. **Documents** — `GET /v3/documents/{id}` until `status: "done"` for searchable content, and `dreamingStatus: "done"` before you read memories or profiles
|
||||
3. **Search** — `POST /v4/search`
|
||||
4. **Profiles** — `POST /v4/profile`
|
||||
|
||||
|
|
@ -56,16 +56,14 @@ Full walkthrough with conversation + document examples: [Quickstart](/quickstart
|
|||
|
||||
## SDKs
|
||||
|
||||
Official clients wrap this API:
|
||||
The current `supermemory` SDKs (5.x) call the [v5 API](/v5/api-reference/overview), not these endpoints. To call v3/v4 through an SDK, pin a release from before 5.0.0:
|
||||
|
||||
- TypeScript: `npm install supermemory`
|
||||
- Python: `pip install supermemory`
|
||||
- TypeScript: `npm install supermemory@4`
|
||||
- Python: `pip install "supermemory<5"`
|
||||
|
||||
See [Supermemory SDK](/integrations/supermemory-sdk).
|
||||
|
||||
The API's OpenAPI generator supplies official **TypeScript / Python SDK** samples via `x-codeSamples`, plus cURL. Playground snippets use the deployed spec, so their availability depends on the API version serving it.
|
||||
|
||||
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.
|
||||
The API's OpenAPI generator supplies **TypeScript / Python SDK** samples via `x-codeSamples`, plus cURL. On this legacy reference they use the pre-5 SDK methods. Playground snippets use the deployed spec, so their availability depends on the API version serving it.
|
||||
|
||||
## OpenAPI
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ Namespace scoping is not read-only access. Writable scoped keys can update and d
|
|||
|
||||
Pairs with [namespaces](/concepts/container-tags) for multi-tenant isolation.
|
||||
|
||||
**Allowed endpoints:** `/ns/{namespace}/document`, `/ns/{namespace}/list`, `/ns/{namespace}/search`, `/ns/{namespace}/profile`, and `/ns/{namespace}/memories`; `/namespaces` and `/ns/{namespace}`; and the legacy `/v3/documents`, `/v3/memories`, `/v4/memories`, `/v4/conversations`, `/v3/search`, `/v4/search`, `/v4/profile`, `/v3/container-tags/list`, and `/v3/session` routes. Any other route returns `403`.
|
||||
**Allowed endpoints:** `/ns/{namespace}/document`, `/ns/{namespace}/list`, `/ns/{namespace}/search`, `/ns/{namespace}/profile`, and `/ns/{namespace}/memories`; `/namespaces` and `/ns/{namespace}`; `/session`; and the legacy `/v3/documents`, `/v3/memories`, `/v4/memories`, `/v4/conversations`, `/v3/search`, `/v4/search`, `/v4/profile`, `/v3/container-tags/list`, and `/v3/session` routes. Any other route returns `403`.
|
||||
|
||||
Scoped keys **cannot** read billing, manage org settings, or mint further keys.
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ Scoped keys **cannot** read billing, manage org settings, or mint further keys.
|
|||
The scoped-key endpoint still takes the namespace in a field named `containerTag`.
|
||||
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key \
|
||||
curl https://api.supermemory.ai/auth/scoped-key \
|
||||
--request POST \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY' \
|
||||
|
|
@ -86,8 +86,9 @@ curl https://api.supermemory.ai/v3/auth/scoped-key \
|
|||
| `containerTags` | No | — | Scope the key to several namespaces instead of one. Takes precedence over `containerTag` |
|
||||
| `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) |
|
||||
| `rateLimitMax` | No | `500` | Max requests per minute (1–10,000), rounded up to the next tier: 500, 1,000, 2,000, 5,000, or 10,000 |
|
||||
|
||||
Requests over the limit return `429` with a `Retry-After` header.
|
||||
|
||||
### Response
|
||||
|
||||
|
|
@ -99,7 +100,8 @@ curl https://api.supermemory.ai/v3/auth/scoped-key \
|
|||
"containerTag": "my-project",
|
||||
"containerTags": ["my-project"],
|
||||
"expiresAt": "2026-03-08T00:00:00.000Z",
|
||||
"allowedEndpoints": ["/v3/session", "/v3/documents", "/v3/memories", "/v4/memories", "/v4/conversations", "/ns/*/memories", "/v3/search", "/v4/search", "/v4/profile", "/v3/container-tags/list", "/ns/*/document", "/ns/*/list", "/ns/*/search", "/ns/*/profile", "/namespaces$", "/ns$", "/ns/*$"]
|
||||
"allowedEndpoints": ["/v3/session", "/session", "/v3/documents", "/v3/memories", "/v4/memories", "/v4/conversations", "/ns/*/memories", "/v3/search", "/v4/search", "/v4/profile", "/v3/container-tags/list", "/ns/*/document", "/ns/*/list", "/ns/*/search", "/ns/*/profile", "/namespaces$", "/ns$", "/ns/*$"],
|
||||
"rateLimitMax": 500
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -110,7 +112,7 @@ Use the returned key like a normal API key — it just will not work outside its
|
|||
Revoke with the `id` from creation. Subsequent requests get `401`. Memories and namespaces are **not** deleted.
|
||||
|
||||
```bash
|
||||
curl https://api.supermemory.ai/v3/auth/scoped-key/KEY_ID \
|
||||
curl https://api.supermemory.ai/auth/scoped-key/KEY_ID \
|
||||
--request DELETE \
|
||||
--header 'Authorization: Bearer YOUR_API_KEY'
|
||||
```
|
||||
|
|
|
|||
|
|
@ -172,6 +172,10 @@ Show "Log in to **YourApp**" instead of "Log in to Supermemory" when users conne
|
|||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Note>
|
||||
Client secrets are write-only. `GET /v3/settings` and the `PATCH /v3/settings` response return each connector's client ID and `*CustomKeyEnabled` flag, but never its client secret.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## API reference
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ Unlike most connectors, GitHub requires repository selection before syncing begi
|
|||
- **Direct selection:** if you already know the repository ids, pass them in `selection.repos` with `connectors.update`. A new selection replaces the old one and starts a sync.
|
||||
|
||||
<Note>
|
||||
See [Managing Connector Selection](/connectors/managing-resources) for the generic selection API that GitHub, Gmail and Google Drive share.
|
||||
See [Managing Connector Selection](/connectors/managing-resources) for the generic selection API that GitHub, Gmail, Google Drive and OneDrive share.
|
||||
</Note>
|
||||
|
||||
<Tabs>
|
||||
|
|
|
|||
|
|
@ -304,7 +304,6 @@ Gmail connector supports multiple sync methods:
|
|||
| Feature | Behavior |
|
||||
|---------|----------|
|
||||
| **Real-time sync** | Via Google Cloud Pub/Sub webhooks (7-day expiry, auto-renewed) |
|
||||
| **Scheduled sync** | Every 4 hours |
|
||||
| **Manual sync** | On-demand via API |
|
||||
| **Incremental sync** | Uses Gmail `historyId` to fetch only changed threads |
|
||||
|
||||
|
|
@ -337,7 +336,7 @@ The Gmail connector requests the following OAuth scopes:
|
|||
<Warning>
|
||||
**Important Limitations:**
|
||||
- **Plan requirement**: Requires Max Plan or above
|
||||
- **INBOX only** for real-time sync: Only INBOX label triggers real-time updates; other labels sync via scheduled sync
|
||||
- **Selected labels only**: Syncs and real-time updates cover the labels chosen in the picker. Nothing syncs until at least one label is selected
|
||||
- **Watch expiration**: Gmail watch subscriptions expire after 7 days (automatically renewed by supermemory)
|
||||
- **Document limit**: Default limit is 10,000 threads per connector (configurable via `documentLimit` parameter)
|
||||
- **Attachments**: Attachment metadata is stored, but attachment content is not downloaded
|
||||
|
|
@ -373,7 +372,7 @@ if (next.authorization) window.location.href = next.authorization.url
|
|||
|
||||
If real-time sync isn't working:
|
||||
|
||||
- Scheduled sync (every 4 hours) and manual sync still work
|
||||
- Manual sync still works
|
||||
- Real-time sync requires supermemory's Pub/Sub infrastructure
|
||||
- Check if the connector was created recently (watch registration happens on creation)
|
||||
- Trigger a manual sync to verify the connector is working
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Connect Google Drive to sync documents into your Supermemory knowledge base with
|
|||
**Explicit scoped mode:** set `config.syncScope` to `"selected"` for the picker flow, or rely on the default for new connects.
|
||||
|
||||
<Note>
|
||||
If you use scoped sync and the user has not finished the picker yet, **scheduled or manual sync may skip that connector** until a selection is saved on the connector.
|
||||
If you use scoped sync and the user has not finished the picker yet, **sync may skip that connector** until a selection is saved on the connector.
|
||||
</Note>
|
||||
|
||||
## Quick setup
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ icon: 'folder-sync'
|
|||
---
|
||||
|
||||
<Note>
|
||||
**Selectable connectors:** GitHub (repositories), Gmail (labels) and Google Drive (files and folders) let you choose what to sync. Other connectors sync everything and return `selection: null`.
|
||||
**Selectable connectors:** GitHub (repositories), Gmail (labels), Google Drive (files and folders) and OneDrive (folders) let you choose what to sync. Other connectors sync everything and return `selection: null`, as does a OneDrive connector set to sync the whole drive.
|
||||
</Note>
|
||||
|
||||
Some connectors let you select which resources to sync. v5 exposes this through two calls on the connector itself: read it with `include: "picker"` to get a hosted picker URL, or send the ids directly with `connectors.update`.
|
||||
|
|
@ -83,7 +83,7 @@ curl "https://api.supermemory.ai/ns/user-123/connectors/{connectorId}?include=pi
|
|||
```
|
||||
|
||||
<Note>
|
||||
The picker link works once, in any browser. `picker` is `null` for providers that do not support selection. A Google Drive connector with full-drive sync can still open the picker; saving a selection switches it to scoped sync. Because the link changes what syncs, `include=picker` needs an admin key with write access to the namespace; otherwise the request returns `403`.
|
||||
The picker link works once, in any browser. `picker` is `null` for providers that do not support selection. A Google Drive or OneDrive connector with whole-drive sync can still open the picker; saving a selection switches it to scoped sync. Because the link changes what syncs, `include=picker` needs an admin key with write access to the namespace; otherwise the request returns `403`.
|
||||
</Note>
|
||||
|
||||
## Set the Selection Directly
|
||||
|
|
@ -150,6 +150,7 @@ The selection key depends on the provider:
|
|||
- GitHub: `repos` (repository ids)
|
||||
- Gmail: `labels` (label ids, for example `INBOX`)
|
||||
- Google Drive: `files` and `folders` (Drive ids)
|
||||
- OneDrive: `folders` (OneDrive folder ids)
|
||||
|
||||
You can send `documentLimit` in the same body. Each call must include `selection`, `documentLimit`, or both.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,24 @@
|
|||
---
|
||||
title: "OneDrive connector"
|
||||
sidebarTitle: "OneDrive"
|
||||
description: "Sync Microsoft Office documents from OneDrive with scheduled synchronization and business account support"
|
||||
description: "Sync Microsoft Office documents from OneDrive with real-time webhook updates and business account support"
|
||||
icon: "/images/microsoft-icon.svg"
|
||||
---
|
||||
|
||||
|
||||
Connect OneDrive to automatically sync Word documents, Excel spreadsheets, and PowerPoint presentations into your Supermemory knowledge base. Supports both personal and business accounts with scheduled synchronization.
|
||||
Connect OneDrive to automatically sync Word documents, Excel spreadsheets, and PowerPoint presentations into your Supermemory knowledge base. Supports both personal and business accounts with real-time updates via webhooks.
|
||||
|
||||
## Sync scope
|
||||
|
||||
**Default for new connectors:** after OAuth, the user picks **folders** in Supermemory's hosted folder picker. Only files in the selected folders are synced, and nothing syncs until at least one folder is saved.
|
||||
|
||||
**Whole OneDrive:** set `config.syncScope` to `"full"` when creating the connector so the entire drive syncs without the picker.
|
||||
|
||||
**Explicit scoped mode:** set `config.syncScope` to `"selected"` for the picker flow, or rely on the default for new connects.
|
||||
|
||||
<Note>
|
||||
Connectors created before folder selection was available keep syncing the whole drive. They can narrow to folders by opening the picker and saving a selection.
|
||||
</Note>
|
||||
|
||||
## Quick setup
|
||||
|
||||
|
|
@ -23,6 +35,7 @@ const connector = await supermemory.connectors.create("user-123", {
|
|||
provider: "onedrive",
|
||||
redirectUrl: "https://yourapp.com/auth/onedrive/callback",
|
||||
documentLimit: 1500,
|
||||
config: { syncScope: "selected" },
|
||||
})
|
||||
|
||||
// Send the user to Microsoft to authorize
|
||||
|
|
@ -42,11 +55,13 @@ connector = client.connectors.create(
|
|||
"provider": "onedrive",
|
||||
"redirect_url": "https://yourapp.com/auth/onedrive/callback",
|
||||
"document_limit": 1500,
|
||||
"config": {"sync_scope": "selected"},
|
||||
},
|
||||
)
|
||||
|
||||
# Send the user to Microsoft to authorize
|
||||
print(f"Redirect to: {connector.authorization.url}")
|
||||
if connector.authorization:
|
||||
print(f"Redirect to: {connector.authorization.url}")
|
||||
# Output: Redirect to: https://api.supermemory.ai/v3/connections/auth/redirect?state=...
|
||||
```
|
||||
|
||||
|
|
@ -57,7 +72,8 @@ curl -X POST "https://api.supermemory.ai/ns/user-123/connectors" \
|
|||
-d '{
|
||||
"provider": "onedrive",
|
||||
"redirectUrl": "https://yourapp.com/auth/onedrive/callback",
|
||||
"documentLimit": 1500
|
||||
"documentLimit": 1500,
|
||||
"config": { "syncScope": "selected" }
|
||||
}'
|
||||
|
||||
# Response: {
|
||||
|
|
@ -73,7 +89,7 @@ curl -X POST "https://api.supermemory.ai/ns/user-123/connectors" \
|
|||
|
||||
### 2. Handle Microsoft OAuth
|
||||
|
||||
Send the user to `authorization.url` before `authorization.expiresAt`. After the user grants permissions, Microsoft redirects to your `redirectUrl` and the initial sync begins. A pending OAuth connector is not returned by list until the user finishes authorization; get returns it with `system.status: "pending_authorization"`.
|
||||
Send the user to `authorization.url` before `authorization.expiresAt`. With **scoped** sync (`syncScope` omitted or `"selected"`), Supermemory then sends the user to its hosted folder picker; once they save a selection, they return to your `redirectUrl` and the initial sync begins. With `syncScope: "full"`, Microsoft redirects through Supermemory to your `redirectUrl` and the initial sync begins right away. A pending OAuth connector is not returned by list until the user finishes authorization; get returns it with `system.status: "pending_authorization"`.
|
||||
|
||||
### 3. Monitor sync status
|
||||
|
||||
|
|
@ -119,8 +135,12 @@ Send the user to `authorization.url` before `authorization.expiresAt`. After the
|
|||
There is no per-connector document list in v5. `supermemory.list(namespace, "documents")` returns every document in the namespace.
|
||||
</Note>
|
||||
|
||||
To change the folders later, read the connector with `include: "picker"` and send the user to `picker.url`, or set folder ids directly with `connectors.update(namespace, id, { selection: { folders: ["<folder-id>"] } })`. A new selection replaces the old one and starts a sync. See [Managing Connector Selection](/connectors/managing-resources).
|
||||
|
||||
## Supported document types
|
||||
|
||||
Word, Excel, and PowerPoint files are converted to PDF by Microsoft Graph before extraction. Markdown, PDF, JSON, and plain-text files are downloaded as-is and go through the same extraction pipeline as uploads.
|
||||
|
||||
### Microsoft Word documents
|
||||
- **Rich text formatting** converted to markdown
|
||||
- **Headers and styles** preserved as markdown hierarchy
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ New v5 connectors belong to one namespace. The namespace goes in the URL (`/ns/{
|
|||
<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.
|
||||
Real-time updates via webhooks. Supports personal and business accounts with file versioning.
|
||||
</Card>
|
||||
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ curl -X POST "https://api.supermemory.ai/ns/user-123/connectors" \
|
|||
|
||||
### 2. Handle OAuth callback
|
||||
|
||||
Send the user to `authorization.url` before `authorization.expiresAt`. When the user authorizes, the provider returns them to your `redirectUrl` and the first sync starts. GitHub, Gmail and Google Drive (with the default `syncScope: "selected"`) first send the user through Supermemory's hosted picker to choose what to sync. A pending OAuth connector is not returned by list until the user finishes authorization; get returns it with `system.status: "pending_authorization"`.
|
||||
Send the user to `authorization.url` before `authorization.expiresAt`. When the user authorizes, the provider returns them to your `redirectUrl` and the first sync starts. GitHub and Gmail, and Google Drive and OneDrive with the default `syncScope: "selected"`, first send the user through Supermemory's hosted picker to choose what to sync. A pending OAuth connector is not returned by list until the user finishes authorization; get returns it with `system.status: "pending_authorization"`.
|
||||
|
||||
Config providers (Web Crawler, S3, Granola) return `authorization: null` and start syncing immediately.
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ curl -X POST "https://api.supermemory.ai/ns/user-123/list/documents" \
|
|||
1. **Create Connector**: Call `POST /ns/{namespace}/connectors` with a `provider`. OAuth providers return an `authorization` link; config providers (Web Crawler, S3, Granola) take a `config` object and return `authorization: null`
|
||||
2. **User Authorization**: Send the user to `authorization.url` when the provider requires it
|
||||
3. **Automatic Setup**: The connector is established. Save any required label, repository, or file selection before content sync can proceed; providers without a selection step start their initial sync after setup
|
||||
4. **Continuous Sync**: Real-time updates via webhooks + scheduled sync every 4 hours (or scheduled recrawling for Web Crawler)
|
||||
4. **Continuous Sync**: Real-time updates via webhooks (or scheduled recrawling for Web Crawler), plus manual sync on demand
|
||||
|
||||
### Document processing pipeline
|
||||
|
||||
|
|
@ -234,11 +234,11 @@ graph TD
|
|||
|
||||
| Provider | Real-time Sync | Scheduled Sync | Manual Sync |
|
||||
|----------|---------------|----------------|-------------|
|
||||
| **Google Drive** | ✅ Webhooks (7-day expiry) | ✅ Every 4 hours | ✅ On-demand |
|
||||
| **Gmail** | ✅ Pub/Sub (7-day expiry) | ✅ Every 4 hours | ✅ On-demand |
|
||||
| **Notion** | ✅ Webhooks | ✅ Every 4 hours | ✅ On-demand |
|
||||
| **OneDrive** | ✅ Webhooks (30-day expiry) | ✅ Every 4 hours | ✅ On-demand |
|
||||
| **GitHub** | ✅ Webhooks | ✅ Every 4 hours | ✅ On-demand |
|
||||
| **Google Drive** | ✅ Webhooks (7-day expiry) | ❌ Not supported | ✅ On-demand |
|
||||
| **Gmail** | ✅ Pub/Sub (7-day expiry) | ❌ Not supported | ✅ On-demand |
|
||||
| **Notion** | ✅ Webhooks | ❌ Not supported | ✅ On-demand |
|
||||
| **OneDrive** | ✅ Webhooks (30-day expiry) | ❌ Not supported | ✅ On-demand |
|
||||
| **GitHub** | ✅ Webhooks | ❌ Not supported | ✅ On-demand |
|
||||
| **Granola** | ❌ Not supported | ❌ Not supported | ✅ On-demand |
|
||||
| **Web Crawler** | ❌ Not supported | ✅ Scheduled recrawling (7+ days) | ✅ On-demand |
|
||||
|
||||
|
|
|
|||
|
|
@ -212,11 +212,11 @@ Business accounts may have additional restrictions:
|
|||
|
||||
**Real-time Sync Not Working**
|
||||
|
||||
If emails aren't syncing in real-time but scheduled/manual sync works:
|
||||
If emails aren't syncing in real-time but manual sync works:
|
||||
|
||||
1. Real-time sync uses Google Cloud Pub/Sub webhooks
|
||||
2. Watch subscriptions expire after 7 days (supermemory auto-renews)
|
||||
3. Only INBOX label triggers real-time updates
|
||||
3. Real-time updates cover only the labels selected for the connector
|
||||
4. Trigger a manual sync to verify the connector is healthy:
|
||||
|
||||
```typescript
|
||||
|
|
@ -247,7 +247,7 @@ const next = await supermemory.connectors.create("user-123", {
|
|||
|
||||
Gmail connector requires Max Plan or above. If you see access errors:
|
||||
- Verify your organization has the required plan
|
||||
- Contact support to upgrade your plan
|
||||
- Upgrade from **Billing** in the [console](https://console.supermemory.ai/billing)
|
||||
|
||||
|
||||
## Best practices
|
||||
|
|
|
|||
|
|
@ -378,6 +378,7 @@
|
|||
"icon": "/icons/hugeicons/tag-01.svg",
|
||||
"pages": [
|
||||
"api-reference/container-tags",
|
||||
"GET /v3/container-tags/list",
|
||||
"GET /v3/container-tags/{containerTag}",
|
||||
"PATCH /v3/container-tags/{containerTag}",
|
||||
"DELETE /v3/container-tags/{containerTag}",
|
||||
|
|
@ -448,6 +449,7 @@
|
|||
"pages": [
|
||||
"v5/api-reference/content-management",
|
||||
"GET /ns/{namespace}/document/{id}",
|
||||
"GET /ns/{namespace}/memories/{id}",
|
||||
"POST /ns/{namespace}/list/{type}",
|
||||
"DELETE /ns/{namespace}/document",
|
||||
"DELETE /ns/{namespace}/memories",
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ console.log(doc.system.status); // "queued" | "extracting" | "chunking" | "embed
|
|||
|--------|-------|-------|
|
||||
| 400 | Bad request | Missing required fields, invalid parameters, unexpected query parameters |
|
||||
| 401 | Unauthorized | Invalid or missing API key |
|
||||
| 402 | Payment required | Insufficient balance or document quota |
|
||||
| 402 | Payment required | Not enough credit balance for this ingest |
|
||||
| 403 | Forbidden | No write access to this namespace |
|
||||
| 409 | Conflict | A namespace merge is in progress |
|
||||
| 429 | Rate limited | Too many requests |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
You are integrating Supermemory into my application. Supermemory provides user memory, semantic search, and automatic knowledge extraction for AI applications.
|
||||
|
||||
You can always reference the documentation by using the **SearchSupermemoryDocs MCP** or running a web search tool for content on **supermemory.ai/docs**.
|
||||
You can always reference the documentation by using the **supermemory-docs MCP** (`https://supermemory.ai/docs/mcp`) or running a web search tool for content on **supermemory.ai/docs**. Prefer `npx supermemory setup` / `npx supermemory help --json` when scaffolding.
|
||||
|
||||
This prompt targets the v5 API and the 5.x SDKs. Already on Supermemory v3/v4? Run `npx supermemory@latest migrate` instead of rewriting calls by hand.
|
||||
|
||||
## STEP 1: ASK ME THESE QUESTIONS
|
||||
|
||||
|
|
@ -18,105 +20,116 @@ You can always reference the documentation by using the **SearchSupermemoryDocs
|
|||
- Direct API calls
|
||||
|
||||
3. Data model?
|
||||
- Individual users only → containerTag: userId
|
||||
- Organizations only → containerTag: orgId
|
||||
- Individual users only → namespace: userId
|
||||
- Organizations only → namespace: orgId
|
||||
- Both users AND orgs → ask for strategy
|
||||
|
||||
4. Do you want USER PROFILES?
|
||||
User profiles are automatically-maintained facts about users (what they like, what they're working on, preferences).
|
||||
- Yes (RECOMMENDED) → Use client.profile() to get context
|
||||
- Yes (RECOMMENDED) → Use `client.profile(namespace)` to get context
|
||||
- No → Just use search
|
||||
|
||||
5. How should I retrieve context?
|
||||
- OPTION A: One call with search included → `profile({ containerTag, q: userMessage })`
|
||||
- OPTION B: Separate calls → `profile()` for facts, `search()` for memories
|
||||
- OPTION A: Profile plus search → `profile(namespace)` for facts, then `search(namespace, { query: userMessage })` for relevant memories
|
||||
- OPTION B: Search only → `search(namespace, { query: userMessage })`
|
||||
|
||||
## STEP 2: INSTALL
|
||||
|
||||
```bash
|
||||
# Get API key: https://console.supermemory.ai
|
||||
npm install supermemory # or: pip install supermemory
|
||||
npm install supermemory # or: pip install supermemory (version 5 or later)
|
||||
# For Vercel AI SDK: npm install @supermemory/tools
|
||||
export SUPERMEMORY_API_KEY="sm_..."
|
||||
```
|
||||
|
||||
## STEP 3: CONFIGURE SETTINGS (DO THIS FIRST)
|
||||
## STEP 3: CANONICAL API SURFACE (use these, nothing else)
|
||||
|
||||
- Auth header: `Authorization: Bearer $SUPERMEMORY_API_KEY` (recommended; `x-api-key` and `x-supermemory-api-key` still work but are deprecated)
|
||||
- Write content: `POST https://api.supermemory.ai/ns/{namespace}/document`
|
||||
- Upload a file: `POST https://api.supermemory.ai/ns/{namespace}/document/file`
|
||||
- Search: `POST https://api.supermemory.ai/ns/{namespace}/search`
|
||||
- Profile: `POST https://api.supermemory.ai/ns/{namespace}/profile`
|
||||
- Org settings: `PATCH https://api.supermemory.ai/organization`
|
||||
- Scoping: one `namespace` in the URL path — never in the body or a header
|
||||
|
||||
DO NOT USE — deprecated or removed in v5:
|
||||
|
||||
- Endpoints: `/v3/documents`, `/v3/search`, `/v3/settings`, `/v4/search`, `/v4/profile`, `/v4/memories` (use `/ns/{namespace}/...` and `/organization`)
|
||||
- Body keys: `containerTag`, `containerTags`, `customId` (use `id`), `entityContext` (use `supportingContext`), `documentDate` (use `date`), `q` (use `query`), `filters` (use `filter`)
|
||||
- SDK: `client.add({ containerTag })`, `client.search.execute`, `client.memories.add`, `client.profile({ containerTag, q })`
|
||||
|
||||
## STEP 4: CONFIGURE ORGANIZATION CONTEXT (OPTIONAL)
|
||||
|
||||
Describe your app so extraction focuses on what matters:
|
||||
|
||||
```typescript
|
||||
// PATCH https://api.supermemory.ai/v3/settings
|
||||
fetch('https://api.supermemory.ai/v3/settings', {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
shouldLLMFilter: true,
|
||||
filterPrompt: `This is a [your app description]. containerTag is [userId/orgId]. We store [what data].`
|
||||
})
|
||||
import { Supermemory } from "supermemory"
|
||||
|
||||
const client = new Supermemory()
|
||||
|
||||
await client.organization.update({
|
||||
organizationalContext: "This is a [your app description]. Each namespace is a [userId/orgId]. We store [what data].",
|
||||
})
|
||||
```
|
||||
|
||||
## STEP 4: CONTAINER TAG STRATEGY
|
||||
## STEP 5: NAMESPACE STRATEGY
|
||||
|
||||
Based on their data model answer:
|
||||
|
||||
**USER-ONLY APP:**
|
||||
|
||||
```typescript
|
||||
containerTag: userId
|
||||
const namespace = userId
|
||||
```
|
||||
|
||||
**ORG-ONLY APP:**
|
||||
|
||||
```typescript
|
||||
containerTag: orgId // Org members share memories
|
||||
const namespace = orgId // Org members share memories
|
||||
```
|
||||
|
||||
**BOTH (ask which):**
|
||||
|
||||
```typescript
|
||||
// Option A: Unique per user-org combination
|
||||
containerTag: `${userId}-${orgId}`
|
||||
const namespace = `${orgId}_${userId}`
|
||||
|
||||
// Option B: Org-scoped with user metadata
|
||||
containerTag: orgId, metadata: { userId }
|
||||
await client.add(orgId, { content, metadata: { userId } })
|
||||
|
||||
// Option C: User-scoped with org metadata
|
||||
containerTag: userId, metadata: { orgId }
|
||||
await client.add(userId, { content, metadata: { orgId } })
|
||||
```
|
||||
|
||||
## STEP 5: INTEGRATION CODE
|
||||
## STEP 6: INTEGRATION CODE
|
||||
|
||||
Based on their integration choice:
|
||||
|
||||
### VERCEL AI SDK
|
||||
|
||||
```typescript
|
||||
import { streamText } from 'ai'
|
||||
import { anthropic } from '@ai-sdk/anthropic'
|
||||
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
||||
import { generateText } from "ai"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
import { supermemoryTools, withSupermemory } from "@supermemory/tools/ai-sdk"
|
||||
|
||||
// Option 1: Agent tools (recommended for agentic flows)
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-5-sonnet-20241022'),
|
||||
prompt: userMessage,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY, {
|
||||
containerTags: [userId]
|
||||
})
|
||||
})
|
||||
// Agent gets searchMemories, addMemory, fetchMemory tools
|
||||
|
||||
// Option 2: Profile middleware (automatic context injection)
|
||||
import { withSupermemory } from '@supermemory/tools/ai-sdk'
|
||||
const modelWithMemory = withSupermemory(anthropic('claude-3-5-sonnet-20241022'), {
|
||||
containerTag: userId,
|
||||
customId: 'conversation-1',
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model: openai("gpt-5"),
|
||||
prompt: userMessage,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
namespace: userId,
|
||||
}),
|
||||
})
|
||||
|
||||
// Option 2: Middleware (automatic context injection)
|
||||
const modelWithMemory = withSupermemory(openai("gpt-5"), {
|
||||
namespace: userId,
|
||||
id: "conversation-1",
|
||||
})
|
||||
|
||||
const answer = await generateText({
|
||||
model: modelWithMemory,
|
||||
messages: [{ role: 'user', content: userMessage }]
|
||||
messages: [{ role: "user", content: userMessage }],
|
||||
})
|
||||
// Profile is automatically injected into context
|
||||
```
|
||||
|
|
@ -124,65 +137,71 @@ const result = await generateText({
|
|||
### DIRECT SDK (WITH PROFILES)
|
||||
|
||||
```typescript
|
||||
import Supermemory from 'supermemory'
|
||||
import { Supermemory } from "supermemory"
|
||||
|
||||
const client = new Supermemory()
|
||||
|
||||
// Before each LLM call:
|
||||
const { profile, searchResults } = await client.profile({
|
||||
containerTag: userId,
|
||||
q: userMessage // Include this if they chose OPTION A (one call)
|
||||
// Omit if they chose OPTION B (separate calls)
|
||||
const { profile } = await client.profile(userId)
|
||||
const related = await client.search(userId, {
|
||||
query: userMessage,
|
||||
searchMode: "memories",
|
||||
limit: 5,
|
||||
})
|
||||
|
||||
// Build context
|
||||
const context = `
|
||||
Static facts: ${profile.static.join('\n')}
|
||||
Recent context: ${profile.dynamic.join('\n')}
|
||||
${searchResults ? `Memories: ${searchResults.results.map(r => r.content).join('\n')}` : ''}
|
||||
`
|
||||
const context = [
|
||||
"Static facts:",
|
||||
...profile.static.map((m) => m.memory),
|
||||
"Recent context:",
|
||||
...profile.dynamic.map((m) => m.memory),
|
||||
"Memories:",
|
||||
...related.results.map((r) => r.memory).filter(Boolean),
|
||||
].join("\n")
|
||||
|
||||
// Send to LLM
|
||||
const messages = [
|
||||
{ role: 'system', content: `User context:\n${context}` },
|
||||
{ role: 'user', content: userMessage }
|
||||
{ role: "system", content: `User context:\n${context}` },
|
||||
{ role: "user", content: userMessage },
|
||||
]
|
||||
|
||||
// After LLM responds:
|
||||
await client.memories.add({
|
||||
// After LLM responds, append the turn to one document per conversation:
|
||||
await client.add(userId, {
|
||||
content: `user: ${userMessage}\nassistant: ${response}`,
|
||||
containerTag: userId
|
||||
id: conversationId,
|
||||
})
|
||||
```
|
||||
|
||||
### DIRECT SDK (NO PROFILES)
|
||||
|
||||
```typescript
|
||||
import Supermemory from 'supermemory'
|
||||
import { Supermemory } from "supermemory"
|
||||
|
||||
const client = new Supermemory()
|
||||
|
||||
// Search for relevant memories
|
||||
const results = await client.search({
|
||||
q: userMessage,
|
||||
containerTag: userId,
|
||||
searchMode: 'hybrid', // Searches memories + document chunks
|
||||
limit: 5
|
||||
// Search memories and document chunks
|
||||
const results = await client.search(userId, {
|
||||
query: userMessage,
|
||||
searchMode: "hybrid",
|
||||
limit: 5,
|
||||
})
|
||||
|
||||
// Build context
|
||||
const context = results.results.map(r => r.content).join('\n')
|
||||
const context = results.results
|
||||
.map((r) => r.memory ?? r.chunk)
|
||||
.filter(Boolean)
|
||||
.join("\n")
|
||||
|
||||
// Send to LLM with context
|
||||
const messages = [
|
||||
{ role: 'system', content: `Relevant context:\n${context}` },
|
||||
{ role: 'user', content: userMessage }
|
||||
{ role: "system", content: `Relevant context:\n${context}` },
|
||||
{ role: "user", content: userMessage },
|
||||
]
|
||||
|
||||
// Store the conversation
|
||||
await client.memories.add({
|
||||
await client.add(userId, {
|
||||
content: `user: ${userMessage}\nassistant: ${response}`,
|
||||
containerTag: userId
|
||||
id: conversationId,
|
||||
})
|
||||
```
|
||||
|
||||
|
|
@ -194,124 +213,134 @@ from supermemory import Supermemory
|
|||
client = Supermemory()
|
||||
|
||||
# With profiles (if they want it)
|
||||
profile_data = client.profile(
|
||||
container_tag=user_id,
|
||||
q=user_message # Include if OPTION A, omit if OPTION B
|
||||
profile = client.profile(user_id).profile
|
||||
related = client.search(user_id, query=user_message, search_mode="memories", limit=5)
|
||||
|
||||
context = "\n".join(
|
||||
[
|
||||
"Static:",
|
||||
*[m.memory for m in profile.static],
|
||||
"Dynamic:",
|
||||
*[m.memory for m in profile.dynamic],
|
||||
"Memories:",
|
||||
*[r.memory for r in related.results if r.memory],
|
||||
]
|
||||
)
|
||||
|
||||
context = f"""
|
||||
Static: {chr(10).join(profile_data.profile.static)}
|
||||
Dynamic: {chr(10).join(profile_data.profile.dynamic)}
|
||||
"""
|
||||
|
||||
# Store conversation
|
||||
client.add(content=f"user: {user_message}\\nassistant: {response}", container_tag=user_id)
|
||||
client.add(
|
||||
user_id,
|
||||
content=f"user: {user_message}\nassistant: {response}",
|
||||
id=conversation_id,
|
||||
)
|
||||
```
|
||||
|
||||
### DIRECT API
|
||||
|
||||
```bash
|
||||
# Add memory
|
||||
curl -X POST https://api.supermemory.ai/v3/documents \
|
||||
curl -X POST https://api.supermemory.ai/ns/user_123/document \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "conversation", "containerTag": "userId"}'
|
||||
-d '{"content": "conversation", "id": "conversation_1"}'
|
||||
|
||||
# Get profile
|
||||
curl -X POST https://api.supermemory.ai/v4/profile \
|
||||
curl -X POST https://api.supermemory.ai/ns/user_123/profile \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTag": "userId", "q": "search query"}'
|
||||
-d '{}'
|
||||
|
||||
# Search
|
||||
curl -X POST https://api.supermemory.ai/v4/search \
|
||||
curl -X POST https://api.supermemory.ai/ns/user_123/search \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"q": "query", "containerTag": "userId", "searchMode": "hybrid"}'
|
||||
-d '{"query": "query", "searchMode": "hybrid"}'
|
||||
```
|
||||
|
||||
## STEP 6: FILE UPLOADS (if they need it)
|
||||
## STEP 7: FILE UPLOADS (if they need it)
|
||||
|
||||
```typescript
|
||||
// Files are automatically extracted (PDFs, images with OCR, videos with transcription)
|
||||
const formData = new FormData()
|
||||
formData.append('file', fileBlob)
|
||||
formData.append('containerTag', userId)
|
||||
formData.append("file", fileBlob)
|
||||
|
||||
await fetch('https://api.supermemory.ai/v3/documents/file', {
|
||||
method: 'POST',
|
||||
await fetch(`https://api.supermemory.ai/ns/${userId}/document/file`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
},
|
||||
body: formData
|
||||
body: formData,
|
||||
})
|
||||
|
||||
// Processing is async - check status before assuming searchable
|
||||
// GET /v3/documents/{documentId}
|
||||
// Processing is async: client.documents.get(userId, documentId)
|
||||
// wait for system.status === "done" for chunks (searchable content), and system.dreamingStatus === "done" for memories
|
||||
```
|
||||
|
||||
## STEP 7: SEARCH MODES
|
||||
## STEP 8: SEARCH MODES
|
||||
|
||||
```typescript
|
||||
// HYBRID (recommended) - searches memories + document chunks
|
||||
searchMode: 'hybrid'
|
||||
// HYBRID (default) - learned memories plus source chunks
|
||||
searchMode: "hybrid"
|
||||
|
||||
// MEMORIES ONLY - just extracted memories, no original text
|
||||
searchMode: 'memories'
|
||||
// MEMORIES ONLY - learned memories, no original text
|
||||
searchMode: "memories"
|
||||
|
||||
// CHUNKS ONLY - source passages for RAG
|
||||
searchMode: "chunks"
|
||||
```
|
||||
|
||||
## STEP 8: METADATA FILTERS (if they need secondary filtering)
|
||||
## STEP 9: METADATA FILTERS (if they need secondary filtering)
|
||||
|
||||
```typescript
|
||||
await client.search({
|
||||
q: query,
|
||||
containerTag: userId,
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: 'type', value: 'conversation', type: 'string_equal' },
|
||||
{ key: 'timestamp', value: '2024', type: 'string_contains' }
|
||||
]
|
||||
}
|
||||
await client.search(userId, {
|
||||
query,
|
||||
filter: {
|
||||
operator: "and",
|
||||
operands: [
|
||||
{ field: "type", operator: "eq", value: "conversation" },
|
||||
{ field: "title", operator: "contains", value: "2024" },
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## KEY POINTS:
|
||||
|
||||
1. Configure settings FIRST with filterPrompt
|
||||
1. Every write and every search names one namespace in the URL path
|
||||
2. User profiles = automatic facts about users (profile.static + profile.dynamic)
|
||||
3. profile({ containerTag, q }) combines profile + search in ONE call
|
||||
4. Search modes: 'hybrid' (recommended) or 'memories'
|
||||
3. `profile(namespace)` takes no query; call `search(namespace, { query })` for message-specific memories
|
||||
4. Search modes: 'hybrid' (default), 'memories', or 'chunks'
|
||||
5. File extraction is automatic - no config needed
|
||||
6. Store conversations after each interaction
|
||||
7. containerTag should match what you put in filterPrompt
|
||||
6. Store conversations after each interaction under a stable `id` per conversation
|
||||
7. Processing is async: `system.status` tracks extraction, and memories are ready when `system.dreamingStatus` is `done` (it reads `dreaming` while they are generated). Pass `dreaming: "instant"` only when memories must be generated right away (it bills one extra operation per document)
|
||||
|
||||
## TESTING:
|
||||
|
||||
```bash
|
||||
# 1. Configure settings
|
||||
curl -X PATCH https://api.supermemory.ai/v3/settings \
|
||||
# 1. Add test memory, processed right away
|
||||
curl -X POST https://api.supermemory.ai/ns/test_user/document \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"shouldLLMFilter": true, "filterPrompt": "..."}'
|
||||
-d '{"content": "Test", "dreaming": "instant"}'
|
||||
|
||||
# 2. Add test memory
|
||||
curl -X POST https://api.supermemory.ai/v3/documents \
|
||||
# 2. Get profile
|
||||
curl -X POST https://api.supermemory.ai/ns/test_user/profile \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "Test", "containerTag": "test_user"}'
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
# 3. Get profile
|
||||
curl -X POST https://api.supermemory.ai/v4/profile \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTag": "test_user"}'
|
||||
Or smoke-test from the terminal with the CLI:
|
||||
|
||||
```bash
|
||||
npx supermemory add "Test" --namespace test_user --dreaming instant
|
||||
npx supermemory profile --namespace test_user
|
||||
```
|
||||
|
||||
## NOW:
|
||||
|
||||
1. Ask me the 5 questions above
|
||||
2. Generate complete working code based on my answers
|
||||
3. Include installation, settings config, and full integration
|
||||
3. Include installation, namespace strategy, and full integration
|
||||
|
||||
**DOCS:** https://supermemory.ai/docs
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ const model = withSupermemory(openai("gpt-5"), {
|
|||
|
||||
## Memory tools
|
||||
|
||||
Add memory capabilities to AI agents with search, add, and fetch operations.
|
||||
Add memory capabilities to AI agents. `supermemoryTools` returns seven tools: `searchMemories`, `addMemory`, `getProfile`, `documentList`, `documentAdd`, `documentDelete`, and `memoryForget`.
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai"
|
||||
|
|
@ -223,6 +223,6 @@ const result = await streamText({
|
|||
{ success: true, results: [...], count: 5 }
|
||||
|
||||
// addMemory result
|
||||
{ success: true, memory: { id: "mem_123", ... } }
|
||||
{ success: true, memory: { id: "doc_123", status: "queued" } }
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ Container tags allow you to organize memories across multiple dimensions:
|
|||
memory_agent = SupermemoryCartesiaAgent(
|
||||
agent=base_agent,
|
||||
container_tag="user-alice", # Primary: user ID
|
||||
custom_id=call_request.call_id, # Required: groups all messages
|
||||
container_tags=["org-acme", "prod"], # Additional: organization, environment
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ icon: "/images/claude-code-icon.svg"
|
|||
|
||||
## Authenticate
|
||||
|
||||
Create a Supermemory API key from the [API Keys](https://console.supermemory.ai/keys) page in the console, then add it to your shell profile:
|
||||
Start a Claude Code session and the plugin opens a browser login, then saves the key to `~/.supermemory-claude/credentials.json`.
|
||||
|
||||
Or create a Supermemory API key from the [API Keys](https://console.supermemory.ai/keys) page in the console and add it to your shell profile:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS / Linux (zsh)">
|
||||
|
|
@ -69,28 +71,29 @@ Create a Supermemory API key from the [API Keys](https://console.supermemory.ai/
|
|||
|
||||
Once installed, the plugin runs automatically:
|
||||
|
||||
- **Reasoned recall** — Before each turn, Claude decides whether recalling memory would help the current message, and only searches when it is worth it.
|
||||
- **Auto-capture** — Conversations and important tool usage are saved for later sessions.
|
||||
- **Team memory** — Project knowledge is shared separately from personal memories.
|
||||
- **Explicit skills** — Ask Claude to search or save memories when you need control.
|
||||
- **Session context** — At session start, profile facts for this project are loaded into context.
|
||||
- **Direct recall** — Before Claude sees each substantive prompt, the hook searches Supermemory and injects fresh matches. Set `recallDirective` to switch to advisory mode, where Claude decides when to search.
|
||||
- **Auto-capture** — After each Claude response (the Stop hook), conversation content added since the last save is captured in the background.
|
||||
- **Shared repo memory** — Captures go to one repository container shared with the Codex, OpenCode, and Cursor plugins, tagged with `sm_scope: personal` metadata.
|
||||
- **MCP tools** — The hosted Supermemory MCP tools (`search_memory`, `add_memory`, and more) use the same credentials. `search_memory` and the legacy camelCase read tools (`listMemories`, `listDocuments`, `getDocument`, `listSpaces`, `whoAmI`) are approved automatically; other tools, including `list_memories`, `list_documents`, `get_document` and `get_profile`, still ask for approval. For deeper history, Claude can also use the `context-gatherer` agent.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
| --- | --- |
|
||||
| `/supermemory:index` | Index codebase architecture and patterns |
|
||||
| `/supermemory:project-config` | Configure project-level settings |
|
||||
| `/supermemory:logout` | Clear saved credentials |
|
||||
| `/supermemory:session` | Show a clickable URL for the current session document |
|
||||
| `/supermemory:status` | Show authentication status |
|
||||
| `/supermemory:index` | Index codebase architecture, conventions, and how to run it into the project container |
|
||||
| `/supermemory:status` | Show authentication status, API and MCP reachability, and the active project container |
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment variables
|
||||
|
||||
```bash
|
||||
SUPERMEMORY_CC_API_KEY=sm_... # Required
|
||||
SUPERMEMORY_DEBUG=true # Optional: enable debug logging
|
||||
SUPERMEMORY_CC_API_KEY=sm_... # Optional: browser login is used when unset
|
||||
SUPERMEMORY_API_URL=... # Optional: override the REST API base URL
|
||||
SUPERMEMORY_REPO_TAG=... # Optional: override the project container
|
||||
SUPERMEMORY_ISOLATE_WORKTREES=true # Optional: key the container on the worktree path
|
||||
SUPERMEMORY_DEBUG=true # Optional: enable debug logging
|
||||
```
|
||||
|
||||
### Global settings
|
||||
|
|
@ -118,13 +121,13 @@ Create `~/.supermemory-claude/settings.json`:
|
|||
|
||||
### Project config
|
||||
|
||||
Per-repo overrides in `.claude/.supermemory-claude/config.json`. Run `/supermemory:project-config` or create manually:
|
||||
Per-repo overrides in `.claude/.supermemory-claude/config.json`. Create the file manually:
|
||||
|
||||
```json
|
||||
{
|
||||
"apiKey": "sm_...",
|
||||
"baseUrl": "https://api.supermemory.ai",
|
||||
"repoContainerTag": "my-team-project",
|
||||
"namespace": "my-team-project",
|
||||
"signalExtraction": true
|
||||
}
|
||||
```
|
||||
|
|
@ -133,8 +136,11 @@ Per-repo overrides in `.claude/.supermemory-claude/config.json`. Run `/supermemo
|
|||
| --- | --- |
|
||||
| `apiKey` | Project-specific API key |
|
||||
| `baseUrl` | Supermemory API URL (use for self-hosted) |
|
||||
| `personalContainerTag` | Override personal container |
|
||||
| `repoContainerTag` | Override team container tag |
|
||||
| `apiVersion` | `v5` or `legacy`. The hosted API uses v5; custom `baseUrl` values default to `legacy`. Set `v5` to use v5 with a self-hosted server 0.0.9 or newer |
|
||||
| `namespace` | Override the project container. Takes precedence over `repoContainerTag` |
|
||||
| `repoContainerTag` | Override the project container (checked before `SUPERMEMORY_REPO_TAG`) |
|
||||
|
||||
API key precedence is `SUPERMEMORY_CC_API_KEY`, project `apiKey`, then `~/.supermemory-claude/credentials.json`.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
|
|
|||
|
|
@ -84,14 +84,9 @@ console.log(response.content[0])
|
|||
import { createClaudeMemoryTool } from "@supermemory/tools/claude-memory"
|
||||
|
||||
const memoryTool = createClaudeMemoryTool(process.env.SUPERMEMORY_API_KEY!, {
|
||||
// Scope memories to a project or user
|
||||
namespace: "my-app",
|
||||
|
||||
// Or use container tags for more flexibility
|
||||
// Scope memories to a project or user (default: "sm_project_default")
|
||||
namespace: "user-123",
|
||||
|
||||
// Custom memory container prefix (default: "claude_memory")
|
||||
|
||||
// Custom API endpoint
|
||||
baseUrl: "https://custom.api.com",
|
||||
})
|
||||
|
|
@ -121,7 +116,7 @@ All memory paths must start with `/memories/`:
|
|||
```
|
||||
|
||||
<Note>
|
||||
Paths are normalized for storage: `/memories/preferences` is stored as `--memories--preferences`.
|
||||
Each file is stored as one document in the namespace, tagged with `metadata.source = "claude-memory"`. Its document ID is a reversible encoding of the path: `/memories/preferences.txt` is stored as `cm_memories_s_preferences_d_txt`.
|
||||
</Note>
|
||||
|
||||
## Commands reference
|
||||
|
|
@ -199,7 +194,7 @@ const memoryTool = createClaudeMemoryTool(process.env.SUPERMEMORY_API_KEY!, {
|
|||
})
|
||||
|
||||
async function runConversation() {
|
||||
const messages: Anthropic.MessageParam[] = []
|
||||
const messages: Anthropic.Beta.BetaMessageParam[] = []
|
||||
|
||||
// Helper to chat with memory
|
||||
async function chat(userMessage: string) {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ description: "Persistent memory for the OpenAI Codex CLI with the codex-supermem
|
|||
icon: "/images/codex.svg"
|
||||
---
|
||||
|
||||
[codex-supermemory](https://github.com/supermemoryai/codex-supermemory) wires Supermemory into the [OpenAI Codex CLI](https://github.com/openai/codex) via hooks and skills. Your agent gets **two layers of memory**:
|
||||
[codex-supermemory](https://github.com/supermemoryai/codex-supermemory) wires Supermemory into the [OpenAI Codex CLI](https://github.com/openai/codex) via hooks and the hosted Supermemory MCP server. Your agent gets **two layers of memory**:
|
||||
|
||||
- **Implicit** (hooks) — automatically recalls context before each prompt and captures conversations incrementally during the session.
|
||||
- **Explicit** (skills) — lets you or the agent save, search, and manage memories on demand.
|
||||
- **Implicit** (hooks) — automatically recalls context before each prompt and captures completed turns in the background.
|
||||
- **Explicit** (MCP tools) — lets you or the agent search, save, list, and forget memories on demand.
|
||||
|
||||
<Tip>
|
||||
**Prefer to keep everything on your machine?** This plugin works with [self-hosted Supermemory](/self-hosting/overview) — run `npx supermemory local`, then `export SUPERMEMORY_API_URL="http://localhost:6767"` (or set `baseUrl` in `~/.codex/supermemory.json`) and use the API key printed on first boot.
|
||||
|
|
@ -22,21 +22,18 @@ npx codex-supermemory@latest install
|
|||
|
||||
This command:
|
||||
|
||||
- Copies hook and skill scripts to `~/.codex/supermemory/`
|
||||
- Enables `codex_hooks` in `~/.codex/config.toml`
|
||||
- Registers `UserPromptSubmit` (recall) and `Stop` (flush) hooks in `~/.codex/hooks.json`
|
||||
- Installs explicit memory skills under `~/.codex/skills/`
|
||||
- Copies the pre-bundled hook scripts and MCP proxy to `~/.codex/supermemory/`
|
||||
- Registers the `supermemory` MCP server in `~/.codex/config.toml`
|
||||
- Registers `SessionStart`, `UserPromptSubmit`, `PreToolUse`, and `Stop` hooks in `~/.codex/hooks.json`
|
||||
- Installs the `supermemory-status` and `supermemory-index` skills under `~/.codex/skills/`
|
||||
|
||||
Restart Codex CLI after installing.
|
||||
|
||||
## Authenticate
|
||||
|
||||
**Browser auth is preferred.** Start Codex CLI — on your first prompt a browser window opens to authenticate with Supermemory.
|
||||
**Browser auth is preferred.** Start Codex CLI — a browser window opens to authenticate with Supermemory.
|
||||
|
||||
Alternatively:
|
||||
|
||||
- Use `$supermemory-login` / `/supermemory-login` inside Codex
|
||||
- Or set an API key from [API Keys](https://console.supermemory.ai/keys):
|
||||
Alternatively, set an API key from [API Keys](https://console.supermemory.ai/keys):
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS / Linux (zsh)">
|
||||
|
|
@ -65,41 +62,42 @@ Once installed, the plugin runs on every Codex session:
|
|||
|
||||
| Hook | Event | What it does |
|
||||
|------|-------|--------------|
|
||||
| `recall` | `UserPromptSubmit` | Captures new turns (every N prompts), searches Supermemory, injects memories + profile as `additionalContext` |
|
||||
| `flush` | `Stop` | Captures any remaining turns at session end so nothing is lost |
|
||||
| `session-start` | `SessionStart` | Loads persistent and recent profile context for the session |
|
||||
| `recall` | `UserPromptSubmit` | Searches Supermemory directly for substantive prompts and injects fresh relevant memories |
|
||||
| `recall-approve` | `PreToolUse` | Auto-allows `search_memory` and the legacy camelCase read tools (`listMemories`, `listDocuments`, `getDocument`, `listSpaces`, `whoAmI`); other Supermemory MCP tools still ask |
|
||||
| `flush` | `Stop` | Captures completed turns in the background |
|
||||
|
||||
- **Incremental capture** — Memories are saved every N turns (default: 3) so mid-session context is available for later prompts in the same session.
|
||||
- **Recall modes** — Set `recallMode` to `"advisory"` to let the model decide when to search, or `"off"` to disable prompt recall.
|
||||
- **Privacy** — Content wrapped in `<private>...</private>` is redacted before storage.
|
||||
|
||||
### Memory scopes
|
||||
|
||||
| Tag | Derived from | Description |
|
||||
|-----|-------------|-------------|
|
||||
| User | `git config user.email` (hashed) | Preferences and workflows across projects |
|
||||
| Project | Git common directory (hashed) | Repo-scoped knowledge (worktrees share by default) |
|
||||
Codex, Claude Code, and OpenCode use one container per repository:
|
||||
|
||||
Override tags in `~/.codex/supermemory.json` if needed:
|
||||
```text
|
||||
repo_<project-name>__<remote-hash>
|
||||
```
|
||||
|
||||
Automatic captures go to this container with `sm_scope: personal` metadata. Explicit saves through the MCP tools are passed to the hosted server unchanged, so they land in your account's active space, not the repository container. The hash comes from the normalized Git remote, so clones and linked worktrees share memory while same-named repositories do not collide. Codex still reads the older `codex_user_*`, `codex_project_*`, and other per-tool containers, so existing memories stay searchable.
|
||||
|
||||
Override the container in `~/.codex/supermemory.json` if needed:
|
||||
|
||||
```json
|
||||
{
|
||||
"userContainerTag": "my-custom-user-tag",
|
||||
"projectContainerTag": "my-custom-project-tag"
|
||||
}
|
||||
```
|
||||
|
||||
Set `SUPERMEMORY_ISOLATE_WORKTREES=true` to keep each worktree isolated.
|
||||
|
||||
## Explicit memory skills
|
||||
## Explicit memory
|
||||
|
||||
Search, save, list, and forget go through the hosted [Supermemory MCP](/supermemory-mcp/mcp) tools, using the same credentials as the hooks. The installer also adds two skills:
|
||||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| `supermemory-search` | Search memories by natural-language query |
|
||||
| `supermemory-save` | Save important project knowledge |
|
||||
| `supermemory-forget` | Remove outdated or incorrect memories |
|
||||
| `supermemory-profile` | Show remembered profile facts |
|
||||
| `supermemory-status` | Check connection, hooks, config, and skills |
|
||||
| `supermemory-login` | Re-authenticate with Supermemory |
|
||||
| `supermemory-logout` | Remove saved local credentials |
|
||||
| `supermemory-status` | Check the saved credential, API reachability, active project container, and account |
|
||||
| `supermemory-index` | Explore the repository and save focused memories about architecture, conventions, and how to run it |
|
||||
|
||||
Example prompts:
|
||||
|
||||
|
|
@ -122,7 +120,7 @@ npx codex-supermemory status
|
|||
npx codex-supermemory uninstall
|
||||
```
|
||||
|
||||
This removes hook registrations and skill scripts. Your existing memories in Supermemory are preserved.
|
||||
This removes the hook registrations, MCP server entry, and skills. Your existing memories in Supermemory are preserved.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -136,8 +134,7 @@ Create `~/.codex/supermemory.json` to override defaults:
|
|||
"maxMemories": 5,
|
||||
"maxProfileItems": 5,
|
||||
"injectProfile": true,
|
||||
"containerTagPrefix": "codex",
|
||||
"autoSaveEveryTurns": 3,
|
||||
"recallMode": "direct",
|
||||
"signalExtraction": false,
|
||||
"debug": false
|
||||
}
|
||||
|
|
@ -147,12 +144,14 @@ Create `~/.codex/supermemory.json` to override defaults:
|
|||
|--------|---------|-------------|
|
||||
| `apiKey` | — | API key (env / browser auth preferred) |
|
||||
| `baseUrl` | `https://api.supermemory.ai` | API base URL (`SUPERMEMORY_API_URL` overrides) |
|
||||
| `apiVersion` | auto | `v5` or `legacy`. The hosted API uses v5; custom URLs default to `legacy`. Set `v5` to use v5 with a self-hosted server 0.0.9 or newer |
|
||||
| `similarityThreshold` | `0.6` | Minimum match score for recall (0–1) |
|
||||
| `maxMemories` | `5` | Max memories injected per prompt |
|
||||
| `maxProfileItems` | `5` | Max profile facts injected per prompt |
|
||||
| `injectProfile` | `true` | Include user profile in context |
|
||||
| `containerTagPrefix` | `"codex"` | Prefix for auto-generated container tags |
|
||||
| `autoSaveEveryTurns` | `3` | Save memories every N turns |
|
||||
| `projectContainerTag` | auto (per repo) | Override the unified project container |
|
||||
| `recallMode` | `"direct"` | `"direct"`, `"advisory"`, or `"off"` |
|
||||
| `recallDirective` | built-in | Context injected when `recallMode` is `"advisory"` |
|
||||
| `signalExtraction` | `false` | Only capture turns with signal keywords |
|
||||
| `debug` | `false` | Write debug logs to `~/.codex-supermemory.log` |
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ Credentials are stored in `~/.supermemory-cursor/credentials.json`.
|
|||
| Session profile | Loads your persistent profile when a Cursor conversation starts |
|
||||
| Automatic recall | Searches on substantive prompts, deduplicates results, and injects them after the first supported tool result |
|
||||
| Incremental capture | Saves each completed turn, and retries unsaved transcript deltas at session end |
|
||||
| MCP tools | Explicit memory control from any Cursor AI session |
|
||||
| MCP tools | The hosted Supermemory MCP tools, proxied over stdio with the same credentials as the hooks |
|
||||
| Context gatherer | Fans out targeted searches before substantial work |
|
||||
| Always-on rule | Makes the agent recall relevant history proactively |
|
||||
|
||||
|
|
@ -93,6 +93,7 @@ Credentials are stored in `~/.supermemory-cursor/credentials.json`.
|
|||
| `memory-save` | Skill | Save an insight, decision, or solution worth keeping |
|
||||
| `memory-search` | Skill | Search memory for past work, bugs, and decisions |
|
||||
| `supermemory-context-gatherer` | Agent | Gather deep background before substantial work |
|
||||
| `supermemory-index` | Command | Index codebase architecture and patterns into Supermemory |
|
||||
| `supermemory-setup` | Command | Connect Supermemory to Cursor |
|
||||
| `supermemory-status` | Command | Check authentication and live connectivity |
|
||||
| `supermemory-config` | Command | Create or edit the project config file |
|
||||
|
|
@ -100,25 +101,18 @@ Credentials are stored in `~/.supermemory-cursor/credentials.json`.
|
|||
|
||||
## MCP tools
|
||||
|
||||
The plugin proxies the hosted [Supermemory MCP](/supermemory-mcp/mcp) server (`https://mcp.supermemory.ai/mcp`) over stdio, using the same credentials as the hooks. Claude Code and Codex use the same server, so all three agents see one tool set. The bundled rule, skills, and agent mainly use these:
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `supermemory_get_config` | Show current config, resolved container tags, and config file paths |
|
||||
| `supermemory_set_config` | Update config at project or global scope |
|
||||
| `supermemory_containers` | Show what `user` and `project` container tags resolve to |
|
||||
| `supermemory_search` | Search memories by query |
|
||||
| `supermemory_add` | Save new information to memory |
|
||||
| `supermemory_list` | List stored memories |
|
||||
| `supermemory_forget` | Delete a memory by id or content |
|
||||
| `supermemory_profile` | Get your user profile summary |
|
||||
| `search_memory` | Search memories in one space |
|
||||
| `add_memory` | Save a memory |
|
||||
| `forget_memory` | Forget outdated memories |
|
||||
| `list_memories` | List recent memories with their IDs |
|
||||
| `list_documents` / `get_document` | Browse and read stored documents |
|
||||
| `list_spaces` / `who_am_i` | Resolve a named space, or report the active account and space |
|
||||
|
||||
Every tool that takes a `container` argument accepts:
|
||||
|
||||
- `"user"` (default): personal memories for the current repository
|
||||
- `"project"`: project knowledge for the current repository
|
||||
- `"both"`: both scopes plus compatible legacy memories
|
||||
- any custom string: used as a raw container tag
|
||||
|
||||
`user` and `project` write to the same repository container. The `sm_scope` metadata field is what keeps personal and session memories separate from explicit project knowledge when an agent asks for one scope.
|
||||
Pass `containerTag` on every call, using the tag from the `<supermemory-context>` block the session-start hook injects. Without it, the hosted server uses the account's active space, and this project's hook recall will not find the memory. Config lives in files rather than tools: see [Configuration](#configuration) or run `/supermemory-config`.
|
||||
|
||||
## Container tags
|
||||
|
||||
|
|
@ -144,6 +138,9 @@ The plugin still reads the former `cursor_user_*` and `cursor_project_*` tags, a
|
|||
|----------|-------------|
|
||||
| `SUPERMEMORY_API_KEY` | API key (overrides all other sources) |
|
||||
| `SUPERMEMORY_API_URL` | Override the Supermemory API base URL |
|
||||
| `SUPERMEMORY_BASE_URL` | API base URL fallback when `SUPERMEMORY_API_URL` is unset |
|
||||
| `SUPERMEMORY_API_VERSION` | `v5` or `legacy` REST contract; overrides config `apiVersion` |
|
||||
| `SUPERMEMORY_MCP_URL` | Override the hosted MCP endpoint the proxy connects to |
|
||||
| `SUPERMEMORY_REPO_TAG` | Override the unified repository container tag |
|
||||
| `SUPERMEMORY_USER_TAG` | Legacy Cursor personal container to continue reading |
|
||||
| `SUPERMEMORY_PROJECT_TAG` | Legacy Cursor project container to continue reading |
|
||||
|
|
@ -183,6 +180,7 @@ The plugin still reads the former `cursor_user_*` and `cursor_project_*` tags, a
|
|||
|--------|---------|-------------|
|
||||
| `apiKey` | — | Project-specific API key |
|
||||
| `baseUrl` | Supermemory API | Override the Supermemory API base URL |
|
||||
| `apiVersion` | v5 for the hosted API, `legacy` for custom URLs | Set `v5` to use v5 with a self-hosted server 0.0.9 or newer |
|
||||
| `repoContainerTag` | derived from normalized Git remote or project path | Override the unified repository container |
|
||||
| `userContainerTag` | — | Legacy Cursor personal container to continue reading |
|
||||
| `projectContainerTag` | — | Legacy Cursor project container to continue reading |
|
||||
|
|
@ -193,7 +191,7 @@ The plugin still reads the former `cursor_user_*` and `cursor_project_*` tags, a
|
|||
| `signalKeywords` | `remember`, `architecture`, `decision`, `bug`, `fix` | Keywords that trigger signal-based capture |
|
||||
| `signalTurnsBefore` | `3` | Number of nearby turns retained around a signal |
|
||||
|
||||
You can also set these from the agent with `supermemory_set_config`, or edit the file by hand.
|
||||
Edit the file by hand, or run the `/supermemory-config` command.
|
||||
|
||||
## Log out
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ icon: "/images/hermes.svg"
|
|||
---
|
||||
|
||||
|
||||
[Hermes agent](https://github.com/NousResearch/hermes-agent) ships a native **supermemory** memory provider: semantic long-term memory, profile recall, search, explicit memory tools, and session-aware ingest — not a bolt-on script the model might skip. Hermes runs across Telegram, Discord, Slack, WhatsApp, Signal, and the CLI from one gateway.
|
||||
The [hermes-supermemory](https://github.com/supermemoryai/hermes-supermemory) plugin is the **supermemory** memory provider for [Hermes agent](https://github.com/NousResearch/hermes-agent): semantic long-term memory, profile recall, search, explicit memory tools, and per-turn conversation capture — not a bolt-on script the model might skip. It previously shipped inside Hermes core and is now maintained by Supermemory as a Hermes plugin. Hermes runs across Telegram, Discord, Slack, WhatsApp, Signal, and the CLI from one gateway.
|
||||
|
||||
Hermes also ships with built-in `MEMORY.md` and `USER.md` files. Supermemory adds structure and isolation (profile-scoped and optional multi-container tags), plus retrieval that goes beyond a single flat file.
|
||||
|
||||
|
|
@ -18,13 +18,13 @@ Create a supermemory API key from the [API Keys](https://console.supermemory.ai/
|
|||
## Install the memory provider
|
||||
|
||||
```bash
|
||||
pip install supermemory
|
||||
```
|
||||
|
||||
```bash
|
||||
hermes plugins install supermemoryai/hermes-supermemory
|
||||
hermes plugins enable supermemory
|
||||
hermes memory setup
|
||||
```
|
||||
|
||||
Hermes installs the plugin's dependency, the `supermemory` Python SDK (`>=5.0.0,<6`), into its own environment.
|
||||
|
||||
Select **supermemory** when prompted and paste your API key.
|
||||
|
||||
Or set the provider and key manually:
|
||||
|
|
@ -41,9 +41,8 @@ echo 'SUPERMEMORY_API_KEY=sm_...' >> ~/.hermes/.env
|
|||
Once configured, the provider runs through Hermes’s normal memory lifecycle:
|
||||
|
||||
- **Prefetch** — Relevant memory context can be loaded before each turn.
|
||||
- **Turn capture** — Cleaned user/assistant turns can be stored after each completed response.
|
||||
- **Session ingest** — The full session can be ingested at session end for richer graph updates.
|
||||
- **Explicit tools** — Search, store, forget, and profile tools are available to the model when appropriate.
|
||||
- **Turn capture** — After each completed turn, the conversation is saved as one document per conversation, rewritten in full, so edits and context compaction never store it twice. Remaining turns are flushed at session end.
|
||||
- **Explicit tools** — Search, store, forget, profile, and read-document tools are available to the model when appropriate.
|
||||
- **Built-in file memory** — This does not replace `MEMORY.md` / `USER.md`; mirroring behavior depends on Hermes version and config (see upstream README).
|
||||
|
||||
## Tools
|
||||
|
|
@ -56,6 +55,7 @@ Kebab-case names are registered for the agent; snake_case aliases remain support
|
|||
| `supermemory-search` | `supermemory_search` | Search by semantic similarity. |
|
||||
| `supermemory-forget` | `supermemory_forget` | Forget a memory by ID or best-match query. |
|
||||
| `supermemory-profile` | `supermemory_profile` | Retrieve persistent profile and recent context. |
|
||||
| `supermemory-read-document` | `supermemory_read_document` | Read a stored document, such as a past conversation, by the `document_id` from search results. |
|
||||
|
||||
## Commands
|
||||
|
||||
|
|
@ -70,8 +70,9 @@ hermes memory setup
|
|||
These variables configure the supermemory provider (for example in your shell or Hermes env file):
|
||||
|
||||
```bash
|
||||
SUPERMEMORY_API_KEY=sm_... # Required
|
||||
SUPERMEMORY_CONTAINER_TAG=hermes-work # Optional: overrides container tag from config
|
||||
SUPERMEMORY_API_KEY=sm_... # Required
|
||||
SUPERMEMORY_CONTAINER_TAG=hermes-work # Optional: overrides container tag from config
|
||||
SUPERMEMORY_BASE_URL=http://localhost:6767 # Optional: API endpoint when base_url is not set in config
|
||||
```
|
||||
|
||||
## Multi-container tags
|
||||
|
|
@ -103,7 +104,7 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
See the [upstream plugin README](https://github.com/NousResearch/hermes-agent/tree/main/plugins/memory/supermemory) for the exact schema and any newer options.
|
||||
See the [plugin README](https://github.com/supermemoryai/hermes-supermemory) for the exact schema and any newer options.
|
||||
|
||||
## Config file
|
||||
|
||||
|
|
@ -111,13 +112,16 @@ Create or edit `$HERMES_HOME/supermemory.json`. Common keys:
|
|||
|
||||
| Key | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `base_url` | `https://api.supermemory.ai` | API endpoint for hosted or self-hosted Supermemory. Takes priority over `SUPERMEMORY_BASE_URL`. |
|
||||
| `container_tag` | `hermes` | Tag for search/writes; use `{identity}` for profile-scoped tags (e.g. `hermes-{identity}` → `hermes-coder`). |
|
||||
| `auto_recall` | `true` | Inject memory context before turns. |
|
||||
| `auto_capture` | `true` | Store turns after each response. |
|
||||
| `max_recall_results` | `10` | Max items merged into context. |
|
||||
| `profile_frequency` | `50` | Profile on first turn and every N turns. |
|
||||
| `capture_mode` | `all` | How aggressively turns are captured. |
|
||||
| `search_mode` | `hybrid` | `hybrid`, `memories`, or `documents`. |
|
||||
| `search_mode` | `hybrid` | `hybrid`, `memories`, or `chunks` (`documents` is still accepted as an alias for `chunks`). |
|
||||
| `entity_context` | built-in | Extraction guidance passed to Supermemory. |
|
||||
| `dreaming` | `dynamic` | `dynamic` groups related conversations before forming memories; `instant` processes each one right away (billed as one extra operation). |
|
||||
| `api_timeout` | `5.0` | SDK / ingest timeout (seconds). |
|
||||
| `enable_custom_container_tags` | `false` | Set `true` to allow extra namespaces; see [Multi-container tags](#multi-container-tags) above. |
|
||||
| `custom_containers` | — | Allowlisted tags beyond the primary `container_tag`. |
|
||||
|
|
@ -136,12 +140,20 @@ Example profile-scoped container:
|
|||
|
||||
## Self-hosted API
|
||||
|
||||
If you run your own supermemory API, set **`base_url`** (and any other host-specific options) in `supermemory.json` or via env as documented in the [upstream plugin README](https://github.com/NousResearch/hermes-agent/tree/main/plugins/memory/supermemory) — alongside your key and container settings.
|
||||
If you run your own supermemory API, start it with `npx supermemory local` and note the API key it prints on first boot. Before running `hermes memory setup`, set **`base_url`** in `$HERMES_HOME/supermemory.json` so the setup connection probe also stays local:
|
||||
|
||||
```json
|
||||
{
|
||||
"base_url": "http://localhost:6767"
|
||||
}
|
||||
```
|
||||
|
||||
Then run `hermes memory setup` and enter the local server's API key.
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Hermes + plugin README" icon="/images/github-icon.svg" href="https://github.com/NousResearch/hermes-agent/tree/main/plugins/memory/supermemory">
|
||||
<Card title="Hermes plugin README" icon="/images/github-icon.svg" href="https://github.com/supermemoryai/hermes-supermemory">
|
||||
Full config table, env vars, and multi-container details.
|
||||
</Card>
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const response = await agent.generate("What do you know about me?")
|
|||
|
||||
```typescript
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), ... },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), ... },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456",
|
||||
|
|
@ -140,6 +140,7 @@ const agent = new Agent(withSupermemory(config, {
|
|||
id: "conv-456",
|
||||
mode: "full",
|
||||
}))
|
||||
```
|
||||
|
||||
### Mode Comparison
|
||||
|
||||
|
|
@ -157,7 +158,7 @@ Conversation saving is enabled by default (`addMemory: "always"`). Messages are
|
|||
|
||||
```typescript
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456", // Required: groups messages for contextual memory
|
||||
|
|
@ -173,7 +174,7 @@ To disable automatic saving:
|
|||
|
||||
```typescript
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456",
|
||||
|
|
@ -192,6 +193,7 @@ Customize how memories are formatted and injected. The template receives `userMe
|
|||
import { Agent } from "@mastra/core/agent"
|
||||
import { withSupermemory } from "@supermemory/tools/mastra"
|
||||
import type { MemoryPromptData } from "@supermemory/tools/mastra"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
const claudePrompt = (data: MemoryPromptData) => `
|
||||
<context>
|
||||
|
|
@ -205,7 +207,7 @@ const claudePrompt = (data: MemoryPromptData) => `
|
|||
`.trim()
|
||||
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456",
|
||||
|
|
@ -306,7 +308,7 @@ import { withSupermemory } from "@supermemory/tools/mastra"
|
|||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "fallback-conv", // Used only when RequestContext doesn't provide a threadId
|
||||
|
|
@ -334,7 +336,7 @@ Enable detailed logging for debugging:
|
|||
|
||||
```typescript
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456",
|
||||
|
|
@ -361,6 +363,8 @@ The wrapper correctly merges with existing processors in the config:
|
|||
const agent = new Agent(withSupermemory(
|
||||
{
|
||||
id: "my-assistant",
|
||||
name: "My Assistant",
|
||||
instructions: "You are a helpful assistant.",
|
||||
model: openai("gpt-4o"),
|
||||
inputProcessors: [myLoggingProcessor],
|
||||
outputProcessors: [myAnalyticsProcessor],
|
||||
|
|
@ -461,7 +465,7 @@ Processors gracefully handle errors without breaking the agent:
|
|||
```typescript
|
||||
// Missing API key throws immediately
|
||||
const agent = new Agent(withSupermemory(
|
||||
{ id: "my-assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{ id: "my-assistant", name: "My Assistant", model: openai("gpt-4o"), instructions: "..." },
|
||||
{
|
||||
namespace: "user-123",
|
||||
id: "conv-456",
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@ npm install @supermemory/memory-graph
|
|||
'use client'; // For Next.js App Router
|
||||
|
||||
import { MemoryGraph } from '@supermemory/memory-graph';
|
||||
import type { DocumentWithMemories } from '@supermemory/memory-graph';
|
||||
import type { GraphApiDocument } from '@supermemory/memory-graph';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function GraphPage() {
|
||||
const [documents, setDocuments] = useState<DocumentWithMemories[]>([]);
|
||||
const [documents, setDocuments] = useState<GraphApiDocument[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ Existing icon-based document nodes and connection styling remain the defaults. O
|
|||
|
||||
## Backend API route
|
||||
|
||||
Create an API route to fetch documents from Supermemory:
|
||||
Create an API route to fetch documents from Supermemory. The endpoint returns each document's memories as `memoryEntries` and its type as `type`; `MemoryGraph` reads `memories` and `documentType`, so map each document before returning it:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
|
|
@ -102,7 +102,14 @@ export async function GET() {
|
|||
});
|
||||
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data);
|
||||
return NextResponse.json({
|
||||
...data,
|
||||
documents: data.documents.map((doc: { type: string; memoryEntries: unknown[] }) => ({
|
||||
...doc,
|
||||
documentType: doc.type,
|
||||
memories: doc.memoryEntries,
|
||||
})),
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -121,7 +128,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
});
|
||||
|
||||
const data = await response.json();
|
||||
res.json(data);
|
||||
res.json({
|
||||
...data,
|
||||
documents: data.documents.map((doc: { type: string; memoryEntries: unknown[] }) => ({
|
||||
...doc,
|
||||
documentType: doc.type,
|
||||
memories: doc.memoryEntries,
|
||||
})),
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -137,7 +151,14 @@ app.get('/api/graph', async (req, res) => {
|
|||
});
|
||||
|
||||
const data = await response.json();
|
||||
res.json(data);
|
||||
res.json({
|
||||
...data,
|
||||
documents: data.documents.map((doc) => ({
|
||||
...doc,
|
||||
documentType: doc.type,
|
||||
memories: doc.memoryEntries,
|
||||
})),
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -151,13 +172,13 @@ app.get('/api/graph', async (req, res) => {
|
|||
|
||||
## Variants
|
||||
|
||||
**Console Variant** - Full-featured dashboard view (0.8x zoom, space selector visible):
|
||||
**Console Variant** - Full dashboard view: themed surface with a dot grid, nodes colored by theme:
|
||||
|
||||
```tsx
|
||||
<MemoryGraph documents={documents} variant="console" />
|
||||
```
|
||||
|
||||
**Consumer Variant** - Embedded widget view (0.5x zoom, space selector hidden):
|
||||
**Consumer Variant** - Embedded widget view: transparent surface, nodes colored by cluster:
|
||||
|
||||
```tsx
|
||||
<MemoryGraph documents={documents} variant="consumer" />
|
||||
|
|
@ -173,10 +194,11 @@ app.get('/api/graph', async (req, res) => {
|
|||
'use client';
|
||||
|
||||
import { MemoryGraph } from '@supermemory/memory-graph';
|
||||
import type { GraphApiDocument } from '@supermemory/memory-graph';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
export default function PaginatedGraph() {
|
||||
const [documents, setDocuments] = useState([]);
|
||||
const [documents, setDocuments] = useState<GraphApiDocument[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
|
@ -184,7 +206,7 @@ export default function PaginatedGraph() {
|
|||
|
||||
useEffect(() => { fetchPage(1, false); }, []);
|
||||
|
||||
const fetchPage = async (pageNum, append) => {
|
||||
const fetchPage = async (pageNum: number, append: boolean) => {
|
||||
pageNum === 1 ? setIsLoading(true) : setIsLoadingMore(true);
|
||||
|
||||
const res = await fetch(`/api/graph?page=${pageNum}&limit=100`);
|
||||
|
|
@ -210,8 +232,7 @@ export default function PaginatedGraph() {
|
|||
isLoading={isLoading}
|
||||
isLoadingMore={isLoadingMore}
|
||||
hasMore={hasMore}
|
||||
totalLoaded={documents.length}
|
||||
loadMoreDocuments={loadMore}
|
||||
onLoadMore={loadMore}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -227,17 +248,6 @@ export default function PaginatedGraph() {
|
|||
/>
|
||||
```
|
||||
|
||||
### Controlled space selection
|
||||
|
||||
```tsx
|
||||
<MemoryGraph
|
||||
documents={documents}
|
||||
selectedSpace={selectedSpace}
|
||||
onSpaceChange={setSelectedSpace}
|
||||
showSpacesSelector={false}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom empty state
|
||||
|
||||
```tsx
|
||||
|
|
@ -257,7 +267,7 @@ export default function PaginatedGraph() {
|
|||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `documents` | `DocumentWithMemories[]` | required | Array of documents to display |
|
||||
| `documents` | `GraphApiDocument[]` | `[]` | Array of documents to display |
|
||||
| `isLoading` | `boolean` | `false` | Shows loading indicator |
|
||||
| `error` | `Error \| null` | `null` | Error to display |
|
||||
| `variant` | `"console" \| "consumer"` | `"console"` | Visual variant |
|
||||
|
|
@ -269,71 +279,68 @@ export default function PaginatedGraph() {
|
|||
|------|------|---------|-------------|
|
||||
| `isLoadingMore` | `boolean` | `false` | Shows indicator when loading more |
|
||||
| `hasMore` | `boolean` | `false` | Whether more documents available |
|
||||
| `totalLoaded` | `number` | - | Total documents currently loaded |
|
||||
| `loadMoreDocuments` | `() => Promise<void>` | - | Callback to load more |
|
||||
| `autoLoadOnViewport` | `boolean` | `true` | Auto-load when 80% visible |
|
||||
| `onLoadMore` | `() => void` | - | Called to load more, for example when the user zooms out past the loaded nodes |
|
||||
| `totalCount` | `number` | - | Total document count shown by the loading indicator |
|
||||
|
||||
### Display props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `showSpacesSelector` | `boolean` | variant-based | Show space filter dropdown |
|
||||
| `highlightDocumentIds` | `string[]` | `[]` | Document IDs to highlight |
|
||||
| `highlightsVisible` | `boolean` | `true` | Whether highlights shown |
|
||||
| `occludedRightPx` | `number` | `0` | Pixels occluded on right |
|
||||
|
||||
### Controlled state props
|
||||
|
||||
| Prop | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `selectedSpace` | `string` | Currently selected space (use `"all"` for all) |
|
||||
| `onSpaceChange` | `(spaceId: string) => void` | Callback when space changes |
|
||||
| `memoryLimit` | `number` | Max memories per document when space selected |
|
||||
| `maxNodes` | `number` | - | Maximum number of nodes to display |
|
||||
| `colors` | `Partial<GraphThemeColors>` | - | Theme color overrides |
|
||||
| `labels` | `MemoryGraphLabels` | - | User-facing label overrides |
|
||||
| `appearance` | `GraphAppearance` | - | Opt-in document node and connection styles (see above) |
|
||||
| `openDocumentOnEnter` | `boolean` | `false` | Enable the Enter action that calls `onOpenDocument` |
|
||||
| `onOpenDocument` | `(documentId: string) => void` | - | Called when the user opens a document |
|
||||
|
||||
---
|
||||
|
||||
## Data types
|
||||
|
||||
### DocumentWithMemories
|
||||
### GraphApiDocument
|
||||
|
||||
```typescript
|
||||
interface DocumentWithMemories {
|
||||
interface GraphApiDocument {
|
||||
id: string;
|
||||
customId?: string | null;
|
||||
title?: string | null;
|
||||
title: string | null;
|
||||
summary: string | null;
|
||||
documentType: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
memories: GraphApiMemory[];
|
||||
}
|
||||
```
|
||||
|
||||
### GraphApiMemory
|
||||
|
||||
```typescript
|
||||
interface GraphApiMemory {
|
||||
id: string;
|
||||
memory: string;
|
||||
content?: string | null;
|
||||
summary?: string | null;
|
||||
url?: string | null;
|
||||
source?: string | null;
|
||||
type?: string | null;
|
||||
status: 'pending' | 'processing' | 'done' | 'failed';
|
||||
metadata?: Record<string, string | number | boolean> | null;
|
||||
createdAt: string | Date;
|
||||
updatedAt: string | Date;
|
||||
memoryEntries: MemoryEntry[];
|
||||
}
|
||||
```
|
||||
|
||||
### MemoryEntry
|
||||
|
||||
```typescript
|
||||
interface MemoryEntry {
|
||||
id: string;
|
||||
documentId: string;
|
||||
content: string | null;
|
||||
summary?: string | null;
|
||||
title?: string | null;
|
||||
type?: string | null;
|
||||
metadata?: Record<string, string | number | boolean> | null;
|
||||
createdAt: string | Date;
|
||||
updatedAt: string | Date;
|
||||
spaceContainerTag?: string | null;
|
||||
isStatic: boolean;
|
||||
spaceId: string;
|
||||
isLatest: boolean;
|
||||
isForgotten: boolean;
|
||||
forgetAfter: string | null;
|
||||
forgetReason: string | null;
|
||||
version: number;
|
||||
parentMemoryId: string | null;
|
||||
rootMemoryId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
relation?: 'updates' | 'extends' | 'derives' | null;
|
||||
isLatest?: boolean;
|
||||
spaceId?: string | null;
|
||||
updatesMemoryId?: string | null;
|
||||
nextVersionId?: string | null;
|
||||
memoryRelations?: Record<string, 'updates' | 'extends' | 'derives'> | null;
|
||||
spaceContainerTag?: string | null;
|
||||
}
|
||||
```
|
||||
|
||||
`DocumentWithMemories` and `MemoryEntry` are still exported as backward-compatible types.
|
||||
|
||||
---
|
||||
|
||||
## Exports
|
||||
|
|
@ -341,26 +348,36 @@ interface MemoryEntry {
|
|||
### Components
|
||||
|
||||
```typescript
|
||||
import {
|
||||
MemoryGraph,
|
||||
GraphCanvas,
|
||||
Legend,
|
||||
LoadingIndicator,
|
||||
NodeDetailPanel,
|
||||
SpacesDropdown
|
||||
} from '@supermemory/memory-graph';
|
||||
import { MemoryGraph, GraphCanvas } from '@supermemory/memory-graph';
|
||||
```
|
||||
|
||||
### Hooks
|
||||
|
||||
```typescript
|
||||
import { useGraphData, useGraphInteractions } from '@supermemory/memory-graph';
|
||||
import { useGraphData, useGraphTheme } from '@supermemory/memory-graph';
|
||||
```
|
||||
|
||||
### Engine classes
|
||||
|
||||
```typescript
|
||||
import {
|
||||
ForceSimulation,
|
||||
ViewportState,
|
||||
SpatialIndex,
|
||||
VersionChainIndex
|
||||
} from '@supermemory/memory-graph';
|
||||
```
|
||||
|
||||
### Constants
|
||||
|
||||
```typescript
|
||||
import { colors, GRAPH_SETTINGS, LAYOUT_CONSTANTS } from '@supermemory/memory-graph';
|
||||
import {
|
||||
DEFAULT_COLORS,
|
||||
DEFAULT_HOVER_POPOVER_Z_INDEX,
|
||||
DEFAULT_LABELS,
|
||||
FORCE_CONFIG,
|
||||
GRAPH_SETTINGS
|
||||
} from '@supermemory/memory-graph';
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -271,9 +271,8 @@ Search through user memories using semantic search:
|
|||
result = await tools.search_memories(
|
||||
information_to_get="user preferences",
|
||||
limit=10,
|
||||
include_full_docs=True
|
||||
)
|
||||
print(f"Found {len(result.memories)} memories")
|
||||
print(f"Found {result.get('count', 0)} memories")
|
||||
```
|
||||
|
||||
```typescript JavaScript
|
||||
|
|
@ -282,7 +281,7 @@ const searchResult = await tools.searchMemories({
|
|||
informationToGet: "user preferences",
|
||||
limit: 10,
|
||||
})
|
||||
console.log(`Found ${searchResult.memories.length} memories`)
|
||||
console.log(`Found ${searchResult.count} memories`)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
|
@ -298,7 +297,8 @@ Store new information in memory:
|
|||
result = await tools.add_memory(
|
||||
memory="User prefers tea over coffee"
|
||||
)
|
||||
print(f"Added memory with ID: {result.memory.id}")
|
||||
memory = result.get("memory") or {}
|
||||
print(f"Added memory with ID: {memory.get('id')}")
|
||||
```
|
||||
|
||||
```typescript JavaScript
|
||||
|
|
@ -306,7 +306,7 @@ print(f"Added memory with ID: {result.memory.id}")
|
|||
const addResult = await tools.addMemory({
|
||||
memory: "User prefers dark roast coffee",
|
||||
})
|
||||
console.log(`Added memory with ID: ${addResult.memory.id}`)
|
||||
console.log(`Added memory with ID: ${addResult.memory?.id}`)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
|
@ -466,7 +466,7 @@ async function chatWithMemory() {
|
|||
messages.push({
|
||||
role: "tool",
|
||||
tool_call_id: toolCall.id,
|
||||
content: JSON.stringify(result),
|
||||
content: result,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -567,7 +567,7 @@ SupermemoryTools(
|
|||
|
||||
**Methods**
|
||||
- `get_tool_definitions()` - Get OpenAI function definitions
|
||||
- `search_memories(information_to_get, limit, include_full_docs)` - Search user memories
|
||||
- `search_memories(information_to_get, limit=10)` - Search user memories. Pass `limit` by keyword: the second positional parameter is the deprecated, ignored `include_full_docs`
|
||||
- `add_memory(memory)` - Add new memory
|
||||
- `execute_tool_call(tool_call)` - Execute individual tool call
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ supermemoryTools(
|
|||
createToolCallExecutor(
|
||||
apiKey: string,
|
||||
config?: { namespace?: string; baseUrl?: string }
|
||||
) -> (toolCall: OpenAI.Chat.ChatCompletionMessageToolCall) => Promise<any>
|
||||
) -> (toolCall: OpenAI.Chat.ChatCompletionMessageToolCall) => Promise<string> // JSON-encoded result
|
||||
```
|
||||
|
||||
## Environment variables
|
||||
|
|
@ -608,7 +608,7 @@ Set these environment variables:
|
|||
```bash
|
||||
SUPERMEMORY_API_KEY=your_supermemory_key
|
||||
OPENAI_API_KEY=your_openai_key
|
||||
SUPERMEMORY_BASE_URL=https://custom-endpoint.com # optional
|
||||
SUPERMEMORY_BASE_URL=https://custom-endpoint.com # optional, Python only; in TypeScript pass baseUrl
|
||||
```
|
||||
|
||||
## Development
|
||||
|
|
@ -645,10 +645,7 @@ npm install
|
|||
npm test
|
||||
|
||||
# Type checking
|
||||
npm run type-check
|
||||
|
||||
# Linting
|
||||
npm run lint
|
||||
npm run check-types
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@ The AI can use these tools autonomously during conversations. With custom contai
|
|||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `supermemory_store` | Save information to long-term memory. |
|
||||
| `supermemory_search` | Search memories by query with similarity scores. |
|
||||
| `supermemory_forget` | Delete a memory by query or ID. |
|
||||
| `supermemory_profile` | View the user profile — persistent facts and recent context. |
|
||||
| `supermemory-save` | Save information to long-term memory. |
|
||||
| `supermemory-search` | Search memories by query with similarity scores. |
|
||||
| `supermemory-forget` | Delete a memory by query or ID. |
|
||||
| `supermemory-profile` | View the user profile — persistent facts and recent context. |
|
||||
|
||||
The older `supermemory_store`, `supermemory_search`, `supermemory_forget`, and `supermemory_profile` names still work but are deprecated. Update tool allowlists to the hyphenated names.
|
||||
|
||||
### Slash commands
|
||||
|
||||
|
|
@ -74,6 +76,9 @@ Users can interact with memory directly in chat.
|
|||
|---------|-------------|
|
||||
| `/remember [text]` | Manually save something to memory. |
|
||||
| `/recall [query]` | Search memories and see results with similarity scores. |
|
||||
| `/memory-usage` | Toggle showing how many memories were loaded and used in responses. |
|
||||
|
||||
The bundled `supermemory-index` skill indexes the current project: ask the agent to index or memorize the codebase, and it explores the workspace and saves focused memories.
|
||||
|
||||
### CLI commands
|
||||
|
||||
|
|
@ -107,13 +112,16 @@ openclaw supermemory wipe # Delete all memories (requires confirma
|
|||
|-----|------|---------|-------------|
|
||||
| `apiKey` | `string` | — | Supermemory API key. |
|
||||
| `baseUrl` | `string` | `https://api.supermemory.ai` | API endpoint (self-hosted / local). |
|
||||
| `apiVersion` | `string` | auto | `"v5"` or `"legacy"`. The hosted API uses v5; custom endpoints default to legacy. Set `"v5"` to use v5 with a self-hosted server 0.0.9 or newer. |
|
||||
| `containerTag` | `string` | `openclaw_{hostname}` | Root memory namespace. |
|
||||
| `autoRecall` | `boolean` | `true` | Inject relevant memories before every AI turn. |
|
||||
| `autoCapture` | `boolean` | `true` | Store conversation content after every turn. |
|
||||
| `maxRecallResults` | `number` | `10` | Max memories injected into context per turn. |
|
||||
| `profileFrequency` | `number` | `50` | Inject full user profile every N turns. |
|
||||
| `captureMode` | `string` | `"all"` | `"all"` filters noise. `"everything"` captures all messages. |
|
||||
| `entityContext` | `string` | built-in | Instructions that guide what memories are extracted from conversations (max 1,500 characters). |
|
||||
| `debug` | `boolean` | `false` | Verbose debug logs. |
|
||||
| `showMemoryUsage` | `boolean` | `true` | Show how many memories were loaded and used in AI responses. |
|
||||
| `enableCustomContainerTags` | `boolean` | `false` | Enable custom container routing. |
|
||||
| `customContainers` | `array` | `[]` | Custom containers with `tag` and `description`. |
|
||||
| `customContainerInstructions` | `string` | `""` | Instructions for AI on container routing. |
|
||||
|
|
@ -123,9 +131,16 @@ openclaw supermemory wipe # Delete all memories (requires confirma
|
|||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"slots": {
|
||||
"memory": "openclaw-supermemory"
|
||||
},
|
||||
"entries": {
|
||||
"openclaw-supermemory": {
|
||||
"enabled": true,
|
||||
"hooks": {
|
||||
"allowPromptInjection": true,
|
||||
"allowConversationAccess": true
|
||||
},
|
||||
"config": {
|
||||
"apiKey": "${SUPERMEMORY_OPENCLAW_API_KEY}",
|
||||
"containerTag": "my_memory",
|
||||
|
|
|
|||
|
|
@ -60,29 +60,53 @@ Or set an API key manually from the [API Keys](https://console.supermemory.ai/ke
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Ensure your `~/.config/opencode/opencode.jsonc` contains:
|
||||
OpenCode V1 and OpenCode 2 read different keys from `~/.config/opencode/opencode.jsonc`. Use the config for the version you run:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["opencode-supermemory"]
|
||||
}
|
||||
```
|
||||
<Tabs>
|
||||
<Tab title="OpenCode V1">
|
||||
```jsonc
|
||||
{
|
||||
"plugin": ["opencode-supermemory@latest"]
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="OpenCode 2">
|
||||
```jsonc
|
||||
{
|
||||
"plugins": ["opencode-supermemory"],
|
||||
"permissions": [
|
||||
{ "action": "supermemory_recall", "resource": "*", "effect": "allow" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The `permissions` rule lets the read-only `supermemory_recall` tool run without prompting.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
The installer writes all three keys (`plugin`, `plugins`, and `permissions`) so that one file covers both versions. OpenCode V1 refuses to start when the file has a top-level `permissions` field ("V2 permissions are not supported by OpenCode V1"), so V1 users must remove `permissions` after installing. V1 ignores `plugins` with a warning, so you can remove it too.
|
||||
</Warning>
|
||||
|
||||
## How it works
|
||||
|
||||
Once installed, the plugin runs automatically:
|
||||
|
||||
- **Context Injection** — On session start, relevant memories are fetched and injected into the agent's context (user profile, project knowledge, semantic matches).
|
||||
- **Keyword Detection** — Phrases like "remember" or "save this" trigger automatic storage.
|
||||
- **Smart Compaction** — At 80% context capacity, sessions are summarized and saved as memories.
|
||||
- **Context Injection** — On a session's first message, your profile facts are injected into the agent's context.
|
||||
- **Direct Recall** — On every substantive prompt, the plugin searches the current project and injects up to five fresh matches. Set `recallMode` to `"advisory"` to let the agent decide when to search, or `"off"` to disable it.
|
||||
- **Automatic Capture** — Completed turns are saved every `captureEveryNTurns` turns (fresh installs use `0`, which saves only at the end), and any remainder is flushed when the session ends or OpenCode shuts down.
|
||||
- **Keyword Detection** — Phrases like "remember" or "save this" nudge the agent to save to memory.
|
||||
- **Smart Compaction** — On OpenCode V1, sessions are summarized at 80% context capacity; on OpenCode 2, the plugin enriches native compaction. Both save the summary as a memory.
|
||||
- **Privacy Protection** — Content within `<private>` tags never persists.
|
||||
|
||||
### Memory scopes
|
||||
|
||||
Both scopes write to one repository container, `repo_{project-name}__{repository-hash}`, shared with the Claude Code, Codex, and Cursor plugins. `sm_scope` metadata keeps them apart.
|
||||
|
||||
| Scope | Description |
|
||||
|-------|-------------|
|
||||
| `user` | Memories that persist across all projects |
|
||||
| `project` | Memories isolated to the current project (default) |
|
||||
| `user` | Personal memories for the current project |
|
||||
| `project` | Project knowledge for the current project (default) |
|
||||
|
||||
### Memory types
|
||||
|
||||
|
|
@ -97,13 +121,14 @@ Once installed, the plugin runs automatically:
|
|||
|
||||
## Commands
|
||||
|
||||
### /supermemory-init
|
||||
The installer adds these in-chat commands:
|
||||
|
||||
Explore and index your codebase structure into memory:
|
||||
|
||||
```
|
||||
/supermemory-init
|
||||
```
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/supermemory-index` | Explore and index your codebase structure into memory (`/supermemory-init` is an alias) |
|
||||
| `/supermemory-login` | Authenticate with Supermemory in the browser |
|
||||
| `/supermemory-logout` | Clear stored credentials |
|
||||
| `/supermemory-status` | Show the Supermemory connection status |
|
||||
|
||||
## Tools
|
||||
|
||||
|
|
@ -116,6 +141,7 @@ The agent has access to a `supermemory` tool with these modes:
|
|||
| `profile` | query? | View user preferences |
|
||||
| `list` | scope?, limit? | Display stored items |
|
||||
| `forget` | memoryId, scope? | Remove memory |
|
||||
| `help` | none | List available modes |
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -124,16 +150,18 @@ Create `~/.config/opencode/supermemory.jsonc`:
|
|||
```jsonc
|
||||
{
|
||||
"apiKey": "sm_...", // Or use SUPERMEMORY_API_KEY / browser login
|
||||
"similarityThreshold": 0.6, // Minimum match score (0-1)
|
||||
"baseUrl": "https://api.supermemory.ai", // Or SUPERMEMORY_API_URL (self-hosted)
|
||||
"similarityThreshold": 0.55, // Minimum match score (0-1)
|
||||
"maxMemories": 5, // Memories per injection
|
||||
"maxProjectMemories": 10, // Project memory listings
|
||||
"maxProfileItems": 5, // Profile facts injected
|
||||
"injectProfile": true, // Include user preferences in context
|
||||
"containerTagPrefix": "opencode", // Tag prefix for scoping
|
||||
"userContainerTag": "my-user-tag", // Optional override
|
||||
"projectContainerTag": "my-project-tag", // Optional override
|
||||
"projectContainerTag": "my-project-tag", // Optional: override the repository container
|
||||
"keywordPatterns": ["log\\s+this"], // Extra auto-save triggers
|
||||
"compactionThreshold": 0.80 // Context usage ratio for summarization
|
||||
"recallMode": "direct", // "direct", "advisory", or "off"
|
||||
"captureEveryNTurns": 3, // Save completed turns every N turns (0 = session end only)
|
||||
"compactionThreshold": 0.80, // OpenCode V1: context usage ratio for summarization
|
||||
"compactionEnabled": true // OpenCode 2: enrich native compaction and save summaries
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ InputParams(
|
|||
| `search_limit` | int | 10 | Maximum number of memories to retrieve per query |
|
||||
| `search_threshold` | float | 0.1 | Minimum similarity threshold for memory retrieval |
|
||||
| `mode` | str | "full" | Memory retrieval mode: `"profile"`, `"query"`, or `"full"` |
|
||||
| `system_prompt` | str | "Based on previous conversations:\n\n" | Prefix text for memory context |
|
||||
| `system_prompt` | str | "Based on previous conversations, I recall:\n\n" | Prefix text for memory context |
|
||||
| `inject_mode` | str | "auto" | How memories are injected: `"auto"`, `"system"`, or `"user"` |
|
||||
|
||||
## Injection modes
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview) ru
|
|||
console.log(profile.static);
|
||||
console.log(profile.dynamic);
|
||||
console.log(profile.buckets);
|
||||
|
||||
const markdown = await supermemory.profileMarkdown("user_123");
|
||||
```
|
||||
|
||||
Buckets group profile facts under names you define:
|
||||
|
|
@ -143,6 +145,10 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview) ru
|
|||
## Memories
|
||||
|
||||
```typescript
|
||||
const memory = await supermemory.memories.get("user_123", "mem_123", {
|
||||
include: ["related", "documents"],
|
||||
});
|
||||
|
||||
const preview = await supermemory.memories.forgetMatching("user_123", {
|
||||
query: "old office address",
|
||||
dryRun: true,
|
||||
|
|
@ -333,6 +339,9 @@ await supermemory.search("user_123", { query: "planning notes" }, {
|
|||
# Delete documents
|
||||
result = client.documents.delete("user_123", ids=["meeting-q1"])
|
||||
|
||||
# Get one memory with its related memories and source document
|
||||
memory = client.memories.get("user_123", "mem_123", include=["related", "documents"])
|
||||
|
||||
# Forget memories: preview, then apply
|
||||
preview = client.memories.forget_matching("user_123", query="old office address", dry_run=True)
|
||||
client.memories.forget("user_123", ids=[m.id for m in preview.matches])
|
||||
|
|
@ -347,7 +356,7 @@ await supermemory.search("user_123", { query: "planning notes" }, {
|
|||
# Connectors
|
||||
setup = client.connectors.create(
|
||||
"user_123",
|
||||
request={"provider": "notion", "redirectUrl": "https://app.example.com/connected"},
|
||||
request={"provider": "notion", "redirect_url": "https://app.example.com/connected"},
|
||||
)
|
||||
# send the user to setup.authorization.url before setup.authorization.expires_at
|
||||
connector = client.connectors.get("user_123", setup.id, include=["syncs", "picker"])
|
||||
|
|
|
|||
|
|
@ -128,10 +128,10 @@ const configWithMemory = withSupermemory({
|
|||
id: "conv-456", // Groups messages into a conversation
|
||||
|
||||
// Search tuning
|
||||
searchMode: "hybrid", // "memories" | "documents" | "hybrid"
|
||||
searchMode: "hybrid", // "memories" | "chunks" | "hybrid"
|
||||
threshold: 0.6, // 0.0-1.0 (higher = more accurate)
|
||||
limit: 10, // Integer from 1 to 100
|
||||
rerank: true, // Rerank for best relevance
|
||||
rerank: "order", // "none" | "order" | "aggregate"
|
||||
rewriteQuery: false, // AI-rewrite query (+400ms latency)
|
||||
|
||||
// Context
|
||||
|
|
@ -150,12 +150,14 @@ const configWithMemory = withSupermemory({
|
|||
| `mode` | string | `"profile"` | Memory retrieval mode |
|
||||
| `addMemory` | string | `"always"` | Whether to save conversations after each response |
|
||||
| `id` | string | **required** | Custom ID to group messages into a conversation |
|
||||
| `searchMode` | string | — | `"memories"`, `"documents"`, or `"hybrid"` |
|
||||
| `searchMode` | string | — | `"memories"`, `"chunks"`, or `"hybrid"` |
|
||||
| `threshold` | number | — | Similarity threshold (0 = more results, 1 = more accurate) |
|
||||
| `limit` | number | — | Maximum number of memory results (integer from 1 to 100) |
|
||||
| `rerank` | boolean | `false` | Rerank results for relevance |
|
||||
| `rerank` | string | `"none"` | Post-retrieval ranking: `"none"`, `"order"`, or `"aggregate"` |
|
||||
| `rewriteQuery` | boolean | `false` | AI-rewrite query for better results (+400ms) |
|
||||
| `entityContext` | string | — | Deprecated and ignored. [Configure it on the container tag instead](/concepts/customization#entity-context). |
|
||||
| `filter` | object | — | Typed metadata filter applied before ranking |
|
||||
| `include` | object | — | Extra data per search result (`documents`, `related`, `forgotten`) |
|
||||
| `supportingContext` | string | — | Context that guides memory extraction for saved conversations (max 1500 characters) |
|
||||
| `metadata` | object | — | Custom metadata attached to saved conversations |
|
||||
| `promptTemplate` | function | — | Custom function to format memory data into prompt |
|
||||
|
||||
|
|
@ -168,5 +170,5 @@ The `searchMode` option controls what type of results are searched:
|
|||
| Mode | Description |
|
||||
| ------------- | ------------------------------------------------------ |
|
||||
| `"memories"` | Search only memory entries (atomic facts about the user) |
|
||||
| `"documents"` | Search only document chunks |
|
||||
| `"chunks"` | Search only document chunks |
|
||||
| `"hybrid"` | Search both memories AND document chunks (recommended) |
|
||||
|
|
|
|||
|
|
@ -44,9 +44,14 @@ If you'd rather write the adapter yourself, every provider implements the same i
|
|||
interface Provider {
|
||||
name: string
|
||||
prompts?: ProviderPrompts
|
||||
concurrency?: ConcurrencyConfig
|
||||
initialize(config: ProviderConfig): Promise<void>
|
||||
ingest(sessions: UnifiedSession[], options: IngestOptions): Promise<IngestResult>
|
||||
awaitIndexing(result: IngestResult, containerTag: string): Promise<void>
|
||||
awaitIndexing(
|
||||
result: IngestResult,
|
||||
containerTag: string,
|
||||
onProgress?: IndexingProgressCallback
|
||||
): Promise<void>
|
||||
search(query: string, options: SearchOptions): Promise<unknown[]>
|
||||
clear(containerTag: string): Promise<void>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Migrating from Mem0 to Supermemory is straightforward. This guide walks you thro
|
|||
Supermemory offers enhanced capabilities over Mem0:
|
||||
- **Knowledge graph** architecture for better context relationships
|
||||
- **Multiple content types** (URLs, PDFs, images, videos)
|
||||
- **Generous free tier** (100k tokens) with affordable pricing
|
||||
- **Free plan** with $5 of free credits every month; Free orgs upgrade to a paid plan once they run out (top-ups are paid-plan only)
|
||||
- **Multiple integration options** (API, MCP, SDKs)
|
||||
|
||||
## Quick migration (all-in-one)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ sidebarTitle: 'Tools: v1.4 → 2.0'
|
|||
production.
|
||||
</Note>
|
||||
|
||||
<Info>
|
||||
This guide covers 1.4.x → 2.0. The current major is 3.x: after this upgrade, follow the [3.0 upgrade guide](/migration/tools-v3-upgrade).
|
||||
</Info>
|
||||
|
||||
## What changed at a glance
|
||||
|
||||
| Area | v1.4.x | v2.0.0 |
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Text-like document types bill on the **text** meters; everything else bills as *
|
|||
|
||||
- `dreaming: "instant"` extracts a document's memories immediately instead of waiting for the next dynamic batch. It costs **one extra operation per document** on top of normal token metering. See [processing modes](/ingestion/add-memories#processing-modes).
|
||||
- Search add-ons: query rewriting (`rewriteQuery`), reranking and aggregation (v5 `rerank: "order"` / `"aggregate"`, v3/v4 `rerank`, v4 `aggregate`) each add **one operation** when they run successfully. Failed or skipped add-ons do not necessarily charge an operation.
|
||||
- Query-based `POST /v4/memories/forget-matching` adds **one operation per search round**, up to five, including `dryRun` previews. Applying an explicit `ids` list bypasses that query-operation charge.
|
||||
- Query-based forgetting (`DELETE /ns/{namespace}/memories/semantic`, legacy `POST /v4/memories/forget-matching`) adds **one operation per search round**, up to five, including `dryRun` previews. Forgetting an explicit `ids` list bypasses that query-operation charge.
|
||||
|
||||
Search is primarily metered as **`sm_search_queries`** (one unit per gated search/profile request). Prefer thinking of operations as **extra platform work**, not as a synonym for “API call.”
|
||||
|
||||
|
|
@ -186,7 +186,7 @@ Usage meters are shared; **feature gates** differ by tier.
|
|||
| Standard PDF extraction, including OCR for scans | Yes | Yes | Yes | Yes | Yes |
|
||||
| [Advanced document extraction for PDFs](/concepts/content-types#advanced-document-extraction) (figure and diagram descriptions) | — | — | — | Yes | Yes |
|
||||
| Diff / delta token billing | Yes | Yes | Yes | Yes | Yes |
|
||||
| Coding plugins (Claude Code, Codex, Cursor, OpenCode, OpenClaw, Hermes) | Yes | Yes | Yes | Yes | Yes |
|
||||
| Coding plugins (Claude Code, Codex, Cursor, OpenCode, OpenClaw, Hermes, Muse Code) | Yes | Yes | Yes | Yes | Yes |
|
||||
| Team management | — | Yes | Yes | Yes | Yes |
|
||||
| Google Drive, OneDrive, Notion, Granola connectors | — | Yes | Yes | Yes | Yes |
|
||||
| Gmail connector | — | — | Yes | Yes | Yes |
|
||||
|
|
@ -194,6 +194,7 @@ Usage meters are shared; **feature gates** differ by tier.
|
|||
| User Insights | — | — | — | Yes | Yes |
|
||||
| Two-factor authentication | — | — | — | Yes | Yes |
|
||||
| Org seat limit (members) | 1 | 3 | 3 | Unlimited | Unlimited |
|
||||
| Restricted members (per-tag access) | — | — | — | Yes | Yes |
|
||||
| Auto top-up in the console | — | Yes | Yes | Yes | Contract |
|
||||
| Auto top-up purchase limits | — | Yes | Yes | Yes | Contract |
|
||||
| Custom metering / SSO / dedicated deploy | — | — | — | — | Yes |
|
||||
|
|
@ -206,8 +207,17 @@ Overrides can be applied per org in metadata (`featureOverrides`) for enterprise
|
|||
|
||||
### HTTP behavior when gated
|
||||
|
||||
- **403** — plan too low for a **feature** (e.g. connector not on Free)
|
||||
- **402** — **quota / credits** exhausted for a metered call (search, tokens, etc.)
|
||||
- **403** — plan too low for a **feature** (e.g. connector not on Free). The `error` message names the minimum plan, for example `This feature requires Max plan or higher`.
|
||||
- **402** — **quota / credits** exhausted for a metered call (search, tokens, etc.). The body names the meter:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Search query limit reached",
|
||||
"details": "You've run out of credits. Top up to continue."
|
||||
}
|
||||
```
|
||||
|
||||
- **429** — the API key's own request rate limit (500 requests per minute by default), not a plan quota. The response carries a `Retry-After` header and `{ "code": "RATE_LIMITED", "retryAfterSeconds": … }`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ Designing isolation up front still makes identifying the user's content easier.
|
|||
|
||||
### Connectors and third-party sources
|
||||
|
||||
OAuth connectors (Drive, Notion, Gmail, and others) pull content your users authorize. Disconnecting a connector stops future sync; you still control whether already-ingested documents remain in the memory store. Treat connector scope and retention as part of your product privacy policy.
|
||||
OAuth connectors (Drive, Notion, Gmail, and others) pull content your users authorize. Disconnecting a connector stops future sync and, by default, deletes the documents it imported; pass `deleteDocuments=false` to keep them. Treat connector scope and retention as part of your product privacy policy.
|
||||
|
||||
### Self-host when cloud is not enough
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ curl -X POST "https://api.supermemory.ai/ns/user_4f8a/document" \
|
|||
|
||||
## 3. Wait until both are `done`
|
||||
|
||||
Poll document status. With **`dreaming: "instant"`**, once `system.status` is `done` the document is indexed **and** memories for that document should be available for search and profiles (`queued → extracting → … → done`).
|
||||
Poll each document. `system.status` reaches `done` once the content is indexed and searchable (`queued → extracting → … → done`). Memories are ready when `system.dreamingStatus` is also `done`; it reads `dreaming` while they are generated. **`dreaming: "instant"`** starts memory generation right away instead of waiting for the next batch.
|
||||
|
||||
> Note that the preferred way is to have `dreaming: dynamic`. supermemory charges one extra operation for instant dreaming. Instant is good for one off tests, setup, debugging and benchmarking.
|
||||
|
||||
|
|
@ -188,7 +188,8 @@ Poll document status. With **`dreaming: "instant"`**, once `system.status` is `d
|
|||
async function waitUntilDone(id: string) {
|
||||
for (;;) {
|
||||
const d = await supermemory.documents.get(user, id);
|
||||
if (d.system.status === "done" || d.system.status === "failed") return d;
|
||||
if (d.system.status === "failed") return d;
|
||||
if (d.system.status === "done" && d.system.dreamingStatus === "done") return d;
|
||||
await new Promise((r) => setTimeout(r, 1500));
|
||||
}
|
||||
}
|
||||
|
|
@ -204,7 +205,9 @@ import time
|
|||
def wait_until_done(doc_id: str):
|
||||
while True:
|
||||
d = client.documents.get(user, doc_id)
|
||||
if d.system.status in ("done", "failed"):
|
||||
if d.system.status == "failed":
|
||||
return d
|
||||
if d.system.status == "done" and d.system.dreaming_status == "done":
|
||||
return d
|
||||
time.sleep(1.5)
|
||||
|
||||
|
|
@ -217,7 +220,7 @@ print("ready to search")
|
|||
# replace DOC_ID with each document id from the add responses
|
||||
curl "https://api.supermemory.ai/ns/user_4f8a/document/DOC_ID" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
||||
# repeat until "system": { "status": "done" }
|
||||
# repeat until "system": { "status": "done", "dreamingStatus": "done" }
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Supermemory local is for builders. Supermemory Enterprise is for o
|
|||
icon: "/icons/hugeicons/building-03.svg"
|
||||
---
|
||||
|
||||
Supermemory local — the self-hosted binary — is free within its lite license limit and built for individual developers: local-first workflows, prototyping, and privacy-sensitive side projects. Its server source is not in the public repository. Text-memory processing can run offline after the first embedding-model download when the LLM is also local; webpage ingestion goes through Firecrawl and needs `FIRECRAWL_API_KEY`.
|
||||
Supermemory local — the self-hosted binary — is free within its lite license limit of 10,000 stored documents and built for individual developers: local-first workflows, prototyping, and privacy-sensitive side projects. Its server source is not in the public repository. Text-memory processing can run offline after the first embedding-model download when the LLM is also local; webpage ingestion goes through Firecrawl and needs `FIRECRAWL_API_KEY`.
|
||||
|
||||
**Supermemory Enterprise** is the full platform, run for your organization: the same memory engine with proprietary models, organizational controls, and infrastructure that scales with you — without you operating any of it.
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Everything in the [Memory API docs](/quickstart) works the same way. The coding
|
|||
|
||||
## Self-hosted vs. the platform
|
||||
|
||||
Self-hosted is free within its lite license limit and useful for local development and privacy-sensitive workloads. The server binary is not open source; the hosted platform is where the full product lives:
|
||||
Self-hosted is free within its lite license limit of 10,000 stored documents and useful for local development and privacy-sensitive workloads. The server binary is not open source; the hosted platform is where the full product lives:
|
||||
|
||||
| | Self-hosted | Platform |
|
||||
|---|---|---|
|
||||
|
|
|
|||
|
|
@ -226,9 +226,9 @@ print(r.stdout)
|
|||
|
||||
## Commands the agent can run
|
||||
|
||||
The Python tool exposes the same command surface as the TypeScript version: standard Unix builtins (`pwd`, `cd`, `ls`, `cat`, `stat`, `mkdir`, `rm`, `mv`, `cp`, `echo`), search and text utilities (`grep`, `find`, `head`, `tail`, `wc`, `sort`, `sed`, `awk`), plus the custom `sgrep <query> [path]` for semantic search across the container. Pipes, redirects, conditionals, loops, and file tests all work.
|
||||
The Python tool runs its own built-in commands: filesystem builtins (`pwd`, `cd`, `ls`, `cat`, `stat`, `mkdir`, `rm`, `rmdir`, `mv`, `cp`, `touch`, `echo`, `printf`, `tee`, `basename`, `dirname`), search and text utilities (`grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `sed`, `cut`, `tr`, `seq`, `date`), file tests (`test`, `[`), plus the custom `sgrep <query> [path]` for semantic search across the container.
|
||||
|
||||
See the [TypeScript Bash Tool reference](/smfs/bash-tool#commands-the-agent-can-run) for the full list.
|
||||
Pipes (`|`), redirects (`>`, `>>`, `<`), and `&&` / `||` chains work. Only simple commands run: loops (`for`, `while`), `if` blocks, and `awk` are not supported in the Python tool. Use the [TypeScript Bash Tool](/smfs/bash-tool#commands-the-agent-can-run) if your agent needs them.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ See the [TypeScript Bash Tool reference](/smfs/bash-tool#commands-the-agent-can-
|
|||
| `base_url` | `None` | Override the API endpoint |
|
||||
| `eager_load` | `True` | Warm the path index when the instance starts |
|
||||
| `eager_content` | `True` | Also warm the content cache during eager load |
|
||||
| `cwd` | `"/home/user"` | Initial working directory |
|
||||
| `cwd` | `"/"` | Initial working directory |
|
||||
| `env` | `None` | Extra environment variables |
|
||||
| `cache_ttl_ms` | `150_000` | Content cache TTL in ms. `None` = never expires (single-writer). `0` = no cache. |
|
||||
|
||||
|
|
@ -247,6 +247,6 @@ The container is what defines the filesystem; setting `cwd` or extra `env` from
|
|||
|
||||
## Limitations
|
||||
|
||||
- `chmod`, `utimes`, and symlinks (`ln -s`, `readlink`) raise `ENOSYS`.
|
||||
- `/dev/null` as a redirect target isn't supported. Write to `/tmp/discard.log` instead.
|
||||
- `chmod`, `ln`, and `readlink` aren't available; the shell returns `command not found`.
|
||||
- Redirecting to `/dev/null` discards the output; nothing is written to the container.
|
||||
- Binary uploads aren't supported. Text is extracted server-side.
|
||||
|
|
|
|||
|
|
@ -193,8 +193,9 @@ Standard Unix surface, plus one custom command. Each does what you'd expect.
|
|||
| `eagerLoad` | `true` | Warm the path index when the instance starts |
|
||||
| `eagerContent` | `true` | Also warm the content cache during eager load |
|
||||
| `cacheTtlMs` | `150_000` | Content cache TTL in ms. `null` = never expires (single-writer). `0` = no cache. |
|
||||
| `includeDocIds` | `false` | Append a `[doc:<id>]` annotation to each `sgrep` result so you can extract source document IDs from stdout |
|
||||
|
||||
Other options (`customCommands`, `logger`, plus `just-bash` pass-throughs like `executionLimits`, `network`, `python`, `javascript`, `cwd`, `env`) exist but aren't part of the supported surface for the SMFS use case. The container is what defines the filesystem; setting `cwd` or extra `env` from the host doesn't change that.
|
||||
Other options (`logger`, plus the `just-bash` pass-throughs `executionLimits` and `env`) exist but aren't part of the supported surface for the SMFS use case. The container is what defines the filesystem; setting extra `env` from the host doesn't change that.
|
||||
|
||||
## Limitations
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ Pushes pending writes and pulls remote changes immediately. Useful right before
|
|||
| `--foreground` | Run the daemon inline instead of detaching. |
|
||||
| `--backend <name>` | Linux only. `fuse` (default) or `nfs`. |
|
||||
| `--key <key>` | Pass an API key explicitly. Saved to project credentials. |
|
||||
| `--api-url <url>` | Override the API base URL. Also read from `SUPERMEMORY_API_URL`. |
|
||||
|
||||
## Multiple agents and multiple containers
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ Set `type` to `documents`, `chunks`, or `memories`. Pagination and sorting move
|
|||
|
||||
Document lists omit `content` by default. Send `{"include":{"content":true}}` to return the last published extracted text, including text from uploaded files. `content` is `null` before the first extraction publishes. During a replacement, previous text remains until new text publishes and also remains if extraction fails. Including content can make responses large.
|
||||
|
||||
Document list items also carry `system.memoryCount`, the number of live memories linked to the document in this namespace. Send `{"include":{"memoryCount":false}}` to skip counting.
|
||||
|
||||
Memory lists return only the latest version of each memory and hide forgotten memories and memories past their `forget_after`. Sending `"include": {"forgotten": true}` admits forgotten or expired rows only if they remain latest; they come back with `isForgotten: true`. Normal forgetting makes a memory non-latest, so this list does not recover it even with that flag. To search such memories, use search with `include.forgotten`. Document memories (`include=memories` on `GET /ns/{namespace}/document/{id}`) report the same forgotten flag.
|
||||
|
||||
Every response contains `documents`, `chunks`, `memories`, and `pagination`. Only the selected resource array is populated. Replace legacy `memories` assumptions in document-list callers with `documents`.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ PATCH /ns/user_1/document/doc_1
|
|||
```
|
||||
</CodeGroup>
|
||||
|
||||
The v5 body accepts any non-empty subset of `content`, `supportingContext`, `metadata`, or `date`, plus optional `taskType` and `dreaming` (which alone do not count as a change). `group` is an ingestion-side setting: it picks which existing memories serve as context while content is processed, so changing it only takes effect when the document is re-ingested. Send it together with `content`. Supplying `content` makes it the new canonical source; facts supported only by the previous source can disappear after reprocessing.
|
||||
The v5 body accepts any non-empty subset of `content`, `supportingContext`, `metadata`, or `date`, plus optional `taskType` and `dreaming` (which alone do not count as a change). `group` is an ingestion-side setting: it picks which existing memories serve as context while content is processed, so changing it only takes effect when the document is re-ingested. Send it together with `content`; a `group` without `content` returns `400`. Supplying `content` makes it the new canonical source; facts supported only by the previous source can disappear after reprocessing.
|
||||
|
||||
### Replace a file-backed document
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ metadata={"reviewed":true}
|
|||
dreaming=dynamic
|
||||
```
|
||||
|
||||
PATCH changes only supplied fields. Include `file` to replace the source while retaining omitted supporting fields, or omit `file` for metadata-, context-, or date-only changes. Like the JSON update, `group` only takes effect when the file is re-ingested, so send it together with `file`. `metadata` and `group` are JSON-encoded strings; `supportingContext` and `date` are plain strings.
|
||||
PATCH changes only supplied fields. Include `file` to replace the source while retaining omitted supporting fields, or omit `file` for metadata-, context-, or date-only changes. Like the JSON update, `group` only takes effect when the file is re-ingested, so send it together with `file`; without one the request returns `400`. `metadata` and `group` are JSON-encoded strings; `supportingContext` and `date` are plain strings.
|
||||
|
||||
<Warning>
|
||||
There is no public v5 `PUT /ns/{namespace}/document/file/{id}` operation. Use POST for a complete replacement and PATCH for a partial update.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ v5 renames the public isolation boundary from container tag to namespace. Existi
|
|||
|
||||
### List namespaces
|
||||
|
||||
The list is paginated: `GET /namespaces?page=1&limit=10` returns `{namespaces, pagination}`, newest first, with `limit` up to 100. Each entry now exposes `id`, `namespace`, `documentCount`, `memoryCount`, nullable `description`, and `system.createdAt/updatedAt`. Update readers that still expect `containerTag`, flat timestamps, or unbounded internal settings.
|
||||
The list is paginated: `GET /namespaces?page=1&limit=10` returns `{namespaces, pagination}`, newest first, with `limit` up to 100. Add `q` to keep only namespaces whose name contains that text, case-insensitively. Each entry now exposes `id`, `namespace`, `documentCount`, `memoryCount`, nullable `description`, and `system.createdAt/updatedAt`. Update readers that still expect `containerTag`, flat timestamps, or unbounded internal settings.
|
||||
|
||||
### Read and update settings
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ DELETE /ns/project_alpha?moveTo=project_archive
|
|||
|
||||
`moveTo` is a query parameter. This returns `202` with `status: "queued"` and `operationId`. The destination must differ from the source. Do not treat acceptance as completed migration.
|
||||
|
||||
Legacy merge can accept multiple sources; v5 moves one source per request. Run multi-source migrations sequentially and record each operation independently.
|
||||
Legacy merge takes exactly two tags and can merge both into a new target; v5 moves one source namespace per request. Run multi-source migrations sequentially and record each operation independently.
|
||||
|
||||
### With the SDK
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ If your code passes a `containerTags` array, pick one namespace. A v5 document l
|
|||
|
||||
| v4 | v5 |
|
||||
| --- | --- |
|
||||
| `client.search.memories({ q, containerTag })` | `client.search(namespace, { query })` |
|
||||
| `client.search.memories({ q, containerTag })` | `client.search(namespace, { query, searchMode: "memories" })` |
|
||||
| `client.profile({ containerTag, q })` | `client.profile(namespace)`; profile no longer takes a query, call `client.search` separately if you need results |
|
||||
| `client.documents.list(...)`, `client.memories.list(...)` | `client.list(namespace, "documents" \| "chunks" \| "memories", { filter? })` |
|
||||
| `client.containerTags.*` | `client.namespaces.*` |
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ ChatGPT opens the **Add Supermemory MCP to ChatGPT** dialog. Select **Sign in wi
|
|||
|
||||
On the Supermemory authorization page:
|
||||
|
||||
- Select **Read + Write** to let ChatGPT search and save Supermemory context. Select **Read only** if you only want search access.
|
||||
- Select **Read and write** to let ChatGPT search and save Supermemory context. Select **Read only** if you only want search access.
|
||||
- Select **Full access** to use every available space, or **Scoped** to choose specific spaces.
|
||||
- Choose how long the connection should remain active.
|
||||
- Select **Approve**.
|
||||
|
|
@ -196,6 +196,8 @@ After approval, ChatGPT returns to the Supermemory MCP plugin page. Select **Try
|
|||
|
||||
Supermemory MCP is now ready to use in ChatGPT Web. You can manage or disconnect it later from the [Plugins page](https://chatgpt.com/plugins).
|
||||
|
||||
To switch between **Read and write** and **Read only**, or change which spaces ChatGPT can use, open the [Agents page](https://console.supermemory.ai/agents) in the Supermemory console and choose **Edit access**. Reconnecting from ChatGPT does not show the authorization page again.
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
<AccordionGroup>
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ Supermemory appears under your connectors. Click **Connect**.
|
|||
|
||||
## Step 4: Authorize
|
||||
|
||||
You’ll be redirected to Supermemory to sign in and choose access scopes (for example **Read + Write** or **Full access**). Select the scopes you want, then click **Authorize**.
|
||||
You’ll be redirected to Supermemory to sign in and choose the permission (**Read and write** or **Read only**) and the scope (**All memories** or **Only some tags**). Select the access you want, then click **Authorize**.
|
||||
|
||||

|
||||
|
||||
## Done
|
||||
|
||||
Supermemory is connected and ready to use in Claude. You can change or revoke access later from **Settings → Connectors**.
|
||||
Supermemory is connected and ready to use in Claude. You can change or revoke access later from **Settings → Connectors**, or from the [Agents page](https://console.supermemory.ai/agents) in the Supermemory console with **Edit access** or **Disconnect memory**.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ Your assistant chooses these tools automatically. Use this table when you need t
|
|||
|
||||
| Tool | Use it for | Inputs | Result |
|
||||
| --- | --- | --- | --- |
|
||||
| `search_memory` | Semantic recall from one space | `query` (required), `containerTag` | Matching memories |
|
||||
| `get_profile` | Stable and recent profile context for one space | `containerTag` | Profile facts |
|
||||
| `search_memory` | Semantic recall from one space | `query` (required), `namespace` | Matching memories with memory IDs and source document IDs |
|
||||
| `get_profile` | Stable and recent profile context for one space | `namespace` | Profile facts |
|
||||
| `add_memory` | Save information | `content` (required), `namespace` | Save confirmation |
|
||||
| `forget_memory` | Forget outdated information | `content` (required), `namespace` | Forget confirmation |
|
||||
| `list_documents` | Browse stored source documents and their summaries | `page`, `limit`, `containerTag` | Document IDs, titles, types, status, dates, and summaries |
|
||||
| `get_document` | Read the available content of one document | `documentId` (required) | Document metadata, summary, and available content |
|
||||
| `list_memories` | Browse recent extracted memory entries and their source document IDs | `page`, `limit`, `containerTag` | Memory IDs, text, versions, and source document IDs |
|
||||
| `forget_memory` | Forget outdated information | `ids` or `content`, `namespace` | Forget confirmation, or the closest matches when nothing was forgotten |
|
||||
| `list_documents` | Browse stored source documents and their summaries | `page`, `limit`, `namespace` | Document IDs, titles, types, status, dates, and summaries |
|
||||
| `get_document` | Read the available content of one document | `documentId` (required), `namespace` | Document metadata, summary, and available content |
|
||||
| `list_memories` | Browse recent extracted memory entries and their source document IDs | `page`, `limit`, `namespace` | Memory IDs, text, versions, and source document IDs |
|
||||
| `list_spaces` | List accessible spaces and resolve a space name to its key | None | Formatted list plus structured `spaces` and `count` fields |
|
||||
| `who_am_i` | Inspect the authenticated account, permissions, scope, and active space | None | Account and access context |
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ Use the retrieval tools for different questions:
|
|||
|
||||
### Save or forget
|
||||
|
||||
`add_memory` saves the supplied `content`. Use `forget_memory` when a fact is outdated or should be removed. Both tools use the active space unless you pass `namespace`. The deprecated `containerTag` input and `add_memory` with `action: "forget"` remain supported for existing clients. Because the legacy action can remove information, `add_memory` retains its destructive safety annotation.
|
||||
`add_memory` saves the supplied `content`. Use `forget_memory` when a fact is outdated or should be removed: find the memory IDs with `search_memory`, then pass them in `ids`. If you pass only `content`, an exact text match is forgotten; otherwise nothing is forgotten and the closest memories are returned with their IDs so you can choose. Space-aware tools use the active space unless you pass `namespace`. The deprecated `containerTag` input and `add_memory` with `action: "forget"` remain supported for existing clients. Because the legacy action can remove information, `add_memory` retains its destructive safety annotation.
|
||||
|
||||
If the content is already final, the assistant should use `add_memory`. If you want to review, edit, or choose a space before saving, it should open the `guided-save` widget instead.
|
||||
|
||||
|
|
@ -79,6 +79,8 @@ If the content is already final, the assistant should use `add_memory`. If you w
|
|||
|
||||
`who_am_i` returns the current identity, role, access type, granted scope, and active space. `list_spaces` returns only spaces the authenticated account can access, with names, keys, document and memory counts, and recent activity.
|
||||
|
||||
Reconnecting a client does not show the authorization page again. To change a connected app's permission or scope, open the [Agents page](https://console.supermemory.ai/agents) in the console and choose **Edit access** from the app's row. Choose **Disconnect memory** to revoke its access; the next connection asks for approval again.
|
||||
|
||||
## Interactive widgets
|
||||
|
||||
Clients that support [MCP Apps](https://modelcontextprotocol.io/extensions/apps/overview) can open these Supermemory widgets directly inside the conversation.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ icon: "/icons/hugeicons/book-open-01.svg"
|
|||
| `GET /ns/{namespace}/connectors/{id}` | Read one connector, with `include=syncs` for recent sync runs or `include=picker` for a hosted picker link |
|
||||
| `PATCH /ns/{namespace}/connectors/{id}` | Change what it syncs: `selection` and `documentLimit` |
|
||||
| `POST /ns/{namespace}/connectors/{id}/sync` | Trigger a sync now. Returns 409 while one is already running |
|
||||
| `DELETE /ns/{namespace}/connectors/{id}` | Disconnect, optionally deleting the documents it imported |
|
||||
| `DELETE /ns/{namespace}/connectors/{id}` | Disconnect. Also deletes the documents it imported unless you pass `deleteDocuments=false` |
|
||||
| `GET /connectors` | List connectors across every namespace this key can read |
|
||||
|
||||
Providers: `notion`, `google-drive`, `onedrive`, `gmail`, `github` authenticate with OAuth. `web-crawler`, `s3`, and `granola` take their configuration in the create body and need no login.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "API reference"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Documents, search, profiles, lists, memories, namespaces, and organization settings in the latest Supermemory API"
|
||||
description: "Documents, search, profiles, lists, memories, connectors, namespaces, and organization settings in the latest Supermemory API"
|
||||
icon: "/icons/hugeicons/plug-socket.svg"
|
||||
---
|
||||
|
||||
|
|
@ -16,6 +16,8 @@ https://api.supermemory.ai
|
|||
/ns/{namespace}/profile
|
||||
/ns/{namespace}/list/{type}
|
||||
/ns/{namespace}/memories
|
||||
/ns/{namespace}/connectors
|
||||
/connectors
|
||||
/namespaces
|
||||
/organization
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue