Skip to main content
POST /query searches your knowledge, your memories, or both, and returns ranked passages, called chunks, with their source details and the context graph around them. Your application puts them in the model’s prompt; the model writes the answer. The defaults work without tuning. In this guide:
  1. Run a query and read what comes back.
  2. Pick a recipe: starting parameters for the common cases.
  3. Tune the ranking: mode, alpha, recency_bias, and max_results.
  4. Choose what to search: several collections, knowledge and memories together, and metadata filters.
  5. Add relationships: the context graph, linked sources, and app-aware search.
  6. Query on behalf of a user: the acl field.
  7. Common mistakes.

1. Run a query

This request searches the acme_corp database for knowledge about rotating API keys. Every query starts from this request; later sections add fields. The body is JSON; ingestion is multipart.
Set up your SDK client before running the Python or TypeScript example.
The response is wrapped in the standard envelope, so read the result from data. Trimmed to the fields you use most, it looks like this:
The full response schema is on the Query API reference.

What each property means

What comes back

  • data.chunks: the matching passages, ranked by relevance, each with its chunk_content, source_title, relevancy_score, and metadata. Keep the order.
  • data.sources: one entry per source, with its id, title, and url for citations.
  • data.graph_context and data.additional_context: relationships and linked passages, covered in section 5.
Pass the whole result to build_string (Python) or buildString (TypeScript) for a prompt-ready string. See How to Use API Results for more. New context is searchable once its indexing status reaches graph_creation.

2. Pick a recipe

Start from the row that matches your goal. Leave everything else at its default. query_by picks how the text is matched: "hybrid" (the default) matches by meaning and by keyword together, and "text" matches keywords only. mode picks how much work the query does. Section 3 explains mode; Semantic Search covers query_by.

3. Tune the ranking

Most of the time the defaults are right. When they are not, start here:
  • mode: "fast" is one retrieval pass, for chat and autocomplete. "thinking" expands the query, reranks, and pulls in linked sources, for answers where quality matters more than latency. "auto", the default, scores each query and routes it to one of the two, choosing thinking when unsure; the response does not say which it chose. Applies to query_by: "hybrid" only.
  • alpha: the balance between meaning (1.0) and keywords (0.0) in a hybrid query. Default 0.8, which "auto" also resolves to. Lower it toward 0.3 to 0.5 for error codes, SKUs, and product names; raise it toward 0.9 for conceptual questions. Semantic Search has the full table.
  • recency_bias: how much newer context is favored, from 0.0 to 1.0. Default 0.4, a mild tilt that only reorders close results. Send 0 for policies and other context that rarely changes, and 0.6 to 0.8 for changelogs and status updates.
  • max_results: drop to 5 for tight context windows; raise to 20 when you rerank downstream.
  • additional_context: a short factual hint, such as "user is on the billing page", that sharpens retrieval. It is not a filter.
In production:
  • Timeouts: 3 to 5 s for thinking, 500 ms or less for fast. Budget "auto" like thinking.
  • Literal token plus intent: run query_by: "hybrid" and query_by: "text" in parallel, dedupe by chunk_uuid, and keep the text hits.
  • Recall, then rerank: ask for max_results: 20 and apply your own rules before picking the final set.
  • Caching: key on the database, the collections, the caller’s acl, and every query parameter, and expire entries when context or permissions change.
To search beyond one collection:
  • Several collections: send collections instead, as a list, or as an object of weights to rank one collection over another. Up to 100; every listed collection must exist, or the call returns 400. max_results caps the merged list.
  • Knowledge and memories together: type: "all" reads both from the same collections and ranks them together. When shared documents and memories live in different collections, list both.
  • A slice you already know: metadata_filters narrows results before ranking, such as only runbooks or only one team’s documents. Metadata covers the operators.
Knowledge and memories come back together in data.chunks, ranked as one list. To let the user’s memories outrank the shared documents, send weights instead of a list:

5. Add relationships

Three fields bring in context beyond the passages that matched. All three are on by default.
  • graph_context: the relationships HydraDB extracted from your context, such as “Payments team owns billing service”, in data.graph_context. false drops it, but only in fast mode; thinking always includes it. Context Graphs explains how to read it.
  • query_forceful_relations: sources linked at ingest with relations.ids, such as a contract and its addendum, returned in data.additional_context. Thinking mode only; fast mode skips it without an error. Knowledge shows how to declare the links.
  • query_apps: for app sources, an extra lane that rebuilds Slack threads, follows ticket and parent links, and matches exact ids and people. It still searches everything else, and has no effect on memories.

6. Query on behalf of a user

Send the caller’s email in acl, such as "acl": ["[email protected]"], and results are limited to documents that person may retrieve, plus public and unrestricted ones. Without acl the query is not filtered, so derive it from your signed-in session, never from the client. Access Control covers setting ACLs on documents and the principal forms.

Common mistakes