Search knowledge collections
Your organization can hold knowledge collections: PDF, Word, slide, and Markdown files that Urai indexes for search. You upload them in the app under Knowledge, you push them with the Knowledge API, and you group them into collections.
Two other pages cover the same documents from another side. Use the Knowledge API to search them from your own code and to get the passages back. Use the extraction API to read the text of one file without keeping it.
Two built-in tools read that index:
search_documentsreturns the passages that match a query.read_documentreturns one document in full.
You name them in tools[] like any other tool. Urai runs the search before the
model writes the answer, so one request gives you a grounded reply.
Make a request
Section titled “Make a request”curl https://chat.app.urai.dev/api/openai/v1/chat/completions \ -H "Authorization: Bearer $URAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-haiku-4-5", "messages": [ { "role": "user", "content": "What is our refund window for annual plans?" } ], "tools": [ { "type": "function", "function": { "name": "search_documents" } }, { "type": "function", "function": { "name": "read_document" } } ] }'Name both tools together. The two work as a pair: search finds the document, and read returns all of it. You can name only one if you want only that behaviour.
If your organization has no collections, a request that names either tool fails
with 400 and the code tool_not_configured. Upload a document first.
Limit the search to some collections
Section titled “Limit the search to some collections”Without a limit, the tools search every collection in the API key’s organization. That is the correct default for most applications.
To narrow the scope, send the top-level knowledge field:
{ "model": "anthropic/claude-haiku-4-5", "messages": [{ "role": "user", "content": "What is our refund window?" }], "tools": [{ "type": "function", "function": { "name": "search_documents" } }], "knowledge": { "collections": ["billing-policies", "support-playbooks"] }}Four rules apply:
- The limit is absolute. The model can narrow the scope further with its own
collectionsargument. It cannot reach a collection you left out. - A name matches the collection slug or the display name. Case does not matter.
- Find the slug in the app URL. The page
/knowledge/billing-policieshas the slugbilling-policies. - An unknown name fails the request with
400and the codeunknown_collection. The message lists the valid slugs. Urai does not fall back to a search of everything.
Use this field when one API key serves several products, and each product must see only its own documents.
Send the knowledge field from an SDK
Section titled “Send the knowledge field from an SDK”knowledge is a top-level field in the request body. It is not a key inside
tools[].function, because a typed OpenAI SDK builds the function object from a
fixed shape and drops any extra key.
Every OpenAI client can add a root-level field.
response = client.chat.completions.create( model="anthropic/claude-haiku-4-5", messages=[{"role": "user", "content": "What is our refund window?"}], tools=[{"type": "function", "function": {"name": "search_documents"}}], extra_body={"knowledge": {"collections": ["billing-policies"]}},)const response = await client.chat.completions.create({ model: "anthropic/claude-haiku-4-5", messages: [{ role: "user", content: "What is our refund window?" }], tools: [{ type: "function", function: { name: "search_documents" } }], // @ts-expect-error The Urai extension is not in the OpenAI types. knowledge: { collections: ["billing-policies"] },});What the model searches with
Section titled “What the model searches with”The model chooses the arguments. You do not send them.
| Argument | Effect |
|---|---|
query |
Required. The question or the keywords to look for. |
collections |
Narrows the search to these collections, inside the limit you set. |
documents |
Restricts the search to named documents from an earlier result. |
limit |
Number of passages to return. The default is 8 and the maximum is 25. |
What the model reads back
Section titled “What the model reads back”Each result carries the passage and enough information to cite it.
{ "query": "refund window annual plans", "results": [ { "document_id": "3f2a…", "document_name": "Billing Policy 2026.pdf", "page": 4, "reference": "p. 4", "collection_id": "9b1c…", "collection_name": "Billing policies", "seq": 12, "score": 0.81, "content": "Annual plans may be refunded in full within 30 days of renewal…" } ]}referenceis one string the model can quote, such asp. 4,Billing > Refunds, orexcerpt 13.pageandsectionappear only when the file format has them. A Word file has no pages.- The tool instructs the model to name the source document in its answer, so citations appear in the answer text. The response body has no separate citation field.
When nothing matches, the tool returns an empty results array and a note. The
model then says that the knowledge base does not cover the question.
Read a whole document
Section titled “Read a whole document”Search returns passages. Some questions need the whole file, such as the total
of an invoice or every row of a table. The model calls read_document for that.
| Argument | Effect |
|---|---|
document |
Required. The document_name from a search result. The file extension is optional. |
from_seq |
Resume position. Omit it to start at the beginning. |
A long document returns in windows of about 40,000 characters. When a reply
carries next_seq, the model calls again with from_seq set to that value.
{ "document_id": "3f2a…", "document_name": "Billing Policy 2026.pdf", "collection_name": "Billing policies", "page_count": 18, "chunk_count": 96, "from_seq": 0, "next_seq": 41, "content": "[p. 1] Billing Policy…"}read_document reads the same collections as search_documents. Your
knowledge.collections limit applies to both.
Combine knowledge with your own tools
Section titled “Combine knowledge with your own tools”Name the built-in tools and your UraiJS tools in the same request. The model picks between them.
{ "model": "anthropic/claude-haiku-4-5", "messages": [ { "role": "user", "content": "Is account acct_8812 inside the refund window?" } ], "tools": [ { "type": "function", "function": { "name": "search_documents" } }, { "type": "function", "function": { "name": "orders" } } ], "knowledge": { "collections": ["billing-policies"] }, "metadata": { "account_id": "acct_8812" }}The model reads the policy from the collection, reads the account from your
tool, and answers with both. See
Call your UraiJS tools for how metadata reaches the
tool.