---
title: "Quickstart"
description: "Ingest a conversation and a document, then use document search, memory graph traversal, and profiles — and wire it into a chat harness."
icon: "play"
---

By the end of this page you will:

1. **Ingest a conversation** (how personal memory actually arrives)
2. **Ingest a document** (how knowledge for RAG arrives)
3. **Retrieve three ways** — document search (RAG), memory graph traversal, and user profile
4. **Drop it into a chat harness** that remembers across restarts

Same `containerTag` for everything. One engine, three ways out.

## Get an API key

Grab a key from the [developer console](https://console.supermemory.ai) — **API Keys → Create API Key**.

**console.supermemory.ai** is where keys and usage live. **app.supermemory.ai** is the consumer product on the same engine — not where you mint API keys.

<CodeGroup>
```bash TypeScript
npm install supermemory
export SUPERMEMORY_API_KEY="sm_..."
```

```bash Python
pip install supermemory
export SUPERMEMORY_API_KEY="sm_..."
```

```bash curl
export SUPERMEMORY_API_KEY="sm_..."
```
</CodeGroup>

## 1. Ingest a conversation

Real apps do not push four isolated one-liners as separate “memories.” They send **conversation turns** — often the full session — under a stable `customId` so the pipeline can extract facts and link entities.

We’ll use one user (`user_4f8a`) and one chat session. The turns never say “Sarah *is* my VP of Product” — that connection is what the graph should resolve later.

<CodeGroup>
```typescript TypeScript
import Supermemory from "supermemory";

const client = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY });
const user = "user_4f8a";

const conversation = `
user: Just got back from Tokyo — the team offsite went great.
assistant: Glad it went well! Anything stand out?
user: Sarah presented the Q3 roadmap at the offsite.
assistant: Sounds like a big moment for her.
user: She's being promoted to VP of Product.
assistant: Congrats to Sarah — that's huge.
user: I need a gift idea for my VP of Product.
assistant: Happy to help brainstorm something personal.
`.trim();

const conv = await client.add({
  content: conversation,
  containerTag: user,
  customId: "chat_offsite_2026", // one session → one document
  metadata: { type: "conversation" },
  dreaming: "instant", // process this document now — see note below
});

console.log(conv.id, conv.status); // e.g. "queued"
```

```python Python
from supermemory import Supermemory

client = Supermemory()
user = "user_4f8a"

conversation = """
user: Just got back from Tokyo — the team offsite went great.
assistant: Glad it went well! Anything stand out?
user: Sarah presented the Q3 roadmap at the offsite.
assistant: Sounds like a big moment for her.
user: She's being promoted to VP of Product.
assistant: Congrats to Sarah — that's huge.
user: I need a gift idea for my VP of Product.
assistant: Happy to help brainstorm something personal.
""".strip()

conv = client.add(
    content=conversation,
    container_tag=user,
    custom_id="chat_offsite_2026",
    metadata={"type": "conversation"},
    dreaming="instant",  # process this document now — see note below
)
print(conv.id, conv.status)
```

```bash curl
curl -X POST "https://api.supermemory.ai/v3/documents" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "user: Just got back from Tokyo — the team offsite went great.\nassistant: Glad it went well! Anything stand out?\nuser: Sarah presented the Q3 roadmap at the offsite.\nassistant: Sounds like a big moment for her.\nuser: She is being promoted to VP of Product.\nassistant: Congrats to Sarah — that is huge.\nuser: I need a gift idea for my VP of Product.\nassistant: Happy to help brainstorm something personal.",
    "containerTag": "user_4f8a",
    "customId": "chat_offsite_2026",
    "metadata": { "type": "conversation" },
    "dreaming": "instant"
  }'
```
</CodeGroup>

`add` returns immediately with `status: "queued"`. Processing is still **async** — wait until `done` before searching.

<Note>
**`dreaming: "instant"`** — By default, dreaming is `"dynamic"`: Supermemory may batch related documents so memories form from coherent units, which can lag after `status: "done"`. For this quickstart (and any path where you need memories/profiles right away), pass **`dreaming: "instant"`** so the document is processed on its own as soon as it finishes indexing. That bills one extra operation per document. See [Processing Modes](/ingestion/add-memories#processing-modes).
</Note>

## 2. Ingest a document

Now add **knowledge** the agent should ground on — a short internal note the conversation never fully spelled out. This is the SuperRAG / document path.

<CodeGroup>
```typescript TypeScript
const handbook = `
# Team notes — gifts & recognition

When someone is promoted to VP or above, the company recommends a thoughtful gift
in the $75–$150 range. Experiences tied to recent team milestones land better
than generic swag.

For product leadership, books on platform strategy or a dinner near the last
offsite city are common picks. Tokyo offsites often inspire travel-themed gifts.
`.trim();

const doc = await client.add({
  content: handbook,
  containerTag: user,
  customId: "doc_gift_policy",
  metadata: { type: "document", source: "handbook" },
  taskType: "superrag"
});

console.log(doc.id, doc.status);
```

```python Python
handbook = """
# Team notes — gifts & recognition

When someone is promoted to VP or above, the company recommends a thoughtful gift
in the $75–$150 range. Experiences tied to recent team milestones land better
than generic swag.

For product leadership, books on platform strategy or a dinner near the last
offsite city are common picks. Tokyo offsites often inspire travel-themed gifts.
""".strip()

doc = client.add(
    content=handbook,
    container_tag=user,
    custom_id="doc_gift_policy",
    metadata={"type": "document", "source": "handbook"},
    task_type="superrag"
)
print(doc.id, doc.status)
```

```bash curl
curl -X POST "https://api.supermemory.ai/v3/documents" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "# Team notes — gifts & recognition\n\nWhen someone is promoted to VP or above, the company recommends a thoughtful gift in the $75–$150 range. Experiences tied to recent team milestones land better than generic swag.\n\nFor product leadership, books on platform strategy or a dinner near the last offsite city are common picks. Tokyo offsites often inspire travel-themed gifts.",
    "containerTag": "user_4f8a",
    "customId": "doc_gift_policy",
    "metadata": { "type": "document", "source": "handbook" },
    "taskType": "superrag"
  }'
```
</CodeGroup>

## 3. Wait until both are `done`

Poll document status. With **`dreaming: "instant"`**, once status is `done` the document is indexed **and** memories for that document should be available for search and profiles (`queued → extracting → … → done`).

> Note that the preferred way is to have `dreaming: dynamic`. supermemory charges one extra operation for instant dreaming. Instant is good for one off tests, setup, debugging and benchmarking.

<CodeGroup>
```typescript TypeScript
async function waitUntilDone(id: string) {
  for (;;) {
    const d = await client.documents.get(id);
    if (d.status === "done" || d.status === "failed") return d;
    await new Promise((r) => setTimeout(r, 1500));
  }
}

await waitUntilDone(conv.id);
await waitUntilDone(doc.id);
console.log("ready to search");
```

```python Python
import time

def wait_until_done(doc_id: str):
    while True:
        d = client.documents.get(doc_id)
        if d.status in ("done", "failed"):
            return d
        time.sleep(1.5)

wait_until_done(conv.id)
wait_until_done(doc.id)
print("ready to search")
```

```bash curl
# replace DOC_ID with each document id from the add responses
curl "https://api.supermemory.ai/v3/documents/DOC_ID" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY"
# repeat until "status": "done"
```
</CodeGroup>

Short text with instant dreaming usually finishes in a few seconds. Larger PDFs take longer. If you omit `dreaming` (default `"dynamic"`), document RAG can work after `done` while memory extraction may still be batching — use `"instant"` when the next step is memory search or profiles.

## 4. Three ways to get context back

### A. Document search (RAG)

Chunk-level retrieval over raw knowledge — use when you need **what the docs say**.

<CodeGroup>
```typescript TypeScript
const rag = await client.search({
  q: "gift ideas for a VP promotion after a Tokyo offsite",
  containerTag: user,
  searchMode: "documents",
  limit: 3,
});

for (const hit of rag.results) {
  console.log(hit.title ?? hit.id);
  for (const chunk of hit.chunks ?? []) {
    console.log(" ", chunk.content?.slice(0, 160));
  }
}
```

```python Python
rag = client.search.memories(
    q="gift ideas for a VP promotion after a Tokyo offsite",
    container_tag=user,
    search_mode="documents",
    limit=3,
)

for hit in rag.results:
    print(getattr(hit, "title", None) or hit.id)
    for chunk in hit.chunks or []:
        print(" ", (chunk.content or "")[:160])
```

```bash curl
curl -X POST "https://api.supermemory.ai/v3/search" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "gift ideas for a VP promotion after a Tokyo offsite",
    "containerTag": "user_4f8a",
    "searchMode": "documents",
    "limit": 3
  }'
```
</CodeGroup>

You should see chunks from the handbook (budget range, Tokyo offsite angle) — **document grounding**, not personal facts.

Switch `searchMode` to `"hybrid"` to get extracted memories and document chunks together:

```typescript
await client.search({
  q: "gift ideas for a VP promotion after a Tokyo offsite",
  containerTag: user,
  searchMode: "hybrid",
  limit: 5,
});
```

### B. Memory graph traversal

Search **extracted memories** with related edges. This is the entity-chain moment: gift → VP of Product → Sarah → Tokyo offsite.

<CodeGroup>
```typescript TypeScript
const memories = await client.search({
  q: "What gift should I get, and why?",
  containerTag: user,
  searchMode: "memories",
  include: { relatedMemories: true },
  limit: 5,
});

console.log(JSON.stringify(memories, null, 2));
```

```python Python
memories = client.search.memories(
    q="What gift should I get, and why?",
    container_tag=user,
    search_mode="memories",
    include={"relatedMemories": True},
    limit=5,
)
print(memories)
```

```bash curl
curl -X POST "https://api.supermemory.ai/v4/search" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "What gift should I get, and why?",
    "containerTag": "user_4f8a",
    "searchMode": "memories",
    "include": { "relatedMemories": true },
    "limit": 5
  }'
```
</CodeGroup>

Abbreviated shape:

```json
{
  "results": [
    {
      "memory": "Sarah is being promoted to VP of Product",
      "similarity": 0.81,
      "context": {
        "parents": [
          {
            "memory": "Sarah presented the Q3 roadmap at the Tokyo offsite",
            "relation": "extends"
          }
        ],
        "children": [
          {
            "memory": "User needs a gift idea for their VP of Product, Sarah",
            "relation": "derives"
          }
        ]
      }
    }
  ],
  "timing": 287
}
```

You never wrote “Sarah is my VP of Product” as one sentence. The graph connected sessions of speech. Deep dive: [graph memory](/concepts/graph-memory).

### C. User profile

Profiles are the **always-on** summary (static + recent dynamic) of an entity (or a `containerTag`) - what you inject every turn without re-searching the world.

<CodeGroup>
```typescript TypeScript
const { profile, searchResults } = await client.profile({
  containerTag: user,
  q: "gift for the person being promoted", // optional: also run search
});

console.log("static:", profile.static);
console.log("dynamic:", profile.dynamic);
console.log("search hits:", searchResults?.results?.length ?? 0);
```

```python Python
result = client.profile(
    container_tag=user,
    q="gift for the person being promoted",
)

print("static:", result.profile.static)
print("dynamic:", result.profile.dynamic)
print("search hits:", len(result.search_results.results) if result.search_results else 0)
```

```bash curl
curl -X POST "https://api.supermemory.ai/v4/profile" \
  -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "containerTag": "user_4f8a",
    "q": "gift for the person being promoted"
  }'
```
</CodeGroup>

> There is a lot more to profiles - with [Buckets](/user-profiles/buckets), for example, you can make supermemory learn and categorize incoming information for learning specific things.


| Path | Use when |
|---|---|
| **Document search** | Ground in policies, docs, handbooks |
| **Memory + related** | Personal facts, entity links, “what’s true about this user” |
| **Profile** | Cheap always-on context every LLM turn |

Same `containerTag` → same context pool. See [Memory vs RAG](/concepts/memory-vs-rag).

## 5. Put it in a harness

There is no single required harness. The pattern is the same wherever you run the model: **read** context (profile / search / docs), generate, **write** the turn back under a stable `customId` so the session stays one document.

Here are two example shapes — pick whatever matches your stack.

### Example: explicit profile + search + add

<CodeGroup>
```typescript TypeScript
// npm install supermemory openai
import Supermemory from "supermemory";
import OpenAI from "openai";
import * as readline from "node:readline/promises";

const memory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY });
const llm = new OpenAI();
const user = "user_4f8a";
const sessionId = "chat_live_session";
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });

while (true) {
  const question = await rl.question("you: ");

  const { profile, searchResults } = await memory.profile({
    containerTag: user,
    q: question,
  });

  // optional: also pull document chunks for grounding
  const rag = await memory.search({
    q: question,
    containerTag: user,
    searchMode: "documents",
    limit: 3,
  });
  const docBits = rag.results
    .flatMap((r) => r.chunks ?? [])
    .map((c) => c.content)
    .filter(Boolean)
    .slice(0, 3);

  const context = [
    "## Profile (static)",
    ...profile.static,
    "## Profile (dynamic)",
    ...profile.dynamic,
    "## Related memories",
    ...(searchResults?.results?.map((m) => m.memory).filter(Boolean) ?? []),
    "## Docs",
    ...docBits,
  ].join("\n");

  const res = await llm.chat.completions.create({
    model: "gpt-4o",
    messages: [
      { role: "system", content: `You help this user. Context:\n${context}` },
      { role: "user", content: question },
    ],
  });
  const answer = res.choices[0].message.content ?? "";
  console.log(`assistant: ${answer}`);

  // append this turn into the same conversation document
  await memory.add({
    content: `user: ${question}\nassistant: ${answer}`,
    containerTag: user,
    customId: sessionId,
  });
}
```

```python Python
# pip install supermemory openai
from supermemory import Supermemory
from openai import OpenAI

memory = Supermemory()
llm = OpenAI()
user = "user_4f8a"
session_id = "chat_live_session"

while True:
    question = input("you: ")

    result = memory.profile(container_tag=user, q=question)
    rag = memory.search.memories(
        q=question, container_tag=user, search_mode="documents", limit=3
    )
    doc_bits = []
    for hit in rag.results:
        for chunk in hit.chunks or []:
            if chunk.content:
                doc_bits.append(chunk.content[:300])
            if len(doc_bits) >= 3:
                break

    memories = result.search_results.results if result.search_results else []
    context = "\n".join(
        [
            "## Profile (static)",
            *result.profile.static,
            "## Profile (dynamic)",
            *result.profile.dynamic,
            "## Related memories",
            *[m.memory for m in memories if m.memory],
            "## Docs",
            *doc_bits,
        ]
    )

    res = llm.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": f"You help this user. Context:\n{context}"},
            {"role": "user", "content": question},
        ],
    )
    answer = res.choices[0].message.content or ""
    print(f"assistant: {answer}")

    memory.add(
        content=f"user: {question}\nassistant: {answer}",
        container_tag=user,
        custom_id=session_id,
    )
```
</CodeGroup>

### Example: Vercel AI SDK

Same pattern, wrapped: `withSupermemory` injects context and can save the conversation for you. Details: [AI SDK integration](/integrations/ai-sdk).

```typescript
// npm install ai @ai-sdk/openai @supermemory/tools
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { withSupermemory } from "@supermemory/tools/ai-sdk";
import * as readline from "node:readline/promises";

const model = withSupermemory(openai("gpt-4o"), {
  containerTag: "user_4f8a",
  customId: "chat_live_session", // keep stable for the whole session
  mode: "full", // profile + query search
});

const rl = readline.createInterface({ input: process.stdin, output: process.stdout });

while (true) {
  const prompt = await rl.question("you: ");
  const { text } = await generateText({ model, prompt });
  console.log(`assistant: ${text}`);
}
```

Try:

```
you: What gift should I get for the person being promoted?
assistant: You're looking for something for Sarah — she's being promoted to VP of
Product after presenting the Q3 roadmap in Tokyo. Your handbook suggests $75–$150
and something tied to the offsite; a Tokyo-inspired experience or platform-strategy
book would fit…
```

### Kill it, restart it

Ctrl+C the process, start again with the **same** `containerTag` (and optional same `customId` for the live session). Ask:

```
you: who's getting promoted?
assistant: Sarah — she's being promoted to VP of Product.
```

Nothing was reloaded from your process. Memory and docs live in supermemory.

## Mental model

```
  INGEST                         WAIT                    RETRIEVE
  ──────                         ────                    ────────
  Conversation (customId)   →    status === done    →    Memory graph (+ related)
  Document (customId)       →    status === done    →    Document search (RAG)
                                                     →    Profile (static + dynamic)
                                                              │
                                                              ▼
                                                         Chat harness
```

## Where next

<CardGroup cols={2}>
  <Card title="Add context" icon="plus" href="/ingestion/add-memories">
    Conversations, files, URLs, customId updates, and status.
  </Card>
  <Card title="Search" icon="search" href="/recall/search">
    Hybrid vs memories, filters, thresholds, rerank.
  </Card>
  <Card title="Graph memory" icon="waypoints" href="/concepts/graph-memory">
    How relations and entity chains are produced.
  </Card>
  <Card title="User profiles" icon="user" href="/concepts/user-profiles">
    Static vs dynamic, and when to inject a profile every turn.
  </Card>
  <Card title="AI SDK" icon="triangle" href="/integrations/ai-sdk">
    withSupermemory modes, customId, addMemory.
  </Card>
  <Card title="Container tags" icon="lock" href="/concepts/container-tags">
    Isolation for multi-tenant products.
  </Card>
</CardGroup>
