supermemory/apps/docs/user-profiles.mdx
Dhravya Shah 492e09bae2 docs: staleness sweep — current model IDs, AI SDK APIs, one search signature
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>
2026-07-17 15:54:30 -07:00

409 lines
11 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "User Profiles"
sidebarTitle: "User Profiles"
description: "Fetch and use automatically maintained user context"
icon: "user"
---
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.
<Tip>
Profiles are built automatically as you [ingest content](/add-memories). No setup required.
</Tip>
## Quick Start
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory();
const { profile } = await client.profile({
containerTag: "user_123"
});
console.log(profile.static); // Long-term facts
console.log(profile.dynamic); // Recent context
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
client = Supermemory()
result = client.profile(container_tag="user_123")
print(result.profile.static) # Long-term facts
print(result.profile.dynamic) # Recent context
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/profile" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTag": "user_123"}'
```
</Tab>
</Tabs>
**Response:**
```json
{
"profile": {
"static": [
"User is a software engineer",
"User specializes in Python and React",
"User prefers dark mode interfaces"
],
"dynamic": [
"User is working on Project Alpha",
"User recently started learning Rust",
"User is debugging authentication issues"
]
}
}
```
---
## Profile + Search
Get profile and search results in one call by adding the `q` parameter:
<Tabs>
<Tab title="TypeScript">
```typescript
const result = await client.profile({
containerTag: "user_123",
q: "deployment errors"
});
// Profile data
const { static: facts, dynamic: context } = result.profile;
// Search results (only if q was provided)
const memories = result.searchResults?.results || [];
```
</Tab>
<Tab title="Python">
```python
result = client.profile(
container_tag="user_123",
q="deployment errors"
)
# Profile data
facts = result.profile.static
context = result.profile.dynamic
# Search results
memories = result.search_results.results if result.search_results else []
```
</Tab>
</Tabs>
---
## Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `containerTag` | string | Yes | User/project identifier |
| `q` | string | No | Search query (includes search results in response) |
| `threshold` | 0-1 | No | Filter search results by relevance score |
| `filters` | object | No | Metadata filters applied to profile and search results |
| `include` | string[] | No | Sections to return — any of `"static"`, `"dynamic"`, `"buckets"`. Omit to return all |
| `buckets` | string[] | No | Restrict the `buckets` section to specific keys. Omit for all configured buckets |
---
## 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 client.profile({ containerTag: userId });
const systemPrompt = `You are assisting a user.
ABOUT THE USER:
${profile.static?.join('\n') || 'No profile yet.'}
CURRENT CONTEXT:
${profile.dynamic?.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 in one call:
```typescript
async function getContext(userId: string, query: string) {
const result = await client.profile({
containerTag: userId,
q: query,
threshold: 0.6
});
return `
User Background:
${result.profile.static.join('\n')}
Current Context:
${result.profile.dynamic.join('\n')}
Relevant Memories:
${result.searchResults?.results.map(m => m.memory).join('\n') || 'None'}
`;
}
```
---
## Profile Buckets
Buckets are **custom topical categories** for a profile — an axis that sits alongside
`static` and `dynamic`. Where static/dynamic split facts by how long-lived they are,
buckets group them by subject (e.g. `preferences`, `goals`, `work`). As content is
ingested, a classifier assigns each memory to the buckets it matches, so you can pull
just the slice of context a given surface needs.
Every org starts with a built-in `preferences` bucket. You can define your own at the
organization or space level in your console settings; space-level buckets are
**add-only** — a container tag inherits all org buckets and may add more, but cannot
disable them.
### Requesting buckets
Pass `include: ["buckets"]` to return bucket-organized memories, and optionally
`buckets` to limit the response to specific keys. `include` also lets you skip
sections you don't need — `["buckets"]` alone omits `static` and `dynamic`.
<Tabs>
<Tab title="fetch">
```typescript
const res = await fetch("https://api.supermemory.ai/v4/profile", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
containerTag: "user_123",
include: ["buckets"],
buckets: ["preferences", "goals"] // optional — omit for all buckets
})
});
const { profile } = await res.json();
console.log(profile.buckets.preferences);
console.log(profile.buckets.goals);
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/profile" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"containerTag": "user_123",
"include": ["buckets"],
"buckets": ["preferences", "goals"]
}'
```
</Tab>
</Tabs>
**Response:**
```json
{
"profile": {
"buckets": {
"preferences": [
"[Summary] Prefers concise, technical answers and dark-mode tooling",
"[Recent] Switched their editor to Zed"
],
"goals": [
"[Recent] Wants to ship the billing revamp this quarter"
]
}
}
}
```
<Note>
**`[Recent]` and `[Summary]` labels.** To keep profiles dense, an entity's older
memories are periodically aggregated into a short synthesis. Entries prefixed
`[Summary]` are that aggregated context; entries prefixed `[Recent]` were ingested
since the last aggregation and aren't summarized yet. The `dynamic` section uses the
same `[Recent]` prefix (plus a `[YYYY-MM-DD]` date). Strip the prefixes if you only
want raw text, or keep them to signal recency to your model.
</Note>
### List bucket definitions
To see which buckets are configured for a container tag (org buckets merged with any
space-level additions), call `/v4/profile/buckets`:
<Tabs>
<Tab title="fetch">
```typescript
const res = await fetch("https://api.supermemory.ai/v4/profile/buckets", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ containerTag: "user_123" })
});
const { buckets } = await res.json();
// [{ key: "preferences", description: "..." }, ...]
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v4/profile/buckets" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTag": "user_123"}'
```
</Tab>
</Tabs>
**Response:**
```json
{
"buckets": [
{
"key": "preferences",
"description": "Explicit first-person preferences the person directly stated."
}
]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `buckets[].key` | string | Stable slug, also stored on each memory. Lowercase alphanumeric with `-`/`_`, 164 chars |
| `buckets[].description` | string | What belongs in the bucket — guides the ingestion classifier |
<Tip>
Bucket descriptions steer classification. A precise description ("Explicit
first-person preferences only — exclude inferred traits") yields cleaner buckets than
a vague one. `static` and `dynamic` are reserved and can't be used as bucket keys.
</Tip>
---
## Framework Examples
<Accordion title="Express.js Middleware">
```typescript
async function withProfile(req, res, next) {
if (!req.user?.id) return next();
try {
const { profile } = await client.profile({
containerTag: 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 client.profile({
containerTag: 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-4o"), {
containerTag: "user-123",
customId: "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 ProfileResponse {
profile: {
static?: string[]; // Long-term facts
dynamic?: string[]; // Recent context
buckets?: Record<string, string[]>; // Topical buckets, keyed by bucket key
};
searchResults?: { // Only if q parameter provided
results: SearchResult[];
total: number;
timing: number;
};
}
```
---
## Next Steps
- [User Profiles Concept](/concepts/user-profiles) — Understand static vs dynamic
- [Ingesting Content](/add-memories) — Build profiles by adding content
- [AI SDK Integration](/integrations/ai-sdk) — Automatic profile injection