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

# Knowledge & RAG

> How ModuleX retrieves your company knowledge: knowledge bases, managed (modulexdb) versus bring-your-own-key storage, and the ingest and retrieval flow that powers RAG.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

ModuleX uses **retrieval-augmented generation (RAG)** to ground answers in your own
content. You upload documents to a **knowledge base**, ModuleX prepares them for
search, and your chats, the [Assistant](/concepts/assistant), and your
[workflows](/concepts/workflows-and-runs) can then retrieve the most relevant
passages on demand — so responses cite your material instead of guessing.

This page explains the ideas you need: what a knowledge base is, the difference
between managed and bring-your-own storage, and the two halves of RAG — getting
content in (ingest) and getting answers out (retrieval).

<MediaEmbed id="MX-MEDIA-1130" type="image" caption={"A single diagram showing the two halves of RAG side by side — ingest on the left, retrieval on the right."} />

## What a knowledge base is

A **knowledge base** is a named collection of your documents that ModuleX has
prepared for search. Think of it as one searchable library: a set of product
manuals, a policy handbook, or a folder of support articles.

Each knowledge base carries its own settings for how documents are split and how
they are turned into searchable vectors, so you can tune one library for long
reference PDFs and another for short snippets — without affecting the rest.

<CardGroup cols={3}>
  <Card title="Documents" icon="file-text">
    The files you upload. Each one moves through the [ingest](#getting-content-in-ingest)
    pipeline and ends up searchable.
  </Card>

  <Card title="Chunks" icon="scissors">
    Each document is split into smaller passages. Retrieval returns chunks, not
    whole files, so answers stay focused.
  </Card>

  <Card title="Embeddings" icon="vector-square">
    Every chunk is converted to a numeric vector that captures its meaning, which
    is what makes search by meaning possible.
  </Card>
</CardGroup>

You can manage knowledge bases in the app or over the API. For the hands-on
walkthrough, see [Knowledge overview](/platform/knowledge/overview) and the
[Build a RAG knowledge base](/guides/build-a-knowledge-base) guide.

<Tip>
  Throughout these docs the feature is called **Knowledge** (singular). A single
  library is a **knowledge base**, often shortened to **KB**.
</Tip>

## Managed versus bring-your-own storage

When you create a knowledge base, you choose where the vectors live. This choice
decides both who hosts the storage and how usage is billed.

<CardGroup cols={2}>
  <Card title="Managed (modulexdb)" icon="database" href="/integrations/knowledge-providers/modulexdb">
    ModuleX hosts the vector storage for you with the built-in **modulexdb**
    provider. Nothing to set up. **Ingest and retrieval are metered in
    [credits](/billing/credits).**
  </Card>

  <Card title="Bring your own (BYOK)" icon="key" href="/platform/knowledge/external-providers">
    Point a knowledge base at a vector store you already run. ModuleX reads and
    writes to it, and **usage on your own store is not charged in credits** —
    your provider bills you directly.
  </Card>
</CardGroup>

### Managed knowledge: modulexdb

Managed knowledge bases use ModuleX's hosted vector store, **modulexdb**. They are
the fastest way to start because there is no external account to connect. Because
ModuleX runs the storage and the embedding calls on your behalf, **each retrieval
and each document ingest spends credits** (see [How credits apply](#how-credits-apply)).

### Bring your own key (BYOK)

If you already operate a vector database, you can connect it and keep your data in
your own infrastructure. ModuleX supports these external knowledge providers:

<CardGroup cols={2}>
  <Card title="Qdrant" icon="circle" href="/integrations/knowledge-providers/qdrant">
    Use a Qdrant cluster as your vector store.
  </Card>

  <Card title="Pinecone" icon="tree-pine" href="/integrations/knowledge-providers/pinecone">
    Use a Pinecone index as your vector store.
  </Card>

  <Card title="MongoDB Atlas" icon="leaf" href="/integrations/knowledge-providers/mongodb-atlas">
    Use MongoDB Atlas Vector Search.
  </Card>

  <Card title="Weaviate" icon="box" href="/integrations/knowledge-providers/weaviate">
    Use a Weaviate instance as your vector store.
  </Card>
</CardGroup>

<Info>
  **Billing in one line.** Managed (modulexdb) knowledge is billed in credits.
  BYOK knowledge is uncosted by ModuleX — it is tracked for analytics only, and any
  charges come from your own provider. See [Credits & metering](/billing/credits).
</Info>

## Getting content in: ingest

**Ingest** is the one-time preparation each document goes through after you upload
it. ModuleX runs it in the background so you can keep working while large files
process.

<Steps>
  <Step title="Upload">
    You add a file to a knowledge base. Supported formats include PDF, Word
    (`.docx` / `.doc`), plain text, Markdown, HTML, CSV, JSON, Excel (`.xlsx`),
    and PowerPoint (`.pptx`).
  </Step>

  <Step title="Parse">
    ModuleX extracts the readable text from the file, whatever its format.
  </Step>

  <Step title="Chunk">
    The text is split into smaller passages using the knowledge base's chunking
    settings, so each piece is a focused, retrievable unit.
  </Step>

  <Step title="Embed">
    Each chunk is converted into an embedding — a vector that represents its
    meaning — and stored alongside the text in the knowledge base.
  </Step>
</Steps>

### Watching a document process

Every document reports its progress, so you always know whether it is ready to
search.

<Accordion title="Document status: pending → processing → completed (or failed)">
  A document moves through these states:

  * **Pending** — uploaded and waiting in the queue.
  * **Processing** — being parsed, chunked, and embedded.
  * **Completed** — fully ingested and ready to retrieve.
  * **Failed** — something went wrong during ingest. You can fix the source file
    and retry the document; retrying a document does not re-charge an unchanged
    ingest.

  For managing and monitoring documents in the app, see
  [Managing documents](/platform/knowledge/documents).
</Accordion>

## Getting answers out: retrieval

**Retrieval** happens every time something asks a question. ModuleX turns the
question into an embedding, compares it against the stored chunks, and returns the
closest matches. Those passages are then handed to the model so its answer is
grounded in your content.

ModuleX offers a few retrieval styles for different needs:

<CardGroup cols={2}>
  <Card title="Semantic (vector) search" icon="search">
    Finds chunks by meaning, even when the wording differs from the question.
    This is the default style.
  </Card>

  <Card title="Hybrid search" icon="layers">
    Blends meaning-based search with exact keyword matching, which helps with
    names, codes, and acronyms.
  </Card>

  <Card title="Multi-knowledge search" icon="library">
    Searches several knowledge bases at once and merges the best results.
  </Card>

  <Card title="Context retrieval" icon="file-stack">
    Returns a ready-to-use block of text, assembled from the top chunks within a
    token budget, for dropping straight into a prompt.
  </Card>
</CardGroup>

### Where retrieval shows up

You rarely call retrieval by hand. It runs wherever an answer should come from
your own material:

<CardGroup cols={3}>
  <Card title="Chat with your knowledge" icon="messages-square" href="/platform/chat/knowledge-chat">
    Ask a question in chat and get an answer drawn from your documents.
  </Card>

  <Card title="The Assistant" icon="bot" href="/concepts/assistant">
    The Assistant retrieves from your knowledge as one of the tools it can use.
  </Card>

  <Card title="Knowledge node" icon="workflow" href="/workflow-builder/nodes/knowledge">
    Add a step to a workflow that retrieves from a knowledge base.
  </Card>
</CardGroup>

### Retrieving over the API

If you build on ModuleX directly, you can run a search against a knowledge base
yourself. Authenticate every request with your API key and organization, exactly
as on every other endpoint (see [Authentication](/api-reference/authentication)).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/knowledge-bases/7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44/search \
    -H "Authorization: Bearer mx_live_8Kd2pQ7rExample" \
    -H "X-Organization-ID: org_3xampleOrg42" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "What is our refund policy?",
      "top_k": 5,
      "min_score": 0.2
    }'
  ```

  ```python Python theme={null}
  import asyncio
  from modulex import Modulex


  async def main():
      async with Modulex(
          api_key="mx_live_8Kd2pQ7rExample",
          organization_id="org_3xampleOrg42",
      ) as mx:
          results = await mx.knowledge.search(
              "7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
              "What is our refund policy?",
              top_k=5,
          )
          for match in results.matches:
              print(match.score, match.content)


  asyncio.run(main())
  ```

  ```javascript JavaScript theme={null}
  import { Modulex } from "modulex";

  const client = new Modulex({
    apiKey: "mx_live_8Kd2pQ7rExample",
    organizationId: "org_3xampleOrg42",
  });

  const results = await client.knowledge.search(
    "7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
    { query: "What is our refund policy?", topK: 5, minScore: 0.2 },
  );

  for (const match of results.matches) {
    console.log(match.score, match.content);
  }
  ```
</CodeGroup>

A successful search returns the matching chunks ranked by relevance:

```json Response theme={null}
{
  "query": "What is our refund policy?",
  "knowledge_base_id": "7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
  "top_k": 5,
  "total_matches": 3,
  "matches": [
    {
      "chunk_id": "c1a2b3c4-...",
      "document_id": "d9e8f7a6-...",
      "document_filename": "refund-policy.pdf",
      "chunk_index": 4,
      "score": 0.83,
      "content": "Refunds are available within 30 days of purchase...",
      "metadata": {}
    }
  ]
}
```

<Note>
  On a **managed (modulexdb)** knowledge base, a search that would exceed your plan
  allowance can return a billing denial instead of results — a `402`, `403`, or
  `429` response. See [Usage gating & limits](/billing/usage-gating) and
  [Errors & status codes](/api-reference/errors) for the response shape and how to
  handle it.
</Note>

## How credits apply

Credits are only spent on **managed (modulexdb)** knowledge. BYOK knowledge bases
are not charged by ModuleX. One credit is a small, fixed unit of managed usage
(100 credits = \$1.00).

| Action on a managed knowledge base | What it costs                                                                                                            |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Ingest a document                  | A flat base charge per document, plus the cost of embedding its text. Retrying an unchanged document does not re-charge. |
| Run a retrieval (any search style) | A flat base charge per search, plus the cost of embedding the query.                                                     |

On a **BYOK** knowledge base, neither ingest nor retrieval spends credits.

For the full pricing model — how credits are metered, the wallet, and overage —
see [Credits & metering](/billing/credits) and
[Billing & credits overview](/billing/overview).

## Plan limits

Your plan sets how many knowledge bases you can keep, how large each uploaded file
can be, and how many documents each knowledge base holds. The values below come
from the current subscription plan configuration.

| Limit                        | Free  | Pro   | Max    | Enterprise |
| ---------------------------- | ----- | ----- | ------ | ---------- |
| Knowledge bases              | 10    | 3     | 50     | Unlimited  |
| Max file size per upload     | 10 MB | 50 MB | 100 MB | Unlimited  |
| Documents per knowledge base | 100   | 1,000 | 1,000  | Unlimited  |

<Warning>
  The **Pro** knowledge-base count (3) is lower than **Free** (10) in the current
  plan configuration. This is a known inconsistency in the source data, shown here
  as-is — confirm the limit that applies to your organization on the
  [Plans & pricing](/billing/plans) page before relying on it. The per-upload file
  size is set by your **plan**, not a single fixed cap.
</Warning>

## Where to go next

<CardGroup cols={2}>
  <Card title="Knowledge overview" icon="book-open" href="/platform/knowledge/overview">
    Create and manage knowledge bases in the ModuleX app.
  </Card>

  <Card title="Build a RAG knowledge base" icon="hammer" href="/guides/build-a-knowledge-base">
    A start-to-finish guide: create a knowledge base, ingest documents, and query
    it.
  </Card>

  <Card title="Managed knowledge (modulexdb)" icon="database" href="/platform/knowledge/managed">
    How ModuleX-hosted vector storage and retrieval work.
  </Card>

  <Card title="External knowledge providers" icon="plug" href="/platform/knowledge/external-providers">
    Connect Qdrant, Pinecone, MongoDB Atlas, or Weaviate.
  </Card>
</CardGroup>
