mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-27 06:15:15 +00:00
Fixes v5 search and recall docs that didn't match the API. - **Options in the URL.** Search examples passed `searchMode`/`limit` as query params, and ingest examples passed `dreaming`/`taskType` the same way. v5 rejects every query param on these routes with `400`. They now go in the JSON body (quickstart, rules, super-rag, recall/search). - **`include`, not `attach`.** Renamed the search option. Its `forgotten` flag also admits forgotten memories into the main results, not just related context. - **Search response.** Added the required `isInference`. `metadata` is always an object, and `system.createdAt` is optional. - **Search add-ons are billed.** `rewriteQuery` and `rerank` each bill one extra operation; the docs said "no extra cost". - **Removed claims that don't match current behavior:** - inferred memories being down-weighted in search; - AST code chunking via `code-chunk` (super-rag now describes how chunking actually works); - a 64-character metadata key limit. - **Smaller fixes:** - The namespace is the SDK's first argument; the docs called it a top-level key. - "No v5 Python SDK" was stale. - Memory review: `total` semantics, the internal review stamp, and the missing 403. Checked against the current API and the published SDKs (TS 5.0.1, Python 5.0.0). Legacy v3/v4 docs are unchanged apart from factual fixes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
266 lines
8.5 KiB
Text
266 lines
8.5 KiB
Text
---
|
|
title: "Search"
|
|
sidebarTitle: "Search API"
|
|
description: "Semantic search across your memories and documents"
|
|
icon: "/icons/hugeicons/search-01.svg"
|
|
---
|
|
|
|
Search through your memories and documents with a single API call. Each search runs inside one `namespace` (what v3/v4 called a container tag).
|
|
|
|
<Tip>
|
|
**`searchMode: "hybrid"`** is the default and gives the best results. It searches both memories and document chunks, returning the most relevant content.
|
|
</Tip>
|
|
|
|
<Note>
|
|
**SDKs:** one call, `supermemory.search(namespace, { query, searchMode })` in TypeScript or `client.search(namespace, query=..., search_mode=...)` in Python. `searchMode` (`"memories"`, `"chunks"`, or `"hybrid"`) picks what comes back.
|
|
</Note>
|
|
|
|
## Quick start
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
import { Supermemory } from "supermemory";
|
|
|
|
const supermemory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY });
|
|
|
|
const results = await supermemory.search("user_123", {
|
|
query: "machine learning",
|
|
searchMode: "hybrid",
|
|
limit: 5,
|
|
});
|
|
|
|
results.results.forEach(result => {
|
|
console.log(result.memory || result.chunk, result.similarity);
|
|
});
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
from supermemory import Supermemory
|
|
|
|
client = Supermemory()
|
|
|
|
results = client.search(
|
|
"user_123",
|
|
query="machine learning",
|
|
search_mode="hybrid",
|
|
limit=5,
|
|
)
|
|
|
|
for result in results.results:
|
|
print(result.memory or result.chunk, result.similarity)
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST "https://api.supermemory.ai/ns/user_123/search" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{ "query": "machine learning", "searchMode": "hybrid", "limit": 5 }'
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"results": [
|
|
{
|
|
"id": "mem_xyz",
|
|
"memory": "User is interested in machine learning for product recommendations",
|
|
"similarity": 0.91,
|
|
"metadata": { "topic": "interests" },
|
|
"isLatest": true,
|
|
"isInference": false,
|
|
"system": { "createdAt": "2024-01-15T10:30:00.000Z", "updatedAt": "2024-01-15T10:30:00.000Z" }
|
|
},
|
|
{
|
|
"id": "chunk_abc",
|
|
"chunk": "Machine learning enables personalized experiences at scale...",
|
|
"similarity": 0.87,
|
|
"metadata": { "source": "onboarding_doc" },
|
|
"isLatest": true,
|
|
"isInference": false,
|
|
"system": { "createdAt": "2024-01-14T09:15:00.000Z", "updatedAt": "2024-01-14T09:15:00.000Z" }
|
|
}
|
|
],
|
|
"searchTime": 92
|
|
}
|
|
```
|
|
|
|
<Info>
|
|
In hybrid mode, results contain either a `memory` field (extracted facts) or a `chunk` field (document content), depending on the source. Branch on field presence.
|
|
</Info>
|
|
|
|
---
|
|
|
|
## Parameters
|
|
|
|
`namespace` is the URL path. Every other option goes in the JSON body: the second argument in TypeScript, or keyword arguments in Python. Search takes no query-string parameters; sending any returns `400`.
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| `namespace` | string | required | Namespace to search (URL path) |
|
|
| `query` | string | required | Search query |
|
|
| `searchMode` | string | `"hybrid"` | `"hybrid"` (recommended), `"memories"`, or `"chunks"` |
|
|
| `limit` | number | 10 | Max results (max 100) |
|
|
| `threshold` | 0-1 | 0.3 | Similarity cutoff (higher = fewer, better results) |
|
|
| `rerank` | string | `"none"` | `"none"`, `"order"` (re-score for relevance, +100ms), or `"aggregate"`. Successful reranking or aggregation can bill one extra [operation](/overview/billing#what-is-an-operation); setting the option alone does not guarantee it runs |
|
|
| `rewriteQuery` | boolean | false | Generate multiple rewrites, search all of them, and merge results. Adds latency and can bill one extra [operation](/overview/billing#what-is-an-operation) when rewriting runs successfully |
|
|
| `filter` | object | — | Metadata filter expression. See [Filtering](#filtering) |
|
|
| `include` | object | all `false` | `{ documents, related, forgotten }` — opt in to extra context per result |
|
|
|
|
<Note>
|
|
Defaults changed from v4: `searchMode` was `memories` and is now `hybrid`; `threshold` was `0.6` and is now `0.3`. Set both explicitly if you are comparing against v4 results.
|
|
</Note>
|
|
|
|
### Search modes
|
|
|
|
- **`hybrid`** (default, recommended) — Searches both memories and document chunks, and returns both in the response
|
|
- **`memories`** — Only searches extracted memories
|
|
- **`chunks`** — Only searches raw document/chunk content, skipping extracted memories
|
|
|
|
```typescript
|
|
// Hybrid: memories + document chunks (default)
|
|
await supermemory.search("user_123", {
|
|
query: "quarterly goals",
|
|
});
|
|
|
|
// Memories only: just extracted facts
|
|
await supermemory.search("user_123", {
|
|
query: "user preferences",
|
|
searchMode: "memories",
|
|
});
|
|
|
|
// Chunks only: RAG over documents
|
|
await supermemory.search("user_123", {
|
|
query: "refund policy",
|
|
searchMode: "chunks",
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Filtering
|
|
|
|
The `namespace` scopes results to a user or project. Use `filter` for metadata-based filtering inside that namespace:
|
|
|
|
```typescript
|
|
const results = await supermemory.search("user_123", {
|
|
query: "meeting notes",
|
|
filter: {
|
|
operator: "and",
|
|
operands: [
|
|
{ field: "type", operator: "eq", value: "meeting" },
|
|
{ field: "year", operator: "eq", value: 2024 },
|
|
],
|
|
},
|
|
});
|
|
```
|
|
|
|
<Accordion title="Filter Types">
|
|
- **Equality:** `{ field: "status", operator: "eq", value: "active" }` (also `neq`; strings, numbers, booleans)
|
|
- **String contains:** `{ field: "title", operator: "contains", value: "react" }` (also `notContains`; optional `caseSensitive`)
|
|
- **Numeric:** `{ field: "priority", operator: "gte", value: 5 }` (`gt`, `gte`, `lt`, `lte`)
|
|
- **Array contains:** `{ field: "tags", operator: "arrayContains", value: "important" }` (also `arrayNotContains`)
|
|
- **Logic:** `{ operator: "and" | "or", operands: [...] }`, nested up to 5 levels
|
|
|
|
Keys are literal: `customer.plan` is one field name, not a nested path. See [Organizing & Filtering](/concepts/filtering) for full syntax.
|
|
</Accordion>
|
|
|
|
---
|
|
|
|
## Query optimization
|
|
|
|
### Reranking
|
|
|
|
Re-scores results for better relevance. Adds ~100ms latency.
|
|
|
|
```typescript
|
|
const results = await supermemory.search("user_123", {
|
|
query: "complex technical question",
|
|
rerank: "order",
|
|
});
|
|
```
|
|
|
|
### Threshold
|
|
|
|
Control result quality vs quantity:
|
|
|
|
```typescript
|
|
// Broad search — more results
|
|
await supermemory.search("user_123", { query: "...", threshold: 0.3 });
|
|
|
|
// Precise search — fewer, better results
|
|
await supermemory.search("user_123", { query: "...", threshold: 0.8 });
|
|
```
|
|
|
|
### Attachments
|
|
|
|
- `include.documents` adds the most recently updated source document to each result when one is available.
|
|
- `include.related` adds parent, child, and sibling memories (see [graph memory](/concepts/graph-memory)).
|
|
- `include.forgotten` lets forgotten and expired memories appear in results. By default, search excludes memories that have been forgotten or have passed their `forgetAfter` expiration.
|
|
|
|
```typescript
|
|
await supermemory.search("user_123", {
|
|
query: "old project notes",
|
|
include: { related: true, forgotten: true },
|
|
searchMode: "memories",
|
|
});
|
|
```
|
|
|
|
Attached context arrives under `result.included` (`included.document`, `included.related.{parents,children,siblings}`).
|
|
|
|
---
|
|
|
|
## Chatbot example
|
|
|
|
Optimal configuration for conversational AI:
|
|
|
|
```typescript
|
|
async function getContext(userId: string, message: string) {
|
|
const results = await supermemory.search(userId, {
|
|
query: message,
|
|
threshold: 0.6,
|
|
searchMode: "hybrid",
|
|
limit: 5,
|
|
});
|
|
|
|
return results.results
|
|
.map(r => r.memory || r.chunk)
|
|
.join('\n\n');
|
|
}
|
|
```
|
|
|
|
<Accordion title="Response schema">
|
|
```typescript
|
|
interface SearchResult {
|
|
id: string;
|
|
memory?: string; // Present for memory results
|
|
chunk?: string; // Present for document chunk results
|
|
similarity: number; // 0-1
|
|
metadata: Record<string, unknown>; // {} when none
|
|
isLatest: boolean;
|
|
isInference: boolean; // false for chunks
|
|
system: { createdAt?: string; updatedAt: string };
|
|
included?: { // Only when you pass include
|
|
document?: object;
|
|
related?: { parents: object[]; children: object[]; siblings: object[] };
|
|
};
|
|
}
|
|
|
|
interface SearchResponse {
|
|
results: SearchResult[];
|
|
searchTime: number; // ms
|
|
}
|
|
```
|
|
</Accordion>
|
|
|
|
---
|
|
|
|
## Next steps
|
|
|
|
- [Ingesting Content](/ingestion/add-memories) — Add content to search
|
|
- [User Profiles](/recall/user-profiles) — Get user context
|
|
- [Organizing & Filtering](/concepts/filtering) — Namespaces and metadata
|