> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hydradb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Recall

> How HydraDB retrieves the right context for each query - across Knowledge, Memories, and the context graph.

Recall turns stored context into the *right* context for a specific query. This page covers what recall is, the endpoints HydraDB exposes, the parameters that matter, and the patterns you'll reach for in production.

For request/response schemas, see the API reference: [Full Recall](/api-reference/endpoint/full-recall), [Memory Recall](/api-reference/endpoint/recall-preferences), [Boolean Recall](/api-reference/endpoint/boolean-recall).

***

## 1. What is Recall

Recall returns the chunks most likely to help your agent succeed on a query - not just the chunks most textually similar to it. Pure vector search gives you similarity; recall gives you usefulness.

HydraDB stores two kinds of context in separate vector stores:

| Store         | Contains                                                          | `vectorstore_status` index | Recall endpoint      |
| ------------- | ----------------------------------------------------------------- | -------------------------- | -------------------- |
| **Memories**  | User preferences, conversation history, per-user inferred content | Index `0` (`[0]`)          | `recall_preferences` |
| **Knowledge** | Ingested documents, files, and app sources                        | Index `1` (`[1]`)          | `full_recall`        |

A single recall call hits one store. To use both in one prompt, call the matching endpoint for each and merge the results.

When `graph_context` is enabled, recall also traverses the **context graph** - a graph of relationships between stored context that HydraDB derives automatically from your data - so related material that pure similarity would miss can come back with the result.

***

## 2. When to use Recall

Use recall when you need:

* Grounded answers from documents or app sources
* Personalized responses for a specific user
* Context-aware retrieval across multiple sources
* Deterministic metadata filtering combined with semantic search

Reach for something else when:

* You need the full document, not ranked chunks → use `/fetch/content`.

***

## 3. Types of Recall

HydraDB exposes three endpoints under `/recall/*`. Pick one based on what you need back.

| Endpoint                          | Searches                              | Returns           | Use when                                     |
| --------------------------------- | ------------------------------------- | ----------------- | -------------------------------------------- |
| `POST /recall/full_recall`        | Knowledge                             | `RetrievalResult` | You need facts from documents                |
| `POST /recall/recall_preferences` | Memories                              | `RetrievalResult` | You need user-specific context               |
| `POST /recall/boolean_recall`     | Knowledge or Memories (`search_mode`) | `RetrievalResult` | You need exact term, AND, or phrase matching |

`full_recall` and `recall_preferences` share the same request and response shape (`RecallSearchRequest` → `RetrievalResult`). `boolean_recall` accepts a smaller set of parameters and runs deterministic lexical matching - no graph traversal, no metadata filters.

To deliver a personalized answer, the canonical pattern is two parallel calls - `full_recall` for shared Knowledge, `recall_preferences` for the user's Memories - merged into a single LLM prompt. See [Minimal Working Example](#6-minimal-working-example).

***

## 4. How Recall Works

The semantic recall endpoints (`full_recall`, `recall_preferences`) accept a `mode`:

| Mode             | Pipeline                             | Latency |
| ---------------- | ------------------------------------ | ------- |
| `fast` (default) | Single query                         | Lower   |
| `thinking`       | Multi-query expansion with reranking | Higher  |

`thinking` produces higher-quality results by expanding the query into sub-queries and reranking candidates. It also surfaces forceful-relation extras (`extra_context_ids` and the `additional_context` map on the response) when matching sources have them. `fast` skips both steps.

`boolean_recall` has no `mode` parameter - it always runs deterministic term matching.

**Rule of thumb.** If a human will read the result, use `thinking`. If a machine will filter it further or low latency is the priority, use `fast`.

***

## 5. Key Parameters

These apply to `full_recall` and `recall_preferences` (`RecallSearchRequest`):

| Parameter                   | Type                     | Default        | Purpose                                                                                                     |
| --------------------------- | ------------------------ | -------------- | ----------------------------------------------------------------------------------------------------------- |
| `tenant_id`                 | string                   | - *(required)* | Tenant identifier - the top-level scoping identifier.                                                       |
| `sub_tenant_id`             | string \| null           | none           | Scopes recall to a user, workspace, or partition. If omitted, HydraDB uses the tenant's default sub-tenant. |
| `query`                     | string                   | - *(required)* | Search terms.                                                                                               |
| `mode`                      | `"fast"` \| `"thinking"` | `"fast"`       | Retrieval pipeline.                                                                                         |
| `max_results`               | integer \| null          | server default | Maximum chunks to return. Start with 10.                                                                    |
| `alpha`                     | number \| `"auto"`       | `0.8`          | Hybrid ranking weight (`0.0` = keyword, `1.0` = semantic).                                                  |
| `recency_bias`              | number                   | `0.0`          | Boost for newer content (`0.0`–`1.0`).                                                                      |
| `graph_context`             | boolean                  | `false`        | Set `true` to populate `graph_context` in the response.                                                     |
| `metadata_filters`          | object \| null           | `null`         | Equality filters on declared, match-enabled metadata fields. Undeclared filters are ignored.                |
| `additional_context`        | string \| null           | `null`         | Extra hint to guide retrieval (e.g. `"User is on the billing page"`).                                       |
| `search_forceful_relations` | boolean                  | `true`         | Whether to fetch forceful-relation extras. Only takes effect in `"thinking"` mode.                          |

