mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-28 06:24:40 +00:00
Fixes v5 profile and bucket docs.
- **The default `preferences` bucket can't be replaced.** It's always part of the effective set. Custom buckets are added alongside it, `deleteBuckets` can't remove it, and defining a bucket named `preferences` only overrides its description.
- **No `[Summary]`/`[Recent]` labels in v5.** Only v4 adds them. Summaries are now told apart by an `aggregated_` id, and individual `dynamic` entries keep their `[YYYY-MM-DD]` date. Example responses are updated, and the migration snippet calls out the change.
- **Name clashes.** A namespace bucket with an org bucket's name returns `409`; the docs said the org's definition silently wins.
- **Smaller fixes:**
- `filterPrompt` → `organizationalContext`.
- An invalid `organization.update` example (stray `},`).
- OAuth redirect URIs now use `/v3/connections/auth/callback/{provider}`.
- The v4 `include` example in the migration snippet.
- Broken anchors and links.
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)
339 lines
9.9 KiB
Text
339 lines
9.9 KiB
Text
---
|
|
title: "User profiles"
|
|
sidebarTitle: "Overview"
|
|
description: "Fetch and use automatically maintained user context"
|
|
icon: "/icons/hugeicons/user.svg"
|
|
---
|
|
|
|
User profiles are extremely short summaries of context about an entity (Usually a user, but can be anything) which includes both the *static* facts about them, as well as a few recent episodes.
|
|
|
|
> You can think of these as a dynamic compaction that's done by supermemory in real-time.
|
|
|
|
This profile should be injected into the agent context for truly personalized experiences. To read more, visit [User profiles - Concept](/concepts/user-profiles)
|
|
|
|
Get a user's profile — their static facts and dynamic context — with a single API call. One profile per `namespace` (what v3/v4 called a container tag).
|
|
|
|
<Tip>
|
|
Profiles are built automatically as you [ingest content](/ingestion/add-memories). No setup required. If you read a profile right after ingesting, pass `dreaming: "instant"` on the add; otherwise a fresh namespace can show an empty profile for minutes.
|
|
</Tip>
|
|
|
|
## Quick start
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
import { Supermemory } from "supermemory";
|
|
|
|
const supermemory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY });
|
|
|
|
const { profile } = await supermemory.profile("user_123");
|
|
|
|
console.log(profile.static.map((m) => m.memory)); // Long-term facts
|
|
console.log(profile.dynamic.map((m) => m.memory)); // Recent context
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
from supermemory import Supermemory
|
|
|
|
client = Supermemory()
|
|
|
|
profile = client.profile("user_123").profile
|
|
|
|
print([m.memory for m in profile.static]) # Long-term facts
|
|
print([m.memory for m in profile.dynamic]) # Recent context
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST "https://api.supermemory.ai/ns/user_123/profile" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"profile": {
|
|
"static": [
|
|
{ "id": "mem_1", "memory": "User is a software engineer" },
|
|
{ "id": "mem_2", "memory": "User specializes in Python and React" },
|
|
{ "id": "mem_3", "memory": "User prefers dark mode interfaces" }
|
|
],
|
|
"dynamic": [
|
|
{ "id": "mem_4", "memory": "[2026-10-02] User is working on Project Alpha" },
|
|
{ "id": "mem_5", "memory": "[2026-10-05] User recently started learning Rust" },
|
|
{ "id": "mem_6", "memory": "[2026-10-09] User is debugging authentication issues" }
|
|
],
|
|
"buckets": {
|
|
"preferences": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
`static`, `dynamic`, and `buckets` are always returned. Omitting the request's `buckets` returns every effective bucket, including the built-in `preferences` bucket; specifying names returns only those buckets, and an empty list returns an empty bucket section. Each entry is `{ id, memory }`; the `id` is the memory ID, so you can [forget](/recall/memory-operations#forget-memories) a profile entry directly. The exception is synthesized summaries of older memories, whose `id` starts with `aggregated_` — they don't map to a single memory. Individual `dynamic` entries start with a `[YYYY-MM-DD]` date.
|
|
|
|
---
|
|
|
|
## Profile + search
|
|
|
|
The v5 profile call takes no query. When you also need query-ranked memories, run a [search](/recall/search) next to it:
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
const [{ profile }, search] = await Promise.all([
|
|
supermemory.profile("user_123"),
|
|
supermemory.search("user_123", {
|
|
query: "deployment errors",
|
|
searchMode: "memories",
|
|
limit: 5,
|
|
}),
|
|
]);
|
|
|
|
// Profile data
|
|
const facts = profile.static.map((m) => m.memory);
|
|
const context = profile.dynamic.map((m) => m.memory);
|
|
|
|
// Query-specific memories
|
|
const memories = search.results.map((r) => r.memory).filter(Boolean);
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
profile = client.profile("user_123").profile
|
|
search = client.search(
|
|
"user_123",
|
|
query="deployment errors",
|
|
search_mode="memories",
|
|
limit=5,
|
|
)
|
|
|
|
# Profile data
|
|
facts = [m.memory for m in profile.static]
|
|
context = [m.memory for m in profile.dynamic]
|
|
|
|
# Query-specific memories
|
|
memories = [r.memory for r in search.results if r.memory]
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
---
|
|
|
|
## Parameters
|
|
|
|
`namespace` is the first argument (URL path). The options object is optional and accepts only `filter` and `buckets`.
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|-----------|------|----------|-------------|
|
|
| `namespace` | string | Yes | User/project identifier |
|
|
| `body.filter` | object | No | Metadata filter applied to the memories that make up the profile |
|
|
| `body.buckets` | string[] | No | Restrict the `buckets` section to specific names (up to 50). Omit for all configured buckets. See [Profile Buckets](/user-profiles/buckets) |
|
|
|
|
---
|
|
|
|
## Filtering profiles
|
|
|
|
Profiles support the same [metadata filter](/concepts/filtering) as `search` and `list` — `filter` narrows which memories are eligible to contribute to `static`, `dynamic`, and `buckets`.
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
const { profile } = await supermemory.profile("user_123", {
|
|
filter: { field: "source", operator: "eq", value: "onboarding" },
|
|
});
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
profile = client.profile(
|
|
"user_123",
|
|
filter={"field": "source", "operator": "eq", "value": "onboarding"},
|
|
).profile
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST "https://api.supermemory.ai/ns/user_123/profile" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"filter": { "field": "source", "operator": "eq", "value": "onboarding" }
|
|
}'
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
Combine `filter` with `buckets` to scope both the profile synthesis and the bucket section in one call:
|
|
|
|
```typescript
|
|
const { profile } = await supermemory.profile("org_customer_442", {
|
|
filter: { field: "channel", operator: "eq", value: "support_ticket" },
|
|
buckets: ["billing"],
|
|
});
|
|
```
|
|
|
|
All filter operators from [Organizing & Filtering](/concepts/filtering) are supported — `eq`/`neq`, `contains`/`notContains`, numeric comparisons, `arrayContains`, and nested `and`/`or`.
|
|
|
|
---
|
|
|
|
## Building prompts
|
|
|
|
The most common pattern — inject profile into your LLM's system prompt:
|
|
|
|
```typescript
|
|
async function chat(userId: string, message: string) {
|
|
const { profile } = await supermemory.profile(userId);
|
|
|
|
const systemPrompt = `You are assisting a user.
|
|
|
|
ABOUT THE USER:
|
|
${profile.static.map((m) => m.memory).join('\n') || 'No profile yet.'}
|
|
|
|
CURRENT CONTEXT:
|
|
${profile.dynamic.map((m) => m.memory).join('\n') || 'No recent activity.'}
|
|
|
|
Personalize responses to their expertise and preferences.`;
|
|
|
|
return llm.chat({
|
|
messages: [
|
|
{ role: "system", content: systemPrompt },
|
|
{ role: "user", content: message }
|
|
]
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Full context pattern
|
|
|
|
Get profile + query-specific memories:
|
|
|
|
```typescript
|
|
async function getContext(userId: string, query: string) {
|
|
const [{ profile }, search] = await Promise.all([
|
|
supermemory.profile(userId),
|
|
supermemory.search(userId, {
|
|
query,
|
|
threshold: 0.6,
|
|
searchMode: "memories",
|
|
}),
|
|
]);
|
|
|
|
return `
|
|
User Background:
|
|
${profile.static.map((m) => m.memory).join('\n')}
|
|
|
|
Current Context:
|
|
${profile.dynamic.map((m) => m.memory).join('\n')}
|
|
|
|
Relevant Memories:
|
|
${search.results.map((r) => r.memory).filter(Boolean).join('\n') || 'None'}
|
|
`;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Profile buckets
|
|
|
|
Buckets are **custom topical categories** for a profile — an axis that sits alongside
|
|
`static` and `dynamic`, grouping facts by subject (e.g. `preferences`, `goals`,
|
|
`work`) instead of by how long-lived they are.
|
|
|
|
<Card title="Profile Buckets" icon="/icons/hugeicons/tag-01.svg" href="/user-profiles/buckets">
|
|
Read and configure buckets — request bucketed profiles, create namespace buckets,
|
|
and see validation limits.
|
|
</Card>
|
|
|
|
---
|
|
|
|
## Framework examples
|
|
|
|
<Accordion title="Express.js middleware">
|
|
```typescript
|
|
async function withProfile(req, res, next) {
|
|
if (!req.user?.id) return next();
|
|
|
|
try {
|
|
const { profile } = await supermemory.profile(req.user.id);
|
|
req.userProfile = profile;
|
|
} catch (e) {
|
|
req.userProfile = null;
|
|
}
|
|
next();
|
|
}
|
|
|
|
app.use(withProfile);
|
|
|
|
app.post('/chat', (req, res) => {
|
|
// req.userProfile available in all routes
|
|
});
|
|
```
|
|
</Accordion>
|
|
|
|
<Accordion title="Next.js API route">
|
|
```typescript
|
|
// app/api/chat/route.ts
|
|
export async function POST(req: NextRequest) {
|
|
const { userId, message } = await req.json();
|
|
|
|
const { profile } = await supermemory.profile(userId);
|
|
|
|
const response = await generateResponse(message, profile);
|
|
return NextResponse.json({ response });
|
|
}
|
|
```
|
|
</Accordion>
|
|
|
|
<Accordion title="AI SDK integration">
|
|
```typescript
|
|
import { withSupermemory } from "@supermemory/tools/ai-sdk"
|
|
import { openai } from "@ai-sdk/openai"
|
|
|
|
// Profiles automatically injected
|
|
const model = withSupermemory(openai("gpt-4"), {
|
|
namespace: "user-123",
|
|
id: "conv-1",
|
|
})
|
|
|
|
const result = await generateText({
|
|
model,
|
|
messages: [{ role: "user", content: "Help with my project" }]
|
|
});
|
|
```
|
|
|
|
See [AI SDK Integration](/integrations/ai-sdk) for details.
|
|
</Accordion>
|
|
|
|
---
|
|
|
|
## Response schema
|
|
|
|
```typescript
|
|
interface ProfileEntry {
|
|
id: string; // memory ID
|
|
memory: string; // the fact
|
|
}
|
|
|
|
interface ProfileResponse {
|
|
profile: {
|
|
static: ProfileEntry[]; // Long-term facts
|
|
dynamic: ProfileEntry[]; // Recent context
|
|
buckets: Record<string, ProfileEntry[]>; // Topical buckets, keyed by bucket name
|
|
};
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Next steps
|
|
|
|
- [Profile Buckets](/user-profiles/buckets) — Custom topical categories for profiles
|
|
- [User Profiles Concept](/concepts/user-profiles) — Understand static vs dynamic
|
|
- [Ingesting Content](/ingestion/add-memories) — Build profiles by adding content
|
|
- [AI SDK Integration](/integrations/ai-sdk) — Automatic profile injection
|