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
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.

Diagram

๐Ÿ“„ Sources

โœ‚๏ธ Chunk + Embed

๐Ÿ—ƒ๏ธ Vector Store

โœ… Grounded Answer

Key Features

Quick Start

  1. Level 1 โ€” List of sources (simplest)

    Pass a list of files, directories, or inline text and the agent answers from them.

    python
    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?")
  2. Level 2 โ€” Dict (inline config)

    Use a dict to pick a vector store while still passing sources inline.

    python
    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?")
  3. Level 3 โ€” Config class (full control)

    Use KnowledgeConfig for typed control over chunking, retrieval, and reranking.

    python
    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?")

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.

Shorthand

Pass the provider name to use its default embedding model.

python
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?")

Full config

Use embedder_config to pin a model or pass provider-specific options.

python
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?")

Local Ollama

Run embeddings locally with Ollama โ€” no API key needed.

python
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?")

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

How It Works

Diagram
LLMVectorStoreKnowledgeAgentUserLLMVectorStoreKnowledgeAgentUserQuestion about documentssearch(query)Embed query + semantic searchTop-k chunksRetrieved contextPrompt + contextGrounded answerResponse
PhaseWhat happens
1. AddDocuments are chunked, embedded, and stored in the vector store via knowledge.add()
2. Searchknowledge.search(query) embeds the query and returns top-k similar chunks
3. RetrieveAgent injects the chunks as context before calling the LLM
4. GenerateLLM answers using the retrieved knowledge; responses are grounded in your data

Configuration Options

KnowledgeConfig SDK Reference

Full parameter reference for KnowledgeConfig

The most common options at a glance:

OptionTypeDefaultDescription
sourceslist[str][]Files, directories, raw text, or cloud URIs (s3://, gs://, az://, Azure blob HTTPS). Arbitrary web URLs are not ingested.
embedderstr"openai"Provider shorthand. Any value other than "openai" overrides the default (e.g. "gemini", "cohere", "ollama", "huggingface", "voyage"). "openai" means “no override”.
embedder_configDict[str, Any]NoneFull embedder dict {"provider": ..., "config": {...}}. Use it to pin a model or pass provider-specific settings. Merged with embedder when both are given.
chunking_strategystr"semantic""fixed" / "semantic" / "sentence" / "paragraph"
retrieval_kint5Number of chunks to retrieve per query
rerankboolFalseApply reranking to improve result order

Basic Configuration

python
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) where the adapter constructors rejected an internal verbose keyword and the resulting TypeError was swallowed.

Check which adapter you actually got:

python
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
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?")
Diagram

Yes

No

Yes

No

Yes

No

๐Ÿš€ Knowledge config

๐Ÿ—‚๏ธ Provider
explicitly set?

๐Ÿง  Try configured provider

๐Ÿ’ค Try default mem0

โœ… Constructed?

โœ… Constructed?

๐ŸŽฏ Use configured provider

โš ๏ธ WARNING log:
Retrieval quality may be reduced
โ†’ fall back to SQLite

๐ŸŽฏ Use mem0 default

๐Ÿ”Ž DEBUG log:
expected fallback
โ†’ use SQLite

Advanced Configuration with Graph Store

python
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.

Diagram

Chunking

Sources

Files: PDF / DOCX / TXT

Local HTML files

In-memory strings

token: fixed size

sentence: natural bounds

semantic: topic bounds

