Skip to main content
HydraDB is context infrastructure for AI applications. From the outside, you call a small set of HTTP APIs. Inside, HydraDB orchestrates database isolation, asynchronous ingestion, indexing, graph construction, and hybrid retrieval - so your application can store context once and query the right pieces later. This page walks through what happens behind the scenes, and points at the endpoints and concepts you’ll touch along the way.

The big picture

HydraDB organizes its work into three logical planes. You interact only with the API; everything else stays behind the service boundary. Two details to notice in the diagram:
  • Two vector stores, one ingest endpoint. POST /context/ingest routes to the Knowledge store when type=knowledge and to the Memories store when type=memory. Same endpoint, different bucket.
  • One query endpoint, every retrieval method. POST /query is the only retrieval entry point. The type and query_by parameters decide what gets queried and how - see Query for the full picture.

Ingestion lifecycle

Ingestion is asynchronous. A successful upload means HydraDB accepted the work and queued it; it does not mean the content is immediately queryable. Each source moves through a status pipeline before it becomes fully queryable: Poll GET /context/status with the returned id to follow each item through the pipeline. Two practical notes:
  • graph_creation is already queryable. Chunks become retrievable as soon as embedding finishes; you only need to wait for completed when you specifically need full graph context (graph_context: true on query).
  • Failures surface with detail. An errored status comes back with an error_code and message so you can distinguish parse failures from validation problems from infrastructure issues.
The full status table and polling pattern lives at Ingestion Status.

From upload to query

Here’s the canonical end-to-end flow. Each step links to the endpoint that owns it:
  1. Create a database with POST /databases - your isolated workspace, optionally with a metadata schema declared up front.
  2. Wait for provisioning by polling GET /databases/status until vectorstore_status.knowledge, vectorstore_status.memories, and graph_status are all true.
  3. Ingest content with POST /context/ingest - pick type=knowledge for shared documents or type=memory for per-user context. See Knowledge and Memories for the content models.
  4. Watch indexing finish by polling GET /context/status until each id reaches completed (or graph_creation if you don’t need graph traversal).
  5. Query with POST /query. Pick type: "knowledge" for Knowledge, type: "memory" for Memories, or type: "all" for both. Pair with query_by: "hybrid" (default) or "text" (BM25, with operator). The mechanics live in Query.
That’s the whole loop. Most of what changes between integrations is what you put in the metadata, what you query with, and which type and query_by combination fits the task.

Database isolation

A database (formerly tenant_id, still accepted as a deprecated alias) is the top-level isolation boundary - no database can read another database’s data. Within a database, collection (formerly sub_tenant_id) carves out logical partitions: users, teams, workspaces, or projects. Omitting collection on any call resolves to the database’s default collection, which is created on the first write - no collection exists until then. The right mapping depends on your product shape: The deeper trade-offs - when to spin up a new database vs. a new collection, how scoping interacts with metadata filters, and how this affects Memories - are covered in Multi-Tenant Support.

Retrieval pipeline

POST /query is the single retrieval endpoint. Two parameters describe the request: type picks the collection, query_by picks the method. From there, every call goes through the same pipeline:
  1. Authenticate and scope. Validate database, resolve the database, and apply the requested collection.
  2. Filter before ranking. Apply metadata_filters to narrow the candidate set (see Metadata).
  3. Retrieve. Run hybrid retrieval over the semantic vector store and the keyword bm25 index, or BM25-only retrieval when query_by: "text".
  4. Blend. Use alpha to weight semantic vs. keyword bm25 contributions (1.0 = pure semantic, 0.0 = pure BM25).
  5. Enrich. When graph_context: true, traverse the context graph and attach related paths. When mode: "thinking", expand the query, rerank, and pull in author-declared forceful relations.
  6. Shape the response. Return ranked chunks, deduplicated sources, optional graph_context, and any additional_context.
The response is retrieved context, not a final LLM answer. You pass the chunks (and any graph context) into your own agent or model prompt - see How to Use API Results for the helper that formats it.

Key controls

A short cheat sheet for the parameters you’ll touch most often, and where each one lives:

Operational mental model

HydraDB separates write-time work from query-time work. Uploads return quickly and run in the background; query stays synchronous and reads only indexed content. When results look incomplete, walk the chain in order:
  1. Status first. Did every id reach completed (or at least graph_creation)? Check Ingestion Status.
  2. Scope second. Is the database correct? Did you write under one collection and read under another? See Multi-Tenant.
  3. Filters third. Are you using the right namespace? Top-level metadata_filters keys match metadata; free-form fields belong under additional_metadata. For hot top-level filters, declare the field in database_metadata_schema with enable_match: true. See Metadata.
This order catches almost every “I uploaded but query returns nothing” debugging session.