mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-04 13:50:28 +00:00
Fixes across existing pages: stale claude-3-sonnet -> current models, deprecated ai/react + toAIStreamResponse -> current AI SDK APIs, five divergent search signatures unified to client.search.memories (v4) / client.search.documents (v3), singular containerTag in v4 contexts, from-zep containerTag type error, canonical processing-status enum, corrected 'v4 has no SDK' claim, internal links re-pointed at final destinations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
288 lines
9.2 KiB
Text
288 lines
9.2 KiB
Text
---
|
|
title: "Review Inferred Memories"
|
|
sidebarTitle: "Memory Review"
|
|
description: "List and act on low-confidence inferred memories — approve, decline, or undo"
|
|
icon: "list-checks"
|
|
---
|
|
|
|
Supermemory's graph automatically **derives** new facts from patterns across your
|
|
existing memories (see [Graph Memory](/concepts/graph-memory)). These derived facts
|
|
are guesses — the engine wasn't told them directly — so they are flagged as
|
|
**inferred** (`isInference: true`) and **down-weighted in search** until confirmed.
|
|
|
|
These two endpoints let you build a review experience on top of that queue: list the
|
|
inferred memories awaiting review, then **approve**, **decline**, or **undo** a
|
|
decision on each one.
|
|
|
|
<Info>
|
|
These endpoints are scoped to a single [container tag](/concepts/permissioning)
|
|
(space), under `/v3/container-tags/{containerTag}`.
|
|
</Info>
|
|
|
|
## How review affects ranking
|
|
|
|
While a memory is unreviewed and inferred it is down-weighted in search, so the
|
|
engine's guesses rank below facts you stated explicitly. Reviewing it resolves that
|
|
either way:
|
|
|
|
| Action | Result | Effect on search |
|
|
|--------|--------|------------------|
|
|
| **Approve** | `isInference` cleared | Ranks like a stated fact — no longer down-weighted |
|
|
| **Decline** | `isForgotten` set | Removed from search entirely — a rejected guess is forgotten |
|
|
| **Undo** | back to unreviewed | Returns to the queue; inferred and down-weighted again |
|
|
|
|
A reviewed memory is stamped with `reviewStatus` in its metadata so it drops out of the
|
|
review queue (declined memories also leave search, since they're forgotten). **Undo**
|
|
clears that stamp — and un-forgets a declined memory — bringing it back.
|
|
|
|
---
|
|
|
|
## List Inferred Memories
|
|
|
|
Return the inferred memories for a container tag that are still awaiting review (the
|
|
review queue). Reviewed memories are excluded.
|
|
|
|
```
|
|
GET /v3/container-tags/{containerTag}/inferred
|
|
```
|
|
|
|
<Tabs>
|
|
<Tab title="fetch">
|
|
```typescript
|
|
const res = await fetch(
|
|
"https://api.supermemory.ai/v3/container-tags/user_123/inferred",
|
|
{ headers: { "Authorization": `Bearer ${API_KEY}` } }
|
|
);
|
|
|
|
const { memories, total } = await res.json();
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl "https://api.supermemory.ai/v3/container-tags/user_123/inferred" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### Path parameters
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `containerTag` | string | The container tag / space to read the review queue for |
|
|
|
|
### Response
|
|
|
|
```json
|
|
{
|
|
"memories": [
|
|
{
|
|
"id": "mem_abc123",
|
|
"memory": "Alex likely works on Stripe's core payments product",
|
|
"parentCount": 3,
|
|
"createdAt": "2025-01-15T10:30:00.000Z",
|
|
"updatedAt": "2025-01-15T10:30:00.000Z",
|
|
"metadata": { "source": "derive" }
|
|
}
|
|
],
|
|
"total": 1
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `memories[].id` | string | Memory entry ID — pass to the review endpoint |
|
|
| `memories[].memory` | string | The inferred memory text |
|
|
| `memories[].parentCount` | number | How many source memories this was derived from. Higher = stronger signal |
|
|
| `memories[].createdAt` | string | ISO 8601 timestamp |
|
|
| `memories[].updatedAt` | string | ISO 8601 timestamp |
|
|
| `memories[].metadata` | object \| null | Arbitrary metadata stored on the memory |
|
|
| `total` | number | Count of unreviewed inferred memories returned |
|
|
|
|
<Note>
|
|
The queue returns up to **50** memories, ordered by `parentCount` descending (most
|
|
strongly supported first), then by `createdAt` descending. It excludes anything that
|
|
is forgotten, expired, or already reviewed. An unknown or empty container tag returns
|
|
`{ "memories": [], "total": 0 }`.
|
|
</Note>
|
|
|
|
---
|
|
|
|
## Review an Inferred Memory
|
|
|
|
Record a decision on a single inferred memory.
|
|
|
|
```
|
|
POST /v3/container-tags/{containerTag}/inferred/{memoryId}/review
|
|
```
|
|
|
|
<Tabs>
|
|
<Tab title="fetch">
|
|
```typescript
|
|
const res = await fetch(
|
|
"https://api.supermemory.ai/v3/container-tags/user_123/inferred/mem_abc123/review",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Authorization": `Bearer ${API_KEY}`,
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: JSON.stringify({ action: "approve" })
|
|
}
|
|
);
|
|
|
|
const result = await res.json();
|
|
// { id: "mem_abc123", isInference: false, isForgotten: false, reviewStatus: "approved" }
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST \
|
|
"https://api.supermemory.ai/v3/container-tags/user_123/inferred/mem_abc123/review" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"action": "approve"}'
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### Path parameters
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `containerTag` | string | The container tag / space the memory belongs to |
|
|
| `memoryId` | string | The memory entry ID from the list endpoint |
|
|
|
|
### Body parameters
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|-----------|------|----------|-------------|
|
|
| `action` | string | yes | One of `approve`, `decline`, or `undo` |
|
|
|
|
<Warning>
|
|
The reject action is named **`decline`**. There is no `reject` value.
|
|
</Warning>
|
|
|
|
**Action semantics:**
|
|
|
|
- **`approve`** — Promote the memory: clears `isInference`, so it ranks like a stated
|
|
fact instead of a down-weighted guess. Stamps `reviewStatus: "approved"`.
|
|
- **`decline`** — Reject the suggestion: the memory is **forgotten**
|
|
(`isForgotten: true`) and stamped `reviewStatus: "declined"`, so it leaves both
|
|
search and the review queue.
|
|
- **`undo`** — Revert a prior `approve`/`decline` back to the unreviewed inferred
|
|
state: restores `isInference: true`, un-forgets the memory (`isForgotten: false`),
|
|
and clears the review stamp, so it returns to the queue.
|
|
|
|
### Response
|
|
|
|
```json
|
|
{
|
|
"id": "mem_abc123",
|
|
"isInference": false,
|
|
"isForgotten": false,
|
|
"reviewStatus": "approved"
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | string | The reviewed memory ID |
|
|
| `isInference` | boolean | `false` after approve; `true` after decline or undo |
|
|
| `isForgotten` | boolean | `true` after decline (the memory is forgotten); `false` otherwise |
|
|
| `reviewStatus` | `"approved"` \| `"declined"` \| `null` | The new status; `null` after an undo |
|
|
|
|
### Errors
|
|
|
|
| Status | When |
|
|
|--------|------|
|
|
| `401` | Missing or invalid authentication |
|
|
| `404` | The container tag or memory was not found in your organization |
|
|
| `409` | The memory isn't reviewable for this action — it's not an inferred memory, or there's no prior review to undo |
|
|
|
|
---
|
|
|
|
## Building a review experience
|
|
|
|
The endpoints are designed for an optimistic, one-at-a-time review UI (swipe to keep /
|
|
decline, with undo). A typical client fetches the queue once, then pops each card off
|
|
locally as the user decides — `undo` re-adds it.
|
|
|
|
<Accordion title="React Query hooks (TypeScript)">
|
|
```typescript
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
const BASE = "https://api.supermemory.ai/v3";
|
|
const key = (tag: string) => ["inferred-memories", tag] as const;
|
|
|
|
export type InferredMemory = {
|
|
id: string;
|
|
memory: string;
|
|
parentCount: number;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
metadata: Record<string, unknown> | null;
|
|
};
|
|
|
|
export type ReviewAction = "approve" | "decline" | "undo";
|
|
|
|
export function useInferredMemories(containerTag: string) {
|
|
return useQuery({
|
|
queryKey: key(containerTag),
|
|
queryFn: async (): Promise<InferredMemory[]> => {
|
|
const res = await fetch(`${BASE}/container-tags/${containerTag}/inferred`, {
|
|
headers: { Authorization: `Bearer ${API_KEY}` },
|
|
});
|
|
if (!res.ok) throw new Error("Failed to load review queue");
|
|
const data = await res.json();
|
|
return data.memories ?? [];
|
|
},
|
|
staleTime: 60_000,
|
|
});
|
|
}
|
|
|
|
export function useReviewInferredMemory(containerTag: string) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (vars: { memoryId: string; action: ReviewAction }) => {
|
|
const res = await fetch(
|
|
`${BASE}/container-tags/${containerTag}/inferred/${vars.memoryId}/review`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Bearer ${API_KEY}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ action: vars.action }),
|
|
},
|
|
);
|
|
if (!res.ok) throw new Error("Review failed");
|
|
return res.json();
|
|
},
|
|
onSuccess: (_data, { memoryId, action }) => {
|
|
// approve/decline remove the card; undo brings it back, so refetch.
|
|
if (action === "undo") {
|
|
queryClient.invalidateQueries({ queryKey: key(containerTag) });
|
|
return;
|
|
}
|
|
queryClient.setQueryData<InferredMemory[]>(key(containerTag), (prev) =>
|
|
prev?.filter((m) => m.id !== memoryId),
|
|
);
|
|
},
|
|
});
|
|
}
|
|
```
|
|
</Accordion>
|
|
|
|
<Note>
|
|
There is no separate "skip" action. A swipe-to-skip is purely client-side — don't send
|
|
a request and the memory simply stays in the queue for a later session.
|
|
</Note>
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
- [Graph Memory](/concepts/graph-memory) — How inferred (`derive`) memories are created
|
|
- [Memory Operations](/memory-operations) — Create, forget, and update memories
|
|
- [Search](/search) — How inferred memories are ranked in results
|