Прескокни до содржината

Ingest a document and query it

Оваа содржина сè уште не е достапна на вашиот јазик.

End to end: a file on your disk becomes an answer with a citation pointing back at it. Everything here is curl, and the whole path takes about five minutes.

You need a key with the editor role — creating collections and uploading documents are writes. Reading and running agents need only a valid key, whatever its role.

Terminal window
export KOVAC_API_KEY="the-key-you-created"
export KOVAC_BASE="https://your-platform-host"
Terminal window
export COLLECTION_ID=$(curl -s -X POST "$KOVAC_BASE/api/manage/collections" \
-H "Authorization: Bearer $KOVAC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "handbook"}' | jq -r '.id')

Defaults are fine to start with. If you already know your documents are short and dense — reference tables, glossaries — a smaller chunk_size retrieves more precisely; see Collections & knowledge for the rest of the settings and why they are set once, at creation.

A 409 here means the name is taken in your tenant. Names are unique per tenant, not global.

Terminal window
curl -s -X POST "$KOVAC_BASE/api/manage/collections/$COLLECTION_ID/documents" \
-H "Authorization: Bearer $KOVAC_API_KEY" \
-F "file=@handbook.pdf" \
-F "source_uri=https://intranet.example.com/handbook.pdf"

Set source_uri to wherever the document really lives. It is what citations will name, so a real URL turns every citation into a link a reader can follow. Skip it and you get upload://handbook.pdf, which identifies the file but leads nowhere.

Accepted formats, by family:

Family Extensions
Documents .pdf .docx .pptx .html .htm .md .txt .rtf .odt .odp .epub
Spreadsheets and delimited text .csv .tsv .xlsx .xls .ods
Structured data .json .yaml .yml .xml
Email .eml .msg
Images (OCR) .png .jpg .jpeg .tif .tiff .bmp .gif .webp .jp2
Source files .py .js .ts .tsx .java .go .rs .rb .php .c .cpp .cs .kt .swift .scala .sh .sql and others

Anything else is rejected with 400 before any work starts. So is a file whose content contradicts its extension — a ZIP renamed to .pdf, an HTML error page saved as .docx. Text formats have no signature to check, so they are never rejected on that ground.

The response is 202 with a document_id and status: "parsing". If it comes back 200 with status: "done" instead, the collection already holds a document with identical content — that is deduplication, not an error.

Terminal window
export DOCUMENT_ID="the-document-id-from-step-2"
curl -s "$KOVAC_BASE/api/manage/collections/$COLLECTION_ID/documents/$DOCUMENT_ID" \
-H "Authorization: Bearer $KOVAC_API_KEY" | jq '{status, error}'

Poll until status is done. A scanned PDF that needs optical character recognition can take a few minutes; a Markdown file is near-instant. A scan in Cyrillic needs its language named at upload — see Scanned PDFs and images in Collections.

If status is error, the error field says why. The two common causes are a file that is not really the format its extension claims, and a PDF that is entirely images with no recoverable text.

A document that has not reached done is not searchable. An agent asked about it will correctly report finding nothing, which looks identical to the document not existing. Check the status before concluding retrieval is broken.

An agent can only search collections named in its own configuration. Open the agent on the Agents screen and add handbook to its knowledge attachments — that is Attach knowledge to an agent, which also covers what to do when you have no suitable agent yet.

Then take its assistant_id:

Terminal window
curl -s "$KOVAC_BASE/api/manage/agents" \
-H "Authorization: Bearer $KOVAC_API_KEY" | jq '.[] | {name, assistant_id}'
export ASSISTANT_ID="the-assistant-id"
Terminal window
export THREAD_ID=$(curl -s -X POST "$KOVAC_BASE/api/agent/threads" \
-H "Authorization: Bearer $KOVAC_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.thread_id')
curl -N -X POST "$KOVAC_BASE/api/agent/threads/$THREAD_ID/runs/stream" \
-H "Authorization: Bearer $KOVAC_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"assistant_id\": \"$ASSISTANT_ID\",
\"input\": {\"messages\": [{\"role\": \"user\", \"content\": \"What is the expense approval threshold?\"}]},
\"stream_mode\": [\"messages\", \"values\"]
}"

Ask something the document actually answers. A first test against a question the document does not cover proves nothing either way — an honest “I could not find that” is the correct response, and indistinguishable from a broken pipeline.

In the stream you should see a call to the search tool, its result — an array of passages, each carrying a ref alongside its content, source_uri, metadata and confidence — and then an answer citing them inline by that ref, as [c9f3a12b]. An answer never contains a file path or URL; see Verifiable citations.

Work down this list in order; each step rules out one cause.

Did the run finish at all? Check the stream’s end event for {"status": "success"}. A failed run still returns HTTP 200, so a client that only checks the status code sees a success with no answer in it. See Errors & limits.

Did the run search at all? Look for a search tool call in the stream. No call means the agent did not think it needed one, or has no search tool. Check that search is in the agent’s tools and that its trust tier permits it — a stripped tool produces an agent that says plainly it cannot search.

Did the search return nothing? An empty result array with a done document usually means the collection is not attached to this agent. The agent’s configured collections are a hard ceiling, so an agent with the wrong attachments searches the wrong place and finds nothing.

Did it return passages but not cite them? That is a model behaviour problem, not a retrieval one. Check the agent’s system prompt for instructions that conflict with citing.

Is the document really indexed? Re-check its status. Also re-read the passages the search did return: if they are from the right document but the wrong part of it, the question and the document’s wording may be too far apart, and a smaller chunk_size or a differently phrased question is the lever.

The agent’s Traces tab shows the same run with the retrieved passages before and after re-scoring, which is the fastest way to tell “retrieved nothing” from “retrieved the wrong thing” — see Read traces and evals.

Next: Author a plugin.