Knowledge Base
Verified against backend/internal/publicapi/builder_dto.go, knowledge_handler.go, and routes.go.
| Method | Path | Scope |
|---|---|---|
| GET | /agents/:id/knowledge | knowledge:read |
| POST | /agents/:id/knowledge | knowledge:write |
| POST | /agents/:id/knowledge/files | knowledge:write |
| PUT | /agents/:id/knowledge/stages | knowledge:write |
| POST | /agents/:id/knowledge/query | knowledge:read |
| DELETE | /agents/:id/knowledge/*title | knowledge:write |
There is no "knowledge base" object
This is worth stating plainly because every competitor's docs model a KB as a resource with an ID you create once and attach files to. This API doesn't, because the underlying table doesn't either: knowledge_base is a chunk table — one row per chunk, with a vector(1536) embedding inline. There's nothing to create ahead of time and no KB id to hold onto. Knowledge attaches directly to the agent.
Add a source
curl -X POST https://api.voicematrix.ai/api/v1/ext/agents/<agent-id>/knowledge \
-H "X-API-Key: vm_live_..." \
-H "Content-Type: application/json" \
-d '{
"source_type": "url",
"url": "https://docs.acme.com/pricing",
"title": "Pricing page"
}'| Field | Required | Notes |
|---|---|---|
source_type | yes | text or url |
content | required if source_type: text | |
url | required if source_type: url | Fetched server-side — SSRF-validated |
title | no, max 200 | Labels the source for listing/deletion |
{ "agent_id": "...", "title": "Pricing page", "chunks": 14 }Content safety on ingestion
Both text and url ingestion pass through the same multilingual (English + Hebrew) content guard used elsewhere in the platform, in enforcement mode — a flagged document is hard-blocked, not merely logged. This matters because ingested content goes straight into an agent's system context: on a Hebrew-first product, an injection attempt written in Hebrew has to be caught by the same gate as one written in English, not fall through to an English-only pattern list.
If ingestion returns 503
Embedding requires Azure OpenAI credentials to be configured. If they aren't, this endpoint answers 503 rather than accepting your document and silently storing it without an embedding — a document that "saved successfully" but is never retrievable would be a much worse failure mode.
Upload a file
curl -X POST https://api.voicematrix.ai/api/v1/ext/agents/<agent-id>/knowledge/files -H "X-API-Key: vm_live_..." -F "file=@מחירון.txt"201
{ "message": "File uploaded successfully", "filename": "מחירון.txt", "chunks": 1, "characters": 196, "warnings": null }This is the dashboard's Knowledge-tab upload: .pdf, .txt, .docx, .csv, .json or .md, up to 10 MB, within the organization's knowledge quota (5,000 chunks; over it, 429 RATE_LIMIT_EXCEEDED). The upload is synchronous: it answers once every chunk is embedded, so allow time for a large file.
- The file's name is its title: the document is listed, limited to stages and deleted by that name.
- A name that already exists for the agent is refused (
409 KNOWLEDGE_DOCUMENT_EXISTS), as is content that is already stored under another name. To update a document — a new price list, say — delete it, then upload the new version; nothing is embedded twice and the old text cannot stay live. - Text files must be UTF-8. A
.txtsaved as Windows-1255 (common for Hebrew on Windows) is refused with400 INVALID_FILE_ENCODING; save it again as UTF-8. Hebrew sources should be UTF-8.txt, not PDF: PDF text extraction reverses right-to-left text, and retrieval returns noise.warnings: ["hebrew_pdf_reversed"]flags a PDF where that happened. - PDF and DOCX are read in a separate, sandboxed process with a time and memory budget. A PDF over 1,000 pages, or a document over 25 MB of text, is refused with
400 FILE_TOO_LARGE; one that runs past the budget with400 DOCUMENT_TOO_COMPLEX. - With an
Idempotency-Keythe whole request must fit in 1 MiB.
Limit a source to some stages
For an agent with a stage graph (stageGraph in /config):
curl -X PUT https://api.voicematrix.ai/api/v1/ext/agents/<agent-id>/knowledge/stages -H "X-API-Key: vm_live_..." -H "Content-Type: application/json" -d '{"filename": "מחירון.txt", "stages": ["pricing", "close"]}'{ "filename": "מחירון.txt", "stages": ["pricing", "close"], "chunks": 1 }Stage ids must exist in the agent's stage graph (up to 12). An empty list makes the source visible in every stage. An unknown file name answers 404.
Search the knowledge
The Knowledge tab's test search: the chunks nearest to a question, as the agent retrieves them.
curl -X POST https://api.voicematrix.ai/api/v1/ext/agents/<agent-id>/knowledge/query -H "X-API-Key: vm_live_..." -H "Content-Type: application/json" -d '{"query": "כמה עולה חבילת עסקים?", "limit": 3}'{
"query": "כמה עולה חבילת עסקים?",
"count": 2,
"results": [
{ "filename": "מחירון.txt", "chunk": "1/1", "content": "מחירון רעים אהובים:
חבילת בסיס — 49 שקלים לחודש…
חבילת עסקים — 149 שקלים לחודש…" },
{ "filename": "מדיניות החזרות", "chunk": "1/1", "content": "ניתן לבטל חבילה בכל עת. ביטול בתוך 14 יום מזכה בהחזר מלא." }
]
}limit defaults to 5. There is no relevance cut-off: the nearest chunks always come back, so judge them by their content. For an agent with a stage graph, add "stage": "<stage id>" to search as that stage does; without it, only sources visible in every stage are searched.
List sources
GET /agents/:id/knowledge{
"data": [
{ "title": "מדיניות החזרות", "chunks": 1, "created_at": "2026-10-07T01:20:47.959107Z" },
{ "title": "מחירון.txt", "chunks": 1, "created_at": "2026-10-07T01:20:47.843958Z" }
],
"pagination": { "total": 2, "limit": 2, "offset": 0, "has_more": false }
}Uploaded files, text and URL sources are listed together, newest first.
Delete a source
DELETE /agents/:id/knowledge/*titleNote the *title wildcard, not :title. A source's title can legitimately contain a / — a url-sourced title derives from host/path (e.g. docs.acme.com/pricing), and a caller-supplied text title might too. A single-segment path parameter can't carry that; the wildcard captures the full remainder and the handler strips the leading slash. If you're constructing this URL yourself, don't URL-encode the slashes in the title — pass it through as the DELETE path directly.
Next
- Agents
- Voice & Agent Capabilities — how
search_knowledgeis used at call time