Knowledge Base
Self-contained document ingestion and retrieval for CUGA agents using Docling and local vector stores.
CUGA includes a built-in knowledge base powered by LangChain and local vector stores. Docling is integrated for document ingestion: it parses and normalizes PDFs, Office files, HTML, Markdown, images, and other supported types before chunking and embedding, so the pipeline stays self-contained with no external document services.
When enabled, the agent can search, ingest, and manage documents — and it automatically becomes aware of what documents are available.
Enabling Knowledge
Knowledge is enabled by default via settings.toml (see Storage for the embedding provider). To opt out for a specific agent in the SDK:
from cuga import CugaAgent
agent = CugaAgent(tools=[...], enable_knowledge=False)The SDK auto-injects knowledge tools and an awareness block into the agent prompt, so the agent knows what documents are available and how to search them.
Try the Demo
cuga start demo_knowledgeThis is the same surface as cuga start demo_crm but with the knowledge engine on — you can upload documents through the UI and query them.
Programmatic Access
from cuga import CugaAgent
import asyncio
agent = CugaAgent(enable_knowledge=True)
async def main():
# Ingest a document
await agent.knowledge.ingest("/path/to/quarterly_report.pdf")
# The agent now automatically knows about this document
result = await agent.invoke("What does the report say about Q4 revenue?")
print(result.answer)
# Direct search (skip the agent loop)
results = await agent.knowledge.search("Q4 revenue figures")
for r in results:
print(f"{r['filename']} (page {r['page']}): {r['text'][:100]}")
# List documents
docs = await agent.knowledge.list_documents()
# Clean up
await agent.aclose()
asyncio.run(main())Scopes
Documents can be agent-scoped (the default — permanent and shared across conversations) or session-scoped (tied to a single thread).
# Permanent, shared across conversations
await agent.knowledge.ingest("/path/to/file.pdf", scope="agent")
results = await agent.knowledge.search("query", scope="agent")thread_id = "user-session-123"
# Temporary, per-conversation
await agent.knowledge.ingest(
"/path/to/file.pdf",
scope="session",
thread_id=thread_id,
)
results = await agent.knowledge.search(
"query",
scope="session",
thread_id=thread_id,
)Supported Document Types
PDF, DOCX, XLSX, PPTX, HTML, Markdown, images, and more — anything Docling can parse.
Storage and Embeddings
The knowledge backend is selected by the global [storage].mode setting:
| Data | mode = "local" | mode = "prod" |
|---|---|---|
| Knowledge vectors | {knowledge.persist_dir}/knowledge_vectors.db (vec0 tables per collection) | storage.postgres_url (pgvector) |
| Knowledge metadata | {knowledge.persist_dir}/metadata.db | Postgres tables cuga_knowledge_meta_*. Uploaded files still live under persist_dir/files/. |
Embeddings are configured under [storage.embedding] and default to a local BAAI/bge-small-en-v1.5 model (no OpenAI key required). See Storage for full options.
The knowledge persistence directory defaults to <cwd>/.cuga/knowledge/ and can be overridden in knowledge_settings.toml.
Routing Knowledge Through CugaLite
The [advanced_features].force_lite_mode_apps list defaults to ["knowledge"], so knowledge queries always run through CugaLite's faster execution path regardless of lite_mode_tool_threshold. To change this, edit settings.toml:
[advanced_features]
force_lite_mode_apps = ["knowledge", "crm"] # add more apps as neededThe agent's awareness block is rebuilt as documents are ingested or removed, so newly added documents are usable immediately on the next invocation.