The chosen chunker applies to every text source uniformly โ€” no extension bypasses it (since PraisonAI PR #4831).

Chunking Strategies

Token-based Chunking
kb = Knowledge({
    "chunker": {
        "name": "token",
        "chunk_size": 500,
        "chunk_overlap": 50
    }
})

Best for: Consistent chunk sizes, token-limited models

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

Best for: Natural text boundaries, Q&A systems

Semantic Chunking
kb = Knowledge({
    "chunker": {
        "name": "semantic",
        "threshold": 0.7,
        "min_chunk_size": 100
    }
})

Best for: Topic-based segmentation, research papers

SDPM Chunking
kb = Knowledge({
    "chunker": {
        "name": "sdpm",
        "max_chunk_size": 1000
    }
})

Best for: Document structure preservation

Document Processing

Supported File Types

Indexing a Codebase

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

python
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?")
Diagram

๐Ÿ“„ Source files

โœ‚๏ธ Chunk

๐Ÿ”ค Embed

๐Ÿ—ƒ๏ธ Vector store

โœ… Grounded answer

Processing Options

python
# 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")

Handling indexing failures

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

Diagram

Indexing outcome

ok

error

๐Ÿ“„ Source

๐Ÿ”ค Embedding call

๐Ÿ—ƒ๏ธ Vector store

โš ๏ธ Log warning

โŒ AddResult success=False

๐Ÿšจ RuntimeError

โœ… AddResult success=True

python
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
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
# 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

With Reranking
# Enable Mem0 reranking for better relevance
results = kb.search(
    query="neural networks",
    user_id="user123",
    rerank=True,
    top_k=20  # Retrieve more before reranking
)
Hybrid Search
# Combine keyword and semantic search
results = kb.search(
    query="transformer architecture",
    user_id="user123",
    keyword_search=True,  # Better recall
    filter_memories=True  # Better precision
)
Metadata Filtering
# Filter by metadata
results = kb.search(
    query="implementation details",
    user_id="user123",
    filters={
        "category": "technical",
        "year": {"$gte": 2023}
    }
)

Memory Integration

When used with agents, knowledge automatically integrates with memory:

python
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
knowledge_config = {
    "graph_store": {
        "provider": "neo4j",  # or "memgraph"
        "config": {
            "url": "bolt://localhost:7687",
            "username": "neo4j",
            "password": "password"
        }
    },
    "extract_relationships": True
}

Relationship Queries

python
# 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

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.

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.

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.

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.

Example: Research Assistant

Complete Example
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')}")

Troubleshooting

SymptomLikely causeFix
praisonai knowledge index exits 1 with no chunks storedDirectory 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=โ€ฆ): 401Missing or invalid OPENAI_API_KEY.Export a valid key: export OPENAI_API_KEY=sk-โ€ฆ.
AddResult.message: Failed to generate embedding (model=โ€ฆ): 404 model_not_foundOPENAI_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 indexedEmbedding failure at index time was masked by an older build.Upgrade to the latest release (PR #2823); indexing now exits non-zero if nothing was stored.
Search is slower or more expensive than expectedOPENAI_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 documentsOn releases before PR #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 directoryThe 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 baseYou 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; defaults are now absolute (<project>/.praisonai/knowledge/chroma).
Windows: Agent(knowledge=["docs/"]) SIGSEGVs or hangsPre-#4422 issue #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 directoryPre-#4788 release: files with unlisted extensions had their path stored as content, not their contents.Upgrade to a release built from PraisonAI PR #4788; source files are now read and chunked.
ValueError: Empty text file or ValueError: Cannot read <path> as UTF-8 text when indexing a directoryThe 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. 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; the same config now applies uniformly to every text branch.
ImportError: chonkie package not found. Please install it using: pip install 'praisonaiagents[knowledge]' when calling agent.start(...) with chunking_strategy="semantic" (the default), "sdpm", or "late", or with any string embedding_modelThe chonkie package is not installed. The default chunker is semantic, so this fires on the first knowledge lookup even if you never set chunking_strategy explicitly. Since PraisonAI PR #5105 the error surfaces with an actionable hint instead of a raw ModuleNotFoundError.pip install 'praisonaiagents[knowledge]' (quotes required in zsh). Or switch to a chunker that does not need chonkie embeddings by passing KnowledgeConfig(chunking_strategy="sentence") or "paragraph".
ImportError mentioning chonkie.embeddings but without the pip install hintchonkie is installed but its embeddings submodule failed to import (typically a broken or incompatible transitive dependency such as sentence-transformers, torch, or transformers). Since PraisonAI PR #5105 the original error is preserved so the real cause is not masked behind misleading install advice.Read the underlying error and reinstall or upgrade the named package. pip install --upgrade sentence-transformers fixes the most common case.

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
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 for the full set of async guarantees.

Related