> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Concepts

> Understanding Nebula's architecture: memories, sources, and the vector graph

## Memories and Sources

In Nebula, everything is stored as a **memory**. A memory is a container with a unique `memory_id` that holds one or more **sources**:

* **Document Memory**: An entire document, automatically split into sources for processing. You can upload text, pre-chunked text, or a file. A short piece of text (like a user preference) is a document memory with a single source.
* **Conversation Memory**: A full conversation where each message is a source. Set `kind="conversation"` and pass a `messages` list of `{role, content}` objects to create one.

Each source has a unique **source ID** for read-only provenance in memory and search responses. To change stored content, update memory-level properties or append replacement content as a new memory entry.

## Document Memories

<CodeGroup>
  ```python Python theme={null}
  from nebula import Nebula

  nebula = Nebula()
  collection = nebula.collections.create(name="research_papers").results

  # Store document text
  created = nebula.memories.create(
      collection_id=collection.id,
      raw_text="Full document content...",
      kind="document",
      metadata={"title": "Research Paper"},
  ).results
  doc_id = created.id

  # Or store a short piece of text
  nebula.memories.create(
      collection_id=collection.id,
      raw_text="User prefers dark mode",
      kind="document",
      metadata={"user_id": "user_789"},
  )
  ```

  ```javascript JavaScript theme={null}
  import Nebula from '@nebula-ai/sdk';

  const client = new Nebula({ apiKey: process.env.NEBULA_API_KEY });
  const { results: collection } = await client.collections.create({
    name: 'research_papers',
  });

  // Store document text
  const { results: doc } = await client.memories.create({
    collection_id: collection.id,
    raw_text: 'Full document content...',
    kind: 'document',
    metadata: { title: 'Research Paper' },
  });
  const docId = doc.id;

  // Or store a short piece of text
  await client.memories.create({
    collection_id: collection.id,
    raw_text: 'User prefers dark mode',
    kind: 'document',
    metadata: { user_id: 'user_789' },
  });
  ```

  ```bash cURL theme={null}
  # Store document text
  curl -X POST "https://api.zeroset.com/v1/memories" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "collection_id": "COLLECTION_ID",
      "kind": "document",
      "raw_text": "Full document content...",
      "metadata": {"title": "Research Paper"}
    }'

  # Upload file (base64 encoded)
  curl -X POST "https://api.zeroset.com/v1/memories" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "collection_id": "COLLECTION_ID",
      "kind": "document",
      "content_parts": [{
        "type": "document",
        "data": "BASE64_ENCODED_FILE_DATA",
        "media_type": "application/pdf",
        "filename": "document.pdf"
      }],
      "metadata": {"title": "Research Paper"}
    }'
  ```
</CodeGroup>

## Conversation Memories

Create a conversation by passing `kind="conversation"` and an initial `messages` list. Append more messages by calling `memories.append()` with the conversation's `memory_id`.

<CodeGroup>
  ```python Python theme={null}
  collection = nebula.collections.create(name="support_chats").results

  # Create a conversation memory
  conv = nebula.memories.create(
      collection_id=collection.id,
      kind="conversation",
      messages=[{"content": "Hello! How can I help?", "role": "assistant"}],
  ).results
  conv_id = conv.id

  # Add messages to the same conversation
  nebula.memories.append(
      conv_id,
      collection_id=collection.id,
      messages=[
          {"content": "I need help", "role": "user"},
          {"content": "I'll help you", "role": "assistant"},
      ],
  )
  ```

  ```javascript JavaScript theme={null}
  const { results: collection } = await client.collections.create({
    name: 'support_chats',
  });

  // Create a conversation memory
  const { results: conv } = await client.memories.create({
    collection_id: collection.id,
    kind: 'conversation',
    messages: [{ content: 'Hello! How can I help?', role: 'assistant' }],
  });
  const convId = conv.id;

  // Add messages to the same conversation
  await client.memories.append(convId, {
    collection_id: collection.id,
    messages: [
      { content: 'I need help', role: 'user' },
      { content: "I'll help you", role: 'assistant' },
    ],
  });
  ```

  ```bash cURL theme={null}
  # Create conversation
  curl -X POST "https://api.zeroset.com/v1/memories" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "collection_id": "COLLECTION_ID",
      "kind": "conversation",
      "messages": [{"content": "Hello! How can I help?", "role": "assistant"}]
    }'

  # Add messages (use memory_id from response)
  curl -X POST "https://api.zeroset.com/v1/memories/MEMORY_ID/append" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "collection_id": "COLLECTION_ID",
      "messages": [
        {"content": "I need help", "role": "user"},
        {"content": "I'\''ll help you", "role": "assistant"}
      ]
    }'
  ```
</CodeGroup>

See [Conversations Guide](/guides/conversations) for multi-turn patterns.

## The Vector Graph

When you store memories, Nebula automatically extracts structured knowledge and builds a graph of entities and relationships. When you search, the response contains three memory layers plus optional sources:

* **Semantics**: Subject-predicate-value assertions (e.g., "Sarah - led - the Aurora migration"), with confidence that grows through corroboration across sources
* **Procedures**: User preferences and behavioral patterns (e.g., "Prefers dark mode")
* **Episodes**: Temporally clustered events with timestamps
* **Sources**: The original source text that grounds each assertion, returned when `include_sources` is enabled

<Warning>The use of `metadata` is highly discouraged. Nebula already consolidates all the semantics from your content automatically.</Warning>

## Memory Lifecycle

1. **Creation**: `memories.create()` creates a new memory
2. **Expansion**: `memories.append(memory_id, ...)` adds content to an existing memory
3. **Extraction**: Nebula extracts entities, facts, and relationships into the vector graph
4. **Retrieval**: `memories.search()` returns semantics, procedures, and episodes, with sources available through `include_sources`; `memories.retrieve(id)` returns the raw memory with all sources
5. **Source Provenance**: Use source IDs to trace retrieval results back to stored memory content
6. **Deletion**: `memories.delete(id)` removes an entire memory and all its sources

<Tip>Build complete units by using `memory_id` to group entire conversations or documents in one container, and group related memories into [collections](/guides/collections).</Tip>

## Next Steps

* [Memory Operations](/guides/memory-operations) - Store, retrieve, and delete memories
* [Collections](/guides/collections) - Organize memories into collections
* [Search](/guides/search) - Semantic search and filtering
