supermemory/apps/docs/concepts/customization.mdx
Dhravya Shah 48167c3246 docs: fix production build breaker — HTML comments are invalid MDX
71 '<!-- CONFIRM -->' review markers across 19 files used HTML comment
syntax, which MDX cannot parse. One parse error breaks the whole
production build — this is why the deployed site 404'd on every page
while local dev limped along. All converted to {/* */} (code-fence
contents untouched). Also: remove the legacy source-'/' redirect,
replace the phantom architecture-diagram image with an ASCII diagram
until the real one lands.

Verified locally: mintlify broken-links parses all pages clean (one
known-good /api-reference tab link that 307s at runtime), and /,
/overview, /concepts/architecture, /quickstart, /patterns/*,
/versioning all render 200 with content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 16:47:05 -07:00

216 lines
12 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: "Customize what supermemory remembers"
sidebarTitle: "Customization"
description: "Steer memory extraction with filter prompts, entity context, and org-level settings — and know exactly when each one applies."
icon: "settings-2"
---
Supermemory decides what's worth remembering. You can steer that decision.
Every document you ingest runs through the memory model with a set of extraction rules. The defaults are tuned for conversational memory — chats between a user and an assistant. If you're building something else (a task agent, a research tool, a support brain), you tell the model what matters through two fields: an org-wide **filter prompt** and a per-container **entity context**. Both are prompts, both are additive, and both apply at ingestion time.
Here's the whole surface at a glance:
| Lever | Scope | What it's for | Where you set it |
|-------|-------|---------------|------------------|
| `filterPrompt` | Entire org | Rules about **what to remember and what to skip** | `PATCH /v3/settings`, or the console |
| `entityContext` | One container tag | **Who or what the entity is** — grounding for extraction | On `add()`, or `PATCH /v3/container-tags/{tag}` |
| Organization Context | Entire org | The console's no-code editor for `filterPrompt` | console → Settings → Organization Context |
That third row isn't a separate field. The console's Organization Context panel writes the same `filterPrompt` setting the API does — it's the same lever with a UI on it. {/* CONFIRM: does the console cap Organization Context length? Couldn't find a 750-char (or any) cap in console-v2 code */}
## Set org-wide rules with filterPrompt
The filter prompt is rules: what to prioritize, what to skip, across every container in your org. It applies to everything you ingest through any door — direct `add()` calls, file uploads, connectors, MCP.
You have to enable LLM filtering to use it — the API rejects a `filterPrompt` without `shouldLLMFilter: true`:
<CodeGroup>
```typescript TypeScript
await client.settings.update({
shouldLLMFilter: true,
filterPrompt: `You're ingesting for Brand.ai's brand guidelines assistant.
Prioritize: approved tone-of-voice rules, logo usage decisions, official taglines.
Skip: drafts, pre-2024 materials, internal debate about pending changes.`,
});
```
```bash cURL
curl -X PATCH https://api.supermemory.ai/v3/settings \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"shouldLLMFilter": true,
"filterPrompt": "You are ingesting for Brand.ai'\''s brand guidelines assistant. Prioritize: approved tone-of-voice rules, logo usage decisions, official taglines. Skip: drafts, pre-2024 materials, internal debate about pending changes."
}'
```
</CodeGroup>
Write it like rules, not like a description. "Prioritize X, skip Y" gives the model a decision procedure; "this org is about brand guidelines" doesn't. Save the describing for entity context — that's what it's for.
Settings apply to new content only. Changing your filter prompt doesn't reprocess memories that already exist.
## Describe the entity with entityContext
Entity context answers a different question: not *what to remember*, but *who or what this container is about*. It's fed into memory generation for that container tag, so it changes what gets extracted, how it's prioritized, and what gets skipped. "User's name is Priya; 'the app' means her fitness startup's iOS app" turns ambiguous ingested text into specific, searchable memories.
It lives on the [container tag](/concepts/permissioning), not on your org. Max 1,500 characters. You can set it two ways.
Inline, when you add content:
<CodeGroup>
```typescript TypeScript
await client.add({
content: "Asked about logo variations for dark backgrounds again — leaning toward the mono version.",
containerTag: "user_4f8a",
entityContext: `Design conversations between john@acme.com and the Brand.ai assistant.
"The logo" means Acme's primary mark. Focus on John's design preferences and constraints.`,
});
```
```bash cURL
curl -X POST https://api.supermemory.ai/v3/documents \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Asked about logo variations for dark backgrounds again — leaning toward the mono version.",
"containerTag": "user_4f8a",
"entityContext": "Design conversations between john@acme.com and the Brand.ai assistant. \"The logo\" means Acme'\''s primary mark. Focus on John'\''s design preferences and constraints."
}'
```
</CodeGroup>
Or directly on the tag, without ingesting anything. The TS SDK doesn't expose a container-tag update method yet, so this one is a REST call:
```bash cURL
curl -X PATCH https://api.supermemory.ai/v3/container-tags/user_4f8a \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entityContext": "Design conversations between john@acme.com and the Brand.ai assistant. \"The logo\" means Acme'\''s primary mark. Focus on John'\''s design preferences and constraints."
}'
```
{/* CONFIRM: PATCH /v3/container-tags/{tag} is admin-gated in the backend (roleGate ROLE_ADMIN) — confirm which API keys pass that gate before documenting the restriction. */}
Either way, entity context **persists on the tag**. Pass it on one `add()` call and it's stored — every future document in that container is processed with it, including connector syncs landing in the same tag, until you overwrite it or set it to `null`. It's tag state, not a per-request option. If that's not what you expected, it's the one behavior on this page worth rereading.
<Note>
Entity context only applies when a document has exactly one container tag. If you're still passing the deprecated `containerTags` array with multiple tags, entity context is skipped for that document — one more reason to use singular `containerTag`.
</Note>
## How the levers compose
Additive, not override. Your prompts are prepended to supermemory's base extraction rules — they never replace them. The filter rules the memory model actually sees look like this:
```text
Overall context - {your filterPrompt}
Entity specific context - {your entityContext}
EXTRACT: Facts, decisions, preferences, relationships, events, dates, names.
SKIP: Unconfirmed assistant suggestions, greetings, vague statements.
```
The last two lines are the built-in defaults, and they're always there. So the division of labor is:
- **Filter prompt = rules.** What counts, what doesn't, org-wide.
- **Entity context = grounding.** Who this container's entity is, so extraction resolves "he", "the project", "the app" into real referents.
- **Base rules = the floor.** Facts, decisions, and preferences get extracted; greetings and vague statements get skipped, whether or not you configure anything.
You can't use these levers to disable extraction of something the base rules want (you can deprioritize it, but the floor stays). And you can't break extraction by leaving them empty — the defaults carry you. The levers exist to resolve ambiguity and shift priorities, not to rewrite the pipeline.
## Tune for agent and task memory
The defaults are conversational. Look at that `SKIP` line again: *unconfirmed assistant suggestions*. For a chat product that's exactly right — the assistant floats an idea, the user ignores it, nothing worth remembering happened. For an autonomous agent it's exactly wrong: the assistant's actions **are** the record. An agent that ran a checkout flow, hit a selector that stopped working, and found a workaround has produced three facts worth remembering — and a conversational filter will shrug at all of them.
The fix is both levers together. Org-level rules that redefine what counts as a fact:
<CodeGroup>
```typescript TypeScript
await client.settings.update({
shouldLLMFilter: true,
filterPrompt: `You're remembering for autonomous task agents, not a chat assistant.
The agent's own actions and their results are facts — never skip them as suggestions.
Prioritize: task outcomes and their status, environment quirks and workarounds,
failures and what fixed them, user-stated constraints and approvals.
Skip: step-by-step narration, transient page state, retries that added no new information.`,
});
```
```bash cURL
curl -X PATCH https://api.supermemory.ai/v3/settings \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"shouldLLMFilter": true,
"filterPrompt": "You are remembering for autonomous task agents, not a chat assistant. The agent'\''s own actions and their results are facts — never skip them as suggestions. Prioritize: task outcomes and their status, environment quirks and workarounds, failures and what fixed them, user-stated constraints and approvals. Skip: step-by-step narration, transient page state, retries that added no new information."
}'
```
</CodeGroup>
Plus per-agent entity context, so each agent's container knows what its pronouns mean:
```bash cURL
curl -X PATCH https://api.supermemory.ai/v3/container-tags/agent_checkout_bot \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entityContext": "This container belongs to checkout-bot, a browser agent running e-commerce checkout flows for Acme'\''s QA team. \"The site\" means the storefront under test; \"the run\" means one full checkout attempt."
}'
```
If your agents share one container and you split them by role, put the role in metadata, not the tag — container tags are isolation boundaries, and agents that need to hand off to each other need to share one. The full pattern is in [agent task memory](/patterns/agent-task-memory).
## What applies to direct add() writes
Everything. There's no bypass: a direct `add()` goes through the same ingestion pipeline as a connector sync, which means the same filter prompt and the same entity context shape what comes out. Precisely:
- **Your document is stored as-is.** The levers govern memory *derivation*, not document storage. The raw content stays retrievable through [document search](/concepts/hybrid-search).
- **The derived memories obey all the levers.** A restrictive filter prompt can mean a document you explicitly added produces one memory, or none. That's the levers working, not ingestion failing — check the document's processing status if you want to confirm it ingested.
- **There's no "remember this verbatim" flag on `add()`.** If you need guaranteed word-for-word recall, that's what document search is for; memory extraction is always an editorial pass.
- **`entityContext` on `add()` writes tag state.** As above: it persists on the container tag and applies to all future ingestion there, not only the document you attached it to.
So if a write "didn't stick," the order to debug in: did the document reach `done`? Then did your filter prompt tell the model to skip exactly that kind of content? It's usually the second one.
## Tune chunk size and connector branding
Two more knobs live on the same `/v3/settings` endpoint.
**Chunk size** controls how documents split for search, in characters. Smaller chunks retrieve more precisely but carry less context each:
<CodeGroup>
```typescript TypeScript
await client.settings.update({
chunkSize: 512, // characters; -1 restores supermemory's default
});
```
```bash cURL
curl -X PATCH https://api.supermemory.ai/v3/settings \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "chunkSize": 512 }'
```
</CodeGroup>
Use 256512 when you need precise citations, 10242048 for long-form analysis, and `-1` unless you've measured a reason not to. {/* CONFIRM: recommended ranges — these are editorial guidance, not from code */}
**Connector branding** lets the OAuth screen say "Log in to YourApp" instead of "Log in to Supermemory" by supplying your own client credentials (`googleDriveCustomKeyEnabled` + client ID/secret, and the same pattern for Notion and OneDrive). Setup steps are in the [connectors overview](/connectors/overview).
Set the two prompts well and the same pipeline that ships tuned for chat becomes a task-memory engine.
## Where next
- [Agent task memory](/patterns/agent-task-memory) — the full multi-agent configuration this page's tuning section feeds into
- [User profiles](/concepts/user-profiles) — how extracted memories roll up into a per-entity profile
- [Permissioning](/concepts/permissioning) — container tags, metadata, and scoped keys
- [Adding memories](/add-memories) — every `add()` parameter, including `customId` and metadata