# Knowledge bases Create knowledge bases and upload documents from the SDK, the API, or MCP — then ground your assistants on them. Source: https://docs.polimorf.app/docs/knowledge 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](/docs/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. ```ts 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: ```ts 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) ```ts 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](/docs/mcp). ## API Every SDK call maps to a plain HTTPS request under `/knowledge/*`. See the [Knowledge API reference](/docs/api/knowledge) for the endpoints, including the one-shot direct upload (`POST /knowledge/sources/:sourceId/documents/upload`).