`boolean_recall` (`FullTextSearchRequest`) is intentionally narrower:

| Parameter                             | Type                            | Default     | Purpose                                         |
| ------------------------------------- | ------------------------------- | ----------- | ----------------------------------------------- |
| `tenant_id`, `sub_tenant_id`, `query` | -                               | -           | As above. `query` and `tenant_id` are required. |
| `operator`                            | `"or"` \| `"and"` \| `"phrase"` | `"or"`      | How search terms combine.                       |
| `max_results`                         | integer                         | `10`        | Result cap.                                     |
| `search_mode`                         | `"sources"` \| `"memories"`     | `"sources"` | Which store to search.                          |

It does **not** accept `mode`, `alpha`, `recency_bias`, `graph_context`, `metadata_filters`, or `additional_context`. If you need any of those, use a semantic endpoint.

<Warning>
  <strong>Two defaults that surprise developers</strong>

  <ul>
    <li><code>graph\_context</code> defaults to <code>false</code> - set it to <code>true</code> to receive graph data in the response.</li>
    <li><code>recency\_bias</code> defaults to <code>0</code> - no recency boost is applied unless you set it.</li>
  </ul>
</Warning>

<Warning>
  <strong><code>metadata\_filters</code> requires a pre-declared schema</strong>
  <p>Top-level filter keys should be defined in <code>tenant\_metadata\_schema</code> with matching enabled. Undeclared filters are ignored, so plan filterable keys before your first ingestion.</p>
  <p>See <a href="/api-reference/endpoint/create-tenant">Create Tenant</a>.</p>
</Warning>

### Tuning heuristics

* **`alpha`** - Start at `0.8`. Lower toward `0.3–0.5` when the query contains literal tokens (error codes, SKUs, product names). Raise toward `0.9` for conceptual questions. Use `"auto"` when the query shape varies.
* **`recency_bias`** - Leave at `0` for static reference material. Set `0.2–0.4` for mixed content, `0.6–0.8` for changelogs, news, or status updates.
* **`max_results`** - Start at `10`. Drop to `5` for tight context windows; raise to `20` if you rerank downstream.
* **`additional_context`** - Use it when the query alone is ambiguous. Keep it short and factual.

***

## 6. Minimal Working Example

The canonical personalized-answer flow: recall Knowledge, recall the user's Memories in parallel, merge into one LLM prompt.

### Setup

<CodeGroup>
  ```bash cURL theme={"dark"}
  # Set your key as an environment variable - used in every request below
  export HYDRA_DB_API_KEY="your_api_key"
  # All requests: -H "Authorization: Bearer $HYDRA_DB_API_KEY"
  ```

  ```typescript TypeScript SDK theme={"dark"}
  import { HydraDBClient } from "@hydradb/sdk";

  const client = new HydraDBClient({
    token: process.env.HYDRA_DB_API_KEY,
  });
  ```

  ```python Python SDK theme={"dark"}
  import os
  from hydra_db import HydraDB

  client = HydraDB(token=os.environ["HYDRA_DB_API_KEY"])
  ```
</CodeGroup>

### Recall - Knowledge and Memories in parallel

