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

# Knowledge Base

> Add document knowledge to agents for grounded, accurate answers

The knowledge system lets agents retrieve relevant information from PDFs, documents, and text before answering, grounding responses in your own sources.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Research Assistant",
    instructions="Answer questions using the knowledge base.",
    knowledge=["research_paper.pdf", "data.txt"],
)

agent.start("What are the key findings?")
```

The user asks about their documents; the agent embeds, searches, and answers from your PDFs and text.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Sources[📄 Sources] --> Chunk[✂️ Chunk + Embed]
    Chunk --> Store[(🗃️ Vector Store)]
    Store --> Answer[✅ Grounded Answer]

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Sources input
    class Chunk,Store process
    class Answer output
```

## Key Features

<CardGroup cols={2}>
  <Card icon="file-pdf">
    Process PDFs, documents, spreadsheets, images, and raw text
  </Card>

  <Card icon="scissors">
    Multiple strategies for optimal text segmentation
  </Card>

  <Card icon="search">
    Vector-based search with optional reranking
  </Card>

  <Card icon="users">
    User, agent, and run-specific knowledge scoping
  </Card>

  <Card icon="project-diagram">
    Optional relationship extraction and storage
  </Card>

  <Card icon="star">
    Automatic quality assessment for stored knowledge
  </Card>
</CardGroup>

## Quick Start

