Concepts
Knowledge bases, ingestion states, chunks and search results.
Knowledge bases and files
Knowledge base IDs start with vs_. /knowledge/v1 and /openai/v1/vector_stores access the same data. The native API also provides restore, retry, segments, events and search explanations. Call from a server using an API Key.
Upload through the file service to obtain a file_id, then attach it to a store. The store file has the same ID as the source. Attaching an existing file returns its original record without reprocessing or applying new attributes or chunking. Batches behave the same way: a file already in the store is not ingested again when it appears in a batch, and the batch's attributes and chunking_strategy apply only to newly added files. To change attributes, use the update file endpoint (POST /vector_stores/{id}/files/{file_id}); to change chunking, remove the file and attach it again.
Ingestion states
| status | Meaning | Next step |
|---|---|---|
| in_progress | Content is being processed | Poll the file or use an SDK polling helper |
| completed | Content is searchable | Search |
| failed | Processing failed | Read last_error, correct the file or retry through the native API |
| cancelled | Processing was cancelled | Remove, then add again if needed |
Images (PNG, JPEG, GIF, WebP) are ingested as a model-generated description of the picture, not verbatim OCR: text in the image may be summarized or left out, and search matches that description. Images take longer to ingest than text; a single image took from a few seconds to tens of seconds in measurements, and longer when several files are ingested at once.
The native praxis.stage reports queued, parse, chunk, embed and index, then becomes null on completion. Store status reflects file processing and expiry. An empty store can be completed; that status does not guarantee it contains searchable content.
A batch attaches up to 500 files. Provide exactly one of file_ids or per-file files. With files, top-level attributes and chunking_strategy are ignored. Cancelling only affects batches in progress; cancelling a completed, failed or cancelled batch returns it unchanged.
Chunks
The default auto strategy resolves to 800 estimated tokens per chunk with 400 overlap tokens. Static chunks allow 100–4096 tokens; overlap must not exceed half the chunk size. Token counts are estimates, not the output of a specific model tokenizer.
The native API exposes chunk text, index, estimated tokens, page, UTF-16 start/end offsets and overlap counts. Page can be null. File content returns chunk texts, so account for overlap before joining them. usage_bytes is the original file size in bytes for indexed files and 0 for files not yet indexed; a store's usage_bytes is the sum of its files.
Search results
/openai/v1/vector_stores/{id}/search matches OpenAI: one result per file, with content listing that file's matching chunks from most to least relevant, score set to the best chunk, and max_num_results counting files (default 10, at most 50). Search on /knowledge/v1 returns one result per chunk, so a file can appear more than once, which suits building model context directly.
query accepts a string or an array; arrays are joined with newlines for one search. File attribute filters support eq, ne, gt, gte, lt, lte, in, nin and and/or combinations. Comparisons are type-strict: numeric 1 differs from string "1".
Search combines meaning and keywords with default weights of 0.7/0.3. The native API accepts ranking_options.hybrid_search weights and praxis.explain: true for explanations. Sending hybrid_search to the compatible endpoint returns 400. Only ranker default-2024-11-15 requests reranking; none, auto and omission keep the initial ranking. Reranking has not been measured separately.
Scores range from 0 to 1 and rank results within one search; they are not relevance probabilities and have no default floor. Unrelated content in the store is still returned, sometimes with scores close to relevant content (measured: 0.70 for the relevant file, 0.61–0.62 for unrelated ones). To filter, set ranking_options.score_threshold; results below it are not returned. OpenAI also applies no threshold by default. Start around 0.5, then check the scores of relevant and unrelated results on your own content and typical questions, and raise it until relevant results start to drop.
With rewrite_query: true the query is rewritten before retrieval; see Models below. has_more reports that more results were cut by max_num_results; search does not paginate and next_page is always null. Native content includes chunk_id, page and span; compatible responses omit them and praxis.
Models
Each knowledge base has three model roles. Set them in models when creating a store through the native API, and change them later with the update endpoint; unset roles use the defaults. Reading a store returns the effective model for each role in models.
| Role | Purpose | Default model |
|---|---|---|
embedding | Generates vectors for chunks and queries | bge-m3 |
rerank | Reorders results when ranking_options.ranker is default-2024-11-15 | bge-reranker-base |
query_rewrite | Rewrites queries when a search sets rewrite_query: true | qwen3.8-flash |
Once a store has files, embedding cannot change (existing vectors come from that model) and changing it returns 409; the other roles can change at any time. The model must exist in the model catalog and serve the role, and an embedding model must output 1024-dimension vectors; otherwise the request returns 400. Setting a role to null restores its default; models: null restores all defaults. The OpenAI-compatible API does not return models and rejects it with 400, as OpenAI does for unknown arguments, but its searches use the models configured on the store.
With rewrite_query: true, the query_rewrite model first turns the question into a concise search query (for example "How long until my refund arrives after a return?" → "refund arrival time"). Retrieval uses the rewrite and search_query returns it; an array query is rewritten item by item. Each rewrite is one small model call that is billed by model usage and adds about 1–2 seconds. If a rewrite fails, takes longer than 5 seconds or comes back empty, that query falls back to the original text and the search continues; it never fails the search. Omitted or false makes no model call.
Updates, expiry and deletion
Omitting name creates an empty name. Creation rejects null; updating name to null clears it. Metadata updates replace all metadata; null clears it. Description is accepted but discarded. Unknown write fields are ignored, so misspellings may not produce errors.
expires_after accepts only last_active_at with 1–365 days. Search and attachment refresh activity; null disables automatic expiry. A deleted store enters the deleting state: on /knowledge/v1 it reads back with status: deleting and a purge_at time, default lists hide it (list it with status=deleting), and search, updates and attachments return 409. Within 7 days you can restore it, or purge it immediately and permanently. /openai/v1/vector_stores matches OpenAI and returns 404 after deletion. Deleting a store never deletes the source files.