Guides

Knowledge bases

Upload a PDF or point at a web page, and let agents answer from it during calls.

A knowledge base is a document the platform has split into chunks and indexed. During a call, what the caller says is used to find the closest chunks, and those are given to the LLM as context.

In the dashboard: Build → Knowledge Base, and the Knowledge tab of Agent Studio to attach one to an agent.

Create from a file

Upload a PDF as multipart form data. The limit is 25 MB, and the file is judged by its content, not its name.

bash
curl -X POST https://api.sevennadi.si/knowledgebase \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -F "file=@refund-policy.pdf" \
  -F "chunk_size=512" \
  -F "overlapping=128" \
  -F "similarity_top_k=15"
json
{"rag_id": "7d1c0a52-9a1e-4f0b-9c0e-2b6f5f0f7a11", "file_name": "refund-policy.pdf", "source_type": "pdf", "status": "processing"}

Create from a URL

bash
curl -X POST https://api.sevennadi.si/knowledgebase \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -F "url=https://www.example.test/help/refunds"

The page is fetched once, with a 20 second timeout and no redirects. HTML is reduced to its text; a URL that serves a PDF is read as a PDF. The URL may not resolve to a private network address: that is refused with 400 and Invalid url: ....

Send either file or url. Sending both or neither is Provide either file or url, not both.

Options

FieldDefaultRangeMeaning
chunk_size51232 to 4096Words per chunk
overlapping1280 to chunk_size - 1Words shared with the previous chunk
similarity_top_k151 to 50How many chunks a search may return
language_supportnonemultilingualStored with the knowledge base

Out-of-range values are refused with chunk_size 32-4096, similarity_top_k 1-50, overlapping 0..chunk_size-1.

Ingestion and status

Ingestion runs in the background. Poll the knowledge base until it leaves processing.

bash
curl https://api.sevennadi.si/knowledgebase/7d1c0a52-9a1e-4f0b-9c0e-2b6f5f0f7a11 \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"
json
{
  "rag_id": "7d1c0a52-9a1e-4f0b-9c0e-2b6f5f0f7a11",
  "file_name": "refund-policy.pdf",
  "vector_id": "b3a1f6de-55f1-4a52-8d3b-0c5a1d7e9f20",
  "status": "processed",
  "source_type": "pdf",
  "chunk_size": 512,
  "similarity_top_k": 15,
  "overlapping": 128,
  "created_at": "2026-10-13T09:12:44Z",
  "updated_at": "2026-10-13T09:12:45Z",
  "humanized_created_at": "just now"
}
StatusMeaning
processingWaiting for, or in, ingestion
processedReady to search
errorIngestion failed. The error field says why: an unreadable PDF, an unreachable URL, or no text found

GET /knowledgebase/all lists them. DELETE /knowledgebase/{rag_id} removes the knowledge base, its chunks and the stored PDF.

How it is indexed

  1. The text is extracted (PDF text layer, or the page's visible text).
  2. It is split into windows of chunk_size words, each overlapping the previous by overlapping words.
  3. Each chunk is embedded and stored in Postgres with the pgvector extension.
  4. A search embeds the question the same way and returns the nearest chunks by cosine distance.

Which embedder is used

  • If your account has an OpenAI-compatible key (provider key OPENAI_API_KEY, optionally OPENAI_BASE_URL), or the operator has set one for the platform, chunks are embedded with that provider's embedding model.
  • With no key, the platform uses an offline stand-in: a hashing embedder that counts words into fixed buckets. It needs no network and finds passages that share words with the question. It does not understand meaning, synonyms or other languages.

Each knowledge base remembers which embedder indexed it, and the list and detail responses name it in embedder: a value starting with hash is the keyword stand-in, openai:<model> is meaning-based search with that embedding model. The dashboard's Knowledge page shows which one each file uses. If it was indexed with a provider key and that key is later removed, it is skipped in searches until a key is back.

Attach it to an agent

Use the knowledge base's vector_id (not rag_id) in the agent's LLM config:

json
{
  "llm_agent": {
    "agent_type": "simple_llm_agent",
    "agent_flow_type": "streaming",
    "llm_config": {
      "provider": "openai", "model": "gpt-4o-mini",
      "vector_store": {"provider_config": {"vector_ids": ["b3a1f6de-55f1-4a52-8d3b-0c5a1d7e9f20"]}}
    }
  }
}

A single vector_id is accepted in place of the list. Graph agents put the same vector_store object inside a rag_config, on the graph or on one node.

What happens on a call

  • Test chat: POST /agent-chat/{agent_id} returns the retrieved chunks in passages, so you can see what the agent was given.
  • mock engine: the reply quotes the best-matching sentence, prefixed with From our documents:. Useful for checking retrieval without an LLM.
  • own engine: each caller turn is searched before the LLM request. The passages are added to that request's system prompt and are never written into the transcript. If the search takes longer than the engine's timeout, the turn is answered without them.

Only knowledge bases that are processed, not deleted, and owned by the agent's account are searched.

Limitations

  • Files must be PDFs with a text layer. Scanned pages without text yield no text found in the source. Other file types are refused.
  • A URL is fetched once. There is no crawling of linked pages and no scheduled refresh; create a new knowledge base to pick up changes.
  • Chunk options cannot be changed after creation.
  • Retrieval on the own engine searches the raw transcript of the turn. A follow-up such as "and how much is that?" searches for exactly those words.
  • Without a provider key, retrieval is word overlap only.