<CodeGroup>
  ```bash cURL theme={"dark"}
  # Run both in parallel from your shell or application layer

  curl -X POST 'https://api.hydradb.com/recall/full_recall' \
    -H "Authorization: Bearer $HYDRA_DB_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "tenant_id": "acme_corp",
      "query": "How do I reset my password?",
      "mode": "thinking",
      "max_results": 5,
      "graph_context": true
    }'

  curl -X POST 'https://api.hydradb.com/recall/recall_preferences' \
    -H "Authorization: Bearer $HYDRA_DB_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "tenant_id": "acme_corp",
      "sub_tenant_id": "user_john_123",
      "query": "answer style and tone preferences",
      "mode": "thinking",
      "max_results": 3
    }'
  ```

  ```typescript TypeScript SDK theme={"dark"}
  async function gatherContext(
    tenantId: string,
    userId: string,
    query: string,
  ) {
    const [knowledge, memories] = await Promise.all([
      client.recall.fullRecall({
        tenant_id: tenantId,
        query,
        mode: "thinking",
        max_results: 5,
        graph_context: true,
      }),
      client.recall.recallPreferences({
        tenant_id: tenantId,
        sub_tenant_id: userId,
        query: "answer style and tone preferences",
        mode: "thinking",
        max_results: 3,
      }),
    ]);
    return { knowledge, memories };
  }
  ```

  ```python Python SDK theme={"dark"}
  import asyncio
  from hydra_db import AsyncHydraDB

  async_client = AsyncHydraDB(token=os.environ["HYDRA_DB_API_KEY"])

  async def gather_context(tenant_id: str, user_id: str, query: str):
      knowledge, memories = await asyncio.gather(
          async_client.recall.full_recall(
              tenant_id=tenant_id,
              query=query,
              mode="thinking",
              max_results=5,
              graph_context=True,
          ),
          async_client.recall.recall_preferences(
              tenant_id=tenant_id,
              sub_tenant_id=user_id,
              query="answer style and tone preferences",
              mode="thinking",
              max_results=3,
          ),
      )
      return knowledge, memories
  ```
</CodeGroup>

### Merge into the LLM prompt

Both calls return the same shape: `chunks[]`, `sources[]`, and (when applicable) `graph_context` and `additional_context`. Format each into a context string - the helper in [How to Use API Results](/essentials/api-results) does this - and feed both into your prompt:

```typescript theme={"dark"}
const knowledgeCtx = buildContextString(knowledge);
const memoryCtx = buildContextString(memories);

const completion = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [
    {
      role: "system",
      content: "Answer using only the provided context. Match the user's preferred style.",
    },
    {
      role: "user",
      content: `User preferences:\n${memoryCtx}\n\nRelevant docs:\n${knowledgeCtx}\n\nQuestion: How do I reset my password?`,
    },
  ],
});
```

### Production checklist

* **Parallelize** the two recall calls - they're independent.
* **Set per-call timeouts.** Generous for `thinking` (3–5s), tight for `fast` (≤500ms).
* **Degrade gracefully.** If memory recall fails or times out, continue with Knowledge only.
* **Pass `additional_context`** with known session state (page, feature, role). It can sharpen retrieval without requiring additional calls.

***

## 7. Common Mistakes

| Symptom                                                                    | Cause                                                             | Fix                                                                                                                                 |
| -------------------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Empty `query_paths` / `chunk_relations`                                    | `graph_context` not set, or no relations exist for the result set | Set `graph_context: true`; empty arrays are normal when there's nothing to return.                                                  |
| Recent uploads don't appear                                                | Indexing not finished                                             | Poll [`/ingestion/verify_processing`](/api-reference/endpoint/verify-processing) - chunks are invisible until processing completes. |
| `metadata_filters` does not narrow results                                 | Filter key is undeclared or not match-enabled                     | Declare filterable keys in `tenant_metadata_schema` with `enable_match: true` before ingestion.                                     |
| Memories missing from `full_recall` (or vice versa)                        | Knowledge and Memories are separate stores                        | Call both endpoints and merge.                                                                                                      |
| Recency doesn't seem to matter                                             | `recency_bias` defaults to `0`                                    | Set it explicitly between `0.1` and `1.0`.                                                                                          |
| `400` / `422` on `boolean_recall` with `alpha`, `mode`, or `graph_context` | Boolean recall doesn't accept those parameters                    | Drop them, or switch to a semantic endpoint.                                                                                        |

***

## 8. Advanced Patterns

**Hybrid: `boolean_recall` + `full_recall`.** When a query mixes a literal token (error code, SKU, function name) with natural-language intent, run both, dedupe by `chunk_uuid`, and treat boolean hits as a "must include" floor.

**Recall-then-rerank.** Request more chunks than you need (`max_results: 20`), then apply your own reranker - recency windows, compliance filters, business rules - before picking the final top-k for the prompt.

***

## Related

* [Memories](/essentials/memories) - user-scoped dynamic context
* [Knowledge](/essentials/knowledge) - shared document context
* [Metadata](/essentials/metadata) - designing filterable fields
* [Context Graphs](/essentials/context-graphs) - how graph traversal enriches recall
* [How to Use API Results](/essentials/api-results) - turning `RetrievalResult` into an LLM prompt
