Knowledge bases
Create knowledge bases and upload documents from the SDK, the API, or MCP — then ground your assistants on them.
A knowledge base is a named collection of documents Polimorf ingests (chunks + embeds) so your assistants can ground their answers on your own content (retrieval-augmented generation). You can manage bases and upload documents from the dashboard, the SDK/API, or an MCP client — not just the dashboard.
What you can do programmatically
- Create, list, and delete knowledge bases.
- Upload documents (the SDK handles the multi-step upload for you), list them, and delete them.
- Search a base's content semantically (via MCP, or as part of an assistant's retrieval at runtime).
Scopes
The knowledge endpoints are not covered by the default key scope. Create an
API key with the knowledge scopes (in addition to runtime:execute if the same
key also runs assistants):
| Scope | Grants |
|---|---|
knowledge:read | List bases and documents. |
knowledge:write | Create/delete bases, upload and delete documents. |
See Authentication for how scopes are enforced. All knowledge calls act within the key's own workspace — you never pass an organization or workspace id.
Upload a document (SDK)
client.knowledge.uploadDocument runs the whole flow for you: it requests a
presigned URL, uploads the bytes straight to object storage, and confirms
completion (which starts ingestion). A string body is sent as UTF-8; binary
formats (PDF, DOCX) pass a Uint8Array. The content type is derived from the
filename extension when you omit it.
import { createClient } from '@polimorfapp/sdk';
const client = createClient(); // reads POLIMORF_API_KEY
// 1. Create a base (or reuse one from client.knowledge.listSources()).
const source = await client.knowledge.createSource({
name: 'Product FAQ',
description: 'Answers the support assistant can ground on.',
});
// 2. Upload a document — returns immediately with status PENDING.
const doc = await client.knowledge.uploadDocument({
sourceId: source.id,
filename: 'faq.md',
content: '# FAQ\n\n## Reset password\nOpen Settings → Security.\n',
});
// 3. Ingestion (chunk + embed) runs in the background. Poll until READY:
const docs = await client.knowledge.listDocuments(source.id);Uploading a binary file is the same call with Uint8Array content:
import { readFile } from 'node:fs/promises';
await client.knowledge.uploadDocument({
sourceId: source.id,
filename: 'handbook.pdf',
content: new Uint8Array(await readFile('./handbook.pdf')),
});Supported file types
pdf, txt, md/markdown, html/htm, csv, json, docx. A single
document is capped at 25 MiB, and each workspace has a total storage
allowance.
Ingestion status
uploadDocument resolves as soon as ingestion is enqueued; the returned
document is PENDING. It advances to PROCESSING, then READY (searchable) or
FAILED. Poll listDocuments to observe the transition.
Manage bases and documents (SDK)
await client.knowledge.listSources();
await client.knowledge.deleteSource(sourceId); // also deletes its documents
await client.knowledge.listDocuments(sourceId);
await client.knowledge.deleteDocument(sourceId, documentId);From MCP
An MCP client (e.g. Claude) can manage knowledge as you: create_knowledge_source,
add_knowledge_text (add a text/markdown document inline), list_knowledge_sources,
list_knowledge_documents, search_knowledge (semantic search over a base), and
the delete tools. Binary files go through the SDK/API upload. See
Connect via MCP.
API
Every SDK call maps to a plain HTTPS request under /knowledge/*. See the
Knowledge API reference for the endpoints, including the
one-shot direct upload (POST /knowledge/sources/:sourceId/documents/upload).