<Steps>
  <Step title="Level 1 — List of sources (simplest)">
    Pass a list of files, directories, or inline text and the agent answers from them.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Research Assistant",
        instructions="Answer questions using the knowledge base.",
        knowledge=["research_paper.pdf", "data.txt"],
    )

    agent.start("What are the key findings?")
    ```

    <Note>
      `Agent(knowledge=[…])` accepts file paths, directory paths, inline text, and cloud storage URIs (`s3://`, `gs://`, `az://`, Azure Blob HTTPS) — see [Cloud Sources](/docs/features/knowledge-cloud-sources). Arbitrary web URLs are skipped: since PraisonAI PR [#4004](https://github.com/MervinPraison/PraisonAI/pull/4004) any `http(s)://` entry is logged with a warning and skipped instead of silently dropped. To ingest a web page, fetch and pass its text, or download it to a local file first.
    </Note>

    <Note>
      `AgentTeam(knowledge=…)` is not wired yet (PraisonAI [#4004](https://github.com/MervinPraison/PraisonAI/pull/4004)) — set `knowledge=…` on each `Agent(...)` in the team instead.
    </Note>
  </Step>

  <Step title="Level 2 — Dict (inline config)">
    Use a dict to pick a vector store while still passing sources inline.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Research Assistant",
        instructions="Answer questions using the knowledge base.",
        knowledge={
            "sources": ["research_paper.pdf", "data.txt"],
            "vector_store": {
                "provider": "chroma",
                "config": {"collection_name": "research_docs", "path": ".praison"},
            },
        },
    )

    agent.start("What are the key findings?")
    ```
  </Step>

  <Step title="Level 3 — Config class (full control)">
    Use `KnowledgeConfig` for typed control over chunking, retrieval, and reranking.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, KnowledgeConfig

    agent = Agent(
        name="Research Assistant",
        instructions="Answer questions using the knowledge base.",
        knowledge=KnowledgeConfig(
            sources=["research_paper.pdf", "data.txt"],
            chunking_strategy="semantic",
            retrieval_k=5,
            rerank=True,
        ),
    )

    agent.start("What are the key findings?")
    ```
  </Step>
</Steps>

## Use a non-OpenAI embedder

By default your knowledge base embeds with OpenAI. Point it at Gemini, Cohere, Ollama, or any mem0-supported provider by setting `embedder` or `embedder_config`.

<Note>
  `embedder="openai"` is the default and means "no override" — it keeps mem0's built-in embedder. Any other value (e.g. `"gemini"`) switches the provider.
</Note>

<Tabs>
  <Tab title="Shorthand">
    Pass the provider name to use its default embedding model.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, KnowledgeConfig

    agent = Agent(
        instructions="Answer from the knowledge base.",
        knowledge=KnowledgeConfig(
            sources=["docs/"],
            embedder="gemini",   # provider shorthand
        ),
    )

    agent.start("What are the key findings?")
    ```
  </Tab>

  <Tab title="Full config">
    Use `embedder_config` to pin a model or pass provider-specific options.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, KnowledgeConfig

    agent = Agent(
        instructions="Answer from the knowledge base.",
        knowledge=KnowledgeConfig(
            sources=["docs/"],
            embedder_config={
                "provider": "gemini",
                "config": {"model": "models/text-embedding-004"},
            },
        ),
    )

    agent.start("What are the key findings?")
    ```
  </Tab>

  <Tab title="Local Ollama">
    Run embeddings locally with Ollama — no API key needed.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, KnowledgeConfig

    agent = Agent(
        instructions="Answer from the knowledge base.",
        knowledge=KnowledgeConfig(
            sources=["docs/"],
            embedder_config={
                "provider": "ollama",
                "config": {
                    "model": "nomic-embed-text",
                    "ollama_base_url": "http://localhost:11434",
                },
            },
        ),
    )

    agent.start("What are the key findings?")
    ```
  </Tab>
</Tabs>

<Tip>
  **When to use which form.** `embedder="<name>"` is the shortcut when the provider's default model is fine. `embedder_config={"provider": ..., "config": {...}}` is the full form — use it to pin a model, set a base URL, or pass provider-specific settings. Set both and they merge: the shorthand fills in `provider` when the full dict omits it.
</Tip>

Supported providers include `openai`, `gemini`, `cohere`, `huggingface`, `ollama`, `voyage`, and `together`.

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Knowledge
    participant VectorStore
    participant LLM

    User->>Agent: Question about documents
    Agent->>Knowledge: search(query)
    Knowledge->>VectorStore: Embed query + semantic search
    VectorStore-->>Knowledge: Top-k chunks
    Knowledge-->>Agent: Retrieved context
    Agent->>LLM: Prompt + context
    LLM-->>Agent: Grounded answer
    Agent-->>User: Response
```

| Phase       | What happens                                                                          |
| ----------- | ------------------------------------------------------------------------------------- |
| 1. Add      | Documents are chunked, embedded, and stored in the vector store via `knowledge.add()` |
| 2. Search   | `knowledge.search(query)` embeds the query and returns top-k similar chunks           |
| 3. Retrieve | Agent injects the chunks as context before calling the LLM                            |
| 4. Generate | LLM answers using the retrieved knowledge; responses are grounded in your data        |

***

## Configuration Options

<Card title="KnowledgeConfig SDK Reference" icon="code" href="/docs/sdk/reference/praisonaiagents/modules/feature_configs">
  Full parameter reference for KnowledgeConfig
</Card>

The most common options at a glance:

| Option              | Type             | Default      | Description                                                                                                                                                                       |
| ------------------- | ---------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sources`           | `list[str]`      | `[]`         | Files, directories, raw text, or cloud URIs (`s3://`, `gs://`, `az://`, Azure blob HTTPS). Arbitrary web URLs are not ingested.                                                   |
| `embedder`          | `str`            | `"openai"`   | Provider shorthand. Any value other than `"openai"` overrides the default (e.g. `"gemini"`, `"cohere"`, `"ollama"`, `"huggingface"`, `"voyage"`). `"openai"` means "no override". |
| `embedder_config`   | `Dict[str, Any]` | `None`       | Full embedder dict `{"provider": ..., "config": {...}}`. Use it to pin a model or pass provider-specific settings. Merged with `embedder` when both are given.                    |
| `chunking_strategy` | `str`            | `"semantic"` | `"fixed"` / `"semantic"` / `"sentence"` / `"paragraph"`                                                                                                                           |
| `retrieval_k`       | `int`            | `5`          | Number of chunks to retrieve per query                                                                                                                                            |
| `rerank`            | `bool`           | `False`      | Apply reranking to improve result order                                                                                                                                           |

### Basic Configuration

<Note>
  `path` is optional. Omit it and data is stored under an absolute per-project directory: `<project>/.praisonai/knowledge/chroma`. See [Knowledge Storage](/docs/features/knowledge-storage) for details.
</Note>

<Note>
  Set `vector_store.provider` explicitly and a fallback (e.g. to SQLite) is logged at `WARNING` level with `Retrieval quality may be reduced` so you notice it. Rely on the default (no explicit provider) and a fallback stays at `DEBUG`, because that path is expected ([PR #2982](https://github.com/MervinPraison/PraisonAI/pull/2982)).
</Note>

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
knowledge_config = {
    "vector_store": {
        "provider": "chroma",
        "config": {
            "collection_name": "knowledge_base",
            "path": ".praison",
            "distance_metric": "cosine"
        }
    },
    "embedder": {
        "provider": "openai",
        "config": {
            # Overridden by OPENAI_EMBEDDING_MODEL if set; see /docs/cli/knowledge-cli#environment-variables
            "model": "text-embedding-3-small"
        }
    }
}
```

### If your configured backend seems ignored

Configure a `mem0` or `mongodb` vector store on a release **before 2026-07-14** and find that searches feel like keyword matching? Your Knowledge instance may have been silently falling back to SQLite. This was a bug (fixed in [PR #2982](https://github.com/MervinPraison/PraisonAI/pull/2982)) where the adapter constructors rejected an internal `verbose` keyword and the resulting `TypeError` was swallowed.

Check which adapter you actually got:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Knowledge

kb = Knowledge(config={
    "vector_store": {
        "provider": "mem0",
        "config": {"collection_name": "my_docs"},
    }
})
print(type(kb.memory).__name__)   # 'Mem0Adapter' on the fix; 'SQLiteKnowledgeAdapter' means you're on a buggy release.
```

Upgrade to a release built from `main` after commit `69d7ecf` to fix it. An explicitly-configured backend that fails to initialise now emits a `WARNING` log — no more silent degradation:

```
WARNING praisonaiagents.knowledge.knowledge: Knowledge provider 'mem0' failed to initialize (<reason>); falling back to a different backend. Retrieval quality may be reduced.
```

The configured backend is honoured on releases built after commit `69d7ecf`; before that, the same code silently ran on SQLite.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, Knowledge

kb = Knowledge(config={
    "vector_store": {
        "provider": "mem0",
        "config": {"collection_name": "research_docs"},
    }
})

agent = Agent(
    name="Researcher",
    instructions="Answer research questions using the knowledge base.",
    knowledge=kb,
)

agent.start("What did we learn about solar output in 2024?")
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Init[🚀 Knowledge config] --> Explicit{🗂️ Provider<br/>explicitly set?}
    Explicit -->|Yes| TryProv[🧠 Try configured provider]
    Explicit -->|No| TryDefault[💤 Try default mem0]

    TryProv --> ProvOK{✅ Constructed?}
    TryDefault --> DefOK{✅ Constructed?}

    ProvOK -->|Yes| UseProv[🎯 Use configured provider]
    ProvOK -->|No| WarnFallback[⚠️ WARNING log:<br/>Retrieval quality may be reduced<br/>→ fall back to SQLite]

    DefOK -->|Yes| UseDefault[🎯 Use mem0 default]
    DefOK -->|No| DebugFallback[🔎 DEBUG log:<br/>expected fallback<br/>→ use SQLite]

    classDef start fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef success fill:#10B981,stroke:#7C90A0,color:#fff
    classDef warn fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff

    class Init start
    class Explicit,ProvOK,DefOK decision
    class UseProv,UseDefault success
    class WarnFallback warn
    class TryProv,TryDefault,DebugFallback process
```

### Advanced Configuration with Graph Store

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
knowledge_config = {
    "vector_store": {
        "provider": "chroma",
        "config": {
            "collection_name": "knowledge_base",
            "path": ".praison"
        }
    },
    "graph_store": {
        "provider": "neo4j",
        "config": {
            "url": "bolt://localhost:7687",
            "username": "neo4j",
            "password": "password"
        }
    },
    "llm": {
        "provider": "openai",
        "config": {
            "model": "gpt-4o-mini",
            "temperature": 0
        }
    },
    "reranker": {
        "enabled": True,
        "default_rerank": False
    }
}
```

## Choosing Sources and Chunking

Pick a source type, then a chunking strategy that matches your content.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph Sources
        S1[Files: PDF / DOCX / TXT]
        S2[Local HTML files]
        S3[In-memory strings]
    end
    subgraph Chunking
        C1[token: fixed size]
        C2[sentence: natural bounds]
        C3[semantic: topic bounds]
    end
    S1 --> C1
    S2 --> C2
    S3 --> C3

    classDef source fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef strat fill:#10B981,stroke:#7C90A0,color:#fff
    class S1,S2,S3 source
    class C1,C2,C3 strat
```

The chosen chunker applies to every text source uniformly — no extension bypasses it (since PraisonAI PR [#4831](https://github.com/MervinPraison/PraisonAI/pull/4831)).

## Chunking Strategies

<CodeGroup>
  ```python Token-based Chunking theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  kb = Knowledge({
      "chunker": {
          "name": "token",
          "chunk_size": 500,
          "chunk_overlap": 50
      }
  })
  ```

  Best for: Consistent chunk sizes, token-limited models

  ```python Sentence-based Chunking theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  kb = Knowledge({
      "chunker": {
          "name": "sentence",
          "chunk_size": 10,  # sentences per chunk
          "min_chunk_size": 3
      }
  })
  ```

  Best for: Natural text boundaries, Q\&A systems

  ```python Semantic Chunking theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  kb = Knowledge({
      "chunker": {
          "name": "semantic",
          "threshold": 0.7,
          "min_chunk_size": 100
      }
  })
  ```

  Best for: Topic-based segmentation, research papers

  ```python SDPM Chunking theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  kb = Knowledge({
      "chunker": {
          "name": "sdpm",
          "max_chunk_size": 1000
      }
  })
  ```

  Best for: Document structure preservation
</CodeGroup>

## Document Processing

### Supported File Types

<CardGroup cols={2}>
  <Card icon="file-pdf">
    * PDF (.pdf)
    * Word (.doc, .docx)
    * Text (.txt)
    * Markdown (.md)
    * RTF (.rtf)
  </Card>

  <Card icon="table">
    * Excel (.xls, .xlsx)
    * CSV (.csv)
    * JSON (.json)
    * XML (.xml)
  </Card>

  <Card icon="globe">
    * Images (OCR)
    * Local HTML files (.html, .htm)
    * Raw text strings
  </Card>

  <Card icon="code">
    Any UTF-8 text file — source code (`.py`, `.js`, `.ts`, `.go`, `.rs`, `.java`), config files (`.yaml`, `.toml`, `.sh`, `.ipynb`, `.rst`), and suffix-less files like `Dockerfile` or `.gitignore`. Content is read and chunked; metadata records the real extension.
  </Card>
</CardGroup>

<Note>
  All supported UTF-8 text extensions — `.txt`, `.md`, `.csv`, `.json`, `.xml`, `.html`, `.htm` — are chunked with the configured `chunker` (respecting `chunk_size` and `chunk_overlap`), and the original case is preserved. Behaviour matches every other file type (PDF/DOCX/media via MarkItDown, source files via the unlisted-extension branch). Since PraisonAI PR [#4831](https://github.com/MervinPraison/PraisonAI/pull/4831).
</Note>

<Note>
  Empty files and non-UTF-8 (binary) files raise `ValueError` instead of being silently indexed. Since PraisonAI PR [#4788](https://github.com/MervinPraison/PraisonAI/pull/4788).
</Note>

### Indexing a Codebase

Point `knowledge=[...]` at source files, configs, and suffix-less files — each UTF-8 text file is read and chunked.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Code Reviewer",
    instructions="Answer questions about the codebase.",
    knowledge=["src/auth.py", "src/config.yaml", "Dockerfile"],
)

agent.start("How does authentication work?")
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Src[📄 Source files] --> Chunk[✂️ Chunk]
    Chunk --> Embed[🔤 Embed]
    Embed --> Store[(🗃️ Vector store)]
    Store --> Answer[✅ Grounded answer]

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Src input
    class Chunk,Embed,Store process
    class Answer output
```

### Processing Options

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Add with metadata
kb.add(
    "research.pdf",
    user_id="user123",
    metadata={
        "category": "AI Research",
        "year": 2024,
        "author": "Dr. Smith"
    }
)

# Batch processing
documents = ["doc1.pdf", "doc2.txt", "doc3.md"]
for doc in documents:
    kb.add(doc, user_id="user123")

```

<Warning>
  **Arbitrary web page URLs are not ingested.** `Knowledge.add(url)` raises
  `NotImplementedError("URL processing not yet implemented")` and
  `Agent(knowledge=[url])` warns and skips for ordinary `http(s)://` pages.
  Download the page first, then add the local path:

  ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import urllib.request

  urllib.request.urlretrieve("https://arxiv.org/pdf/2301.00000.pdf", "paper.pdf")
  kb.add("paper.pdf", user_id="user123")
  ```
</Warning>

<Note>
  **Cloud storage URIs are downloaded automatically.** Pass `s3://`, `gs://`, `az://`, or an Azure Blob HTTPS URL directly — PraisonAI fetches and indexes it for you:

  ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  from praisonaiagents import Agent

  agent = Agent(
      name="Handbook Assistant",
      instructions="Answer from the handbook.",
      knowledge=["s3://my-bucket/handbook.pdf"],
  )
  agent.start("What's the leave policy?")
  ```

  See [Cloud Sources](/docs/features/knowledge-cloud-sources) for providers, credentials, and error handling.
</Note>

## Handling indexing failures

Indexing errors are surfaced, not swallowed. When the embedding call fails, the CLI exits non-zero and the Python API raises.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Indexing outcome"
        Src[📄 Source] --> Embed[🔤 Embedding call]
        Embed -->|ok| Store[(🗃️ Vector store)]
        Embed -->|error| Warn[⚠️ Log warning]
        Warn --> Result[❌ AddResult success=False]
        Result --> Raise[🚨 RuntimeError]
        Store --> Ok[✅ AddResult success=True]
    end

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef warn fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef fail fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff

    class Src input
    class Embed,Store process
    class Warn warn
    class Result,Raise fail
    class Ok ok
```

<Warning>
  `Knowledge.add(source)` from Python raises `RuntimeError` on the first source whose embedding fails. Wrap batch calls in `try` / `except` to keep going.
</Warning>

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Knowledge

kb = Knowledge()
try:
    kb.add("research_paper.pdf")
except RuntimeError as e:
    # message includes the embedding model and the underlying error, e.g.
    # "Failed to generate embedding (model=text-embedding-3-small): 403 model_not_found"
    print(f"Indexing failed: {e}")
```

The lower-level `ChromaKnowledgeAdapter.add()` returns an `AddResult` instead of raising:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
result = adapter.add("Paris is the capital of France.")
if not result.success:
    print(result.message)   # "Failed to generate embedding (model=…): …"
```

Search degrades gracefully — a failed embedding is logged at `WARNING` and the call returns an empty `SearchResult` rather than raising, so an embedding outage cannot bring down the calling agent.

## Search Features

### Basic Search

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Simple search
results = kb.search("artificial intelligence", limit=5)

# User-scoped search
results = kb.search(
    query="machine learning",
    user_id="user123",
    limit=10
)
```

### Advanced Search Options

<CodeGroup>
  ```python With Reranking theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  # Enable Mem0 reranking for better relevance
  results = kb.search(
      query="neural networks",
      user_id="user123",
      rerank=True,
      top_k=20  # Retrieve more before reranking
  )
  ```

  ```python Hybrid Search theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  # Combine keyword and semantic search
  results = kb.search(
      query="transformer architecture",
      user_id="user123",
      keyword_search=True,  # Better recall
      filter_memories=True  # Better precision
  )
  ```

  ```python Metadata Filtering theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  # Filter by metadata
  results = kb.search(
      query="implementation details",
      user_id="user123",
      filters={
          "category": "technical",
          "year": {"$gte": 2023}
      }
  )
  ```
</CodeGroup>

## Memory Integration

When used with agents, knowledge automatically integrates with memory:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
agent = Agent(
    name="Research Assistant",
    knowledge={
        "sources": ["papers/"],
        "vector_store": {
            "provider": "chroma",
            "config": {"collection_name": "research_docs"}
        }
    },
    memory=True  # Enable memory integration
)

# Knowledge is automatically searched during conversations
response = agent.start("What does the research say about transformers?")
```

## Graph Store Features

Graph stores add relationship extraction and connection queries on top of semantic search.

### Configuration

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
knowledge_config = {
    "graph_store": {
        "provider": "neo4j",  # or "memgraph"
        "config": {
            "url": "bolt://localhost:7687",
            "username": "neo4j",
            "password": "password"
        }
    },
    "extract_relationships": True
}
```

### Relationship Queries

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Find related concepts
results = kb.search_graph(
    "What concepts are related to transformers?",
    user_id="user123"
)

# Explore connections
results = kb.search_graph(
    "How is attention mechanism connected to BERT?",
    user_id="user123"
)
```

## Best Practices

<AccordionGroup>
  <Accordion title="Match chunk size to your query complexity">
    Use smaller chunks (100-200 tokens) for precise fact retrieval. Use larger chunks (500-1000 tokens) when answers need more context. Semantic chunking works best for research papers and long-form documents.
  </Accordion>

  <Accordion title="Separate collections by domain">
    Use a different `collection_name` per knowledge domain (e.g., `product_docs`, `legal_contracts`). This prevents cross-contamination and allows targeted filtering by domain.
  </Accordion>

  <Accordion title="Use metadata for filtering">
    Add `metadata` when indexing documents to enable `filters=` in searches. Filter by `category`, `year`, or `author` to narrow results without changing query text.
  </Accordion>

  <Accordion title="Enable reranking for higher precision">
    Set `rerank=True` in `kb.search()` when you need top-quality results. Reranking retrieves more candidates then scores them for relevance — best for Q\&A and research assistants.
  </Accordion>
</AccordionGroup>

## Example: Research Assistant

<CodeGroup>
  ```python Complete Example theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  from praisonaiagents import Agent
  from praisonaiagents import Knowledge

  # Configure knowledge base
  knowledge_config = {
      "vector_store": {
          "provider": "chroma",
          "config": {
              "collection_name": "research_papers",
              "path": ".praison"
          }
      },
      "chunker": {
          "name": "semantic",
          "threshold": 0.7
      },
      "embedder": {
          "provider": "openai",
          "config": {
              "model": "text-embedding-3-small"
          }
      },
      "reranker": {
          "enabled": True
      }
  }

  # Create research assistant
  research_agent = Agent(
      name="Research Assistant",
      instructions="""You are an expert research assistant.
      Use the knowledge base to provide accurate, well-sourced answers.
      Always cite the specific documents you reference.""",
      knowledge={
          "sources": ["research_papers"],
          **knowledge_config
      }
  )

  # Use the assistant
  response = research_agent.start(
      "What are the main approaches to AI alignment?"
  )

  # Direct knowledge queries
  kb = research_agent.knowledge
  papers = kb.search("alignment techniques", limit=5)
  for paper in papers:
      print(f"- {paper['text'][:100]}...")
      print(f"  Source: {paper.get('metadata', {}).get('source')}")
  ```
</CodeGroup>

## Troubleshooting

| Symptom                                                                                                                                                                      | Likely cause                                                                                                                                                                           | Fix                                                                                                                                                                                       |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `praisonai knowledge index` exits `1` with `no chunks stored`                                                                                                                | Directory contained no supported file types, or every file failed to extract.                                                                                                          | Check the file extensions and re-run with `--verbose` to see per-file diagnostics.                                                                                                        |
| `AddResult.message: Failed to generate embedding (model=…): 401`                                                                                                             | Missing or invalid `OPENAI_API_KEY`.                                                                                                                                                   | Export a valid key: `export OPENAI_API_KEY=sk-…`.                                                                                                                                         |
| `AddResult.message: Failed to generate embedding (model=…): 404 model_not_found`                                                                                             | `OPENAI_EMBEDDING_MODEL` is set to a name the provider doesn't recognise.                                                                                                              | Unset it (default is `text-embedding-3-small`) or set it to a supported model like `text-embedding-3-large`.                                                                              |
| `search()` returns empty results for content you just indexed                                                                                                                | Embedding failure at index time was masked by an older build.                                                                                                                          | Upgrade to the latest release (PR [#2823](https://github.com/MervinPraison/PraisonAI/pull/2823)); indexing now exits non-zero if nothing was stored.                                      |
| Search is slower or more expensive than expected                                                                                                                             | `OPENAI_EMBEDDING_MODEL=text-embedding-3-large` is set.                                                                                                                                | Switch back to `text-embedding-3-small` for latency-sensitive apps, or budget for the \~6.5× cost.                                                                                        |
| MongoDB search returns another tenant's documents                                                                                                                            | On releases before PR [#3810](https://github.com/MervinPraison/PraisonAI/pull/3810), the MongoDB adapter silently ignored `user_id` / `agent_id` / `run_id`.                           | Upgrade to a release built after commit `6b6707c1`. The adapter now honors these scopes on both `add()` and `search()` for tenant isolation.                                              |
| `RuntimeError: Chroma persist failed at '<path>' (PanicException: ...)` on `Agent.start(...)` or `Knowledge.add(...)`                                                        | The on-disk sqlite Chroma store at `<path>` is corrupt, locked by another process, or was written by an incompatible Chroma version.                                                   | Delete `<path>` and re-index, or point `knowledge={"vector_store": {"config": {"path": "/a/fresh/dir"}}}` at a fresh directory.                                                           |
| `RuntimeError: Knowledge indexing backend crashed on <file>` while indexing a directory                                                                                      | The vector-store backend panicked on that file (typically a Chroma rust-binding panic on a corrupt store).                                                                             | Delete the persist directory or move `<file>` aside and re-run.                                                                                                                           |
| Two unrelated projects appear to share the same Knowledge base                                                                                                               | You are on a pre-#4422 release where the default `path` was the cwd-relative string `"knowledge_db"`.                                                                                  | Upgrade to the release built from PraisonAI PR [#4422](https://github.com/MervinPraison/PraisonAI/pull/4422); defaults are now absolute (`<project>/.praisonai/knowledge/chroma`).        |
| Windows: `Agent(knowledge=["docs/"])` SIGSEGVs or hangs                                                                                                                      | Pre-#4422 issue [#4376](https://github.com/MervinPraison/PraisonAI/issues/4376): pyo3 `PanicException` (a `BaseException`) unwound the process instead of surfacing as a Python error. | Upgrade; panics are now caught and re-raised as `RuntimeError` with an actionable message.                                                                                                |
| `search()` returns nothing after indexing `.py` / `.js` / other source files, or a code directory                                                                            | Pre-#4788 release: files with unlisted extensions had their **path** stored as content, not their contents.                                                                            | Upgrade to a release built from PraisonAI PR [#4788](https://github.com/MervinPraison/PraisonAI/pull/4788); source files are now read and chunked.                                        |
| `ValueError: Empty text file` or `ValueError: Cannot read <path> as UTF-8 text` when indexing a directory                                                                    | The file is empty, or is binary (image bytes with a `.txt` extension, encoded blob, etc.).                                                                                             | Remove or skip the file. Binary media (`.png`, `.mp3`, etc.) go through the media branch, not the text branch.                                                                            |
| After indexing a `.md`/`.txt`/`.csv`/`.json`/`.xml`/`.html` file, `search()` returns fewer, coarser, or lowercased results than the same content in a `.pdf` or `.rst` file. | Pre-#4831 release: the text branch stored the whole file as one memory and lowercased it, so `chunk_size` / `chunk_overlap` were ignored on these extensions.                          | Upgrade to a release built from PraisonAI PR [#4831](https://github.com/MervinPraison/PraisonAI/pull/4831). Re-index the affected files so they are stored as chunks with case preserved. |
| `chunk_size` set in the `chunker` config seems to have no effect on `.md`/`.txt` indexing.                                                                                   | Same root cause as above — the text branch bypassed the chunker on pre-#4831 releases.                                                                                                 | Upgrade to a build that includes PR [#4831](https://github.com/MervinPraison/PraisonAI/pull/4831); the same config now applies uniformly to every text branch.                            |

## Async safety

Knowledge search runs on a worker thread when called from an async agent (`agent.astart(...)` or `agent.astream(...)`). It never blocks the event loop, so multiple async agents — or an `asyncio.gather(...)` of tasks — that all query the same knowledge base progress in parallel instead of serialising on the slowest lookup.

No user-facing change: the async path automatically dispatches the underlying (synchronous) embedding + vector-store call via `asyncio.to_thread`.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import asyncio
from praisonaiagents import Agent

agent = Agent(
    name="Research Assistant",
    instructions="Answer questions using the knowledge base.",
    knowledge=["research_paper.pdf"],
)

async def main():
    # Both lookups offload to worker threads — the loop stays responsive.
    await asyncio.gather(
        agent.astart("What are the key findings?"),
        agent.astart("Summarise the methodology"),
    )

asyncio.run(main())
```

See [Async Safety](/docs/features/async-safety) for the full set of async guarantees.

## Related

<CardGroup cols={2}>
  <Card title="RAG" icon="database" href="/docs/features/rag">
    Build retrieval-augmented generation pipelines
  </Card>

  <Card title="Vector Store" icon="database" href="/docs/features/vector-store">
    Store and query embeddings with a pluggable, namespace-aware backend
  </Card>

  <Card title="Async Safety" icon="shield-check" href="/docs/features/async-safety">
    How knowledge search, memory writes, and the in-memory adapter behave under concurrent tasks
  </Card>

  <Card title="Cloud Sources" icon="cloud" href="/docs/features/knowledge-cloud-sources">
    Load knowledge from S3, Google Cloud Storage, and Azure Blob buckets
  </Card>
</CardGroup>
