---
name: topoteretes-cognee-recall
title: cognee recall
kind: skill
description: >
  Use when querying cognee memory with recall() (or search()) — picking a search
  type, understanding auto-routing, scoping to datasets, node sets or sessions,
  getting context or citations instead of an answer, reading the results, or
  debugging empty or unexpected results.
updated: 2026-10-03
authored_by: topoteretes
author_url: https://github.com/topoteretes
source_url: https://github.com/topoteretes/cognee/blob/main/.agents/skills/cognee-recall/SKILL.md
brought_by: kt
license: Apache-2.0
---

# Query memory with recall()

`recall()` is cognee's query API. It picks a search strategy, searches the
graph and (with a session) the session cache, and returns a list of tagged
results.

```python
import cognee

results = await cognee.recall("Where was Einstein born?")
for r in results:
    print(r.source, r.text)  # e.g. "graph", "Einstein was born in Ulm."
```

Without `datasets` it searches every dataset the user can read. Pass
`datasets=["research"]` (names) or `dataset_ids=[...]` (UUIDs, which win) to
narrow it; that is also faster.

## Use it

### How the search type is picked

1. An explicit `query_type=SearchType.X` always wins.
2. Otherwise, with no usable LLM key, `CHUNKS` (plain vector search).
3. Otherwise the router (`auto_route=True`, the default). It is two regex
   rules, first match wins, no LLM call:
   - the whole query is one `"quoted phrase"` → `CHUNKS_LEXICAL`
   - mentions coding rules/standards/conventions or code-review guidelines
     → `CODING_RULES`
4. Everything else → `HYBRID_COMPLETION`.

A routed type (never a pinned one) that the backend rejects, or a routed
`CHUNKS_LEXICAL` / `CODING_RULES` that returns nothing, is retried once as
`HYBRID_COMPLETION`. The router never picks `CYPHER`.

```python
from cognee import SearchType

await cognee.recall("What changed in v2?", query_type=SearchType.GRAPH_COMPLETION)
```

### Search types

The full list is `cognee/modules/search/types/SearchType.py`; the
type-to-retriever table is `cognee/modules/retrieval/README.md`.

| Type | LLM? | Use for |
|---|---|---|
| `HYBRID_COMPLETION` (default) | yes | General questions: document passages plus entity neighbourhoods, then an answer |
| `GRAPH_COMPLETION` | yes | Answers from graph relationships |
| `GRAPH_COMPLETION_COT`, `_CONTEXT_EXTENSION`, `_DECOMPOSITION` | yes | Harder multi-hop questions (more LLM calls) |
| `GRAPH_SUMMARY_COMPLETION` | yes | Summarizes the retrieved graph edges at query time (extra LLM call), then answers |
| `RAG_COMPLETION` | yes | Classic chunk RAG |
| `TRIPLET_COMPLETION` | yes | Subject-predicate-object facts (needs triplet embedding) |
| `TEMPORAL` | yes | Time questions; needs data remembered with `temporal_cognify=True` |
| `CHUNKS` | no | Raw passages by vector similarity |
| `CHUNKS_LEXICAL` | no | Keyword / exact-phrase match |
| `SUMMARIES` | no | Document summaries |
| `CODE` | no | Code-graph operations via `code_query={...}`; needs `scope="code"` in recall |
| `SKILLS` | no | Discover skill playbooks; exactly one dataset |
| `CYPHER` | no | Raw Cypher. On by default; `ALLOW_CYPHER_QUERY=false` disables it. It can write, so only pass user-authored queries deliberately |
| `NATURAL_LANGUAGE` | yes | LLM writes Cypher, then runs it (same flag) |
| `GRAPH_REPORT` | partly | Graph insight report: hubs, cross-set links, suggested questions |
| `FEELING_LUCKY` | yes | An LLM picks the type |
| `AGENTIC_COMPLETION` | yes | Multi-step loop with skills/tools; exactly one dataset. Use `search()` for its parameters |

### Scope: which sources are searched

`scope` is one of, or a list of: `graph`, `session`, `session_first`,
`trace`, `session_context`, `all`, `tools`, `code`. `all` means graph +
session + trace + session_context; `tools` and `code` are never included
implicitly.

When `scope` is omitted:

| You pass | Sources |
|---|---|
| `session_id` only | Session first; a session hit skips the graph |
| `session_id` + `datasets` | Session and graph both contribute |
| `session_id` + `query_type` | **Graph only** — pinning a type drops the session |
| no `session_id` | Graph only |

Session and trace search is keyword overlap, not embeddings.

### Filters and knobs

- `top_k=15`: per dataset, not in total. The default HYBRID caps each lane
  at `min(top_k, 10)`; set `chunks_top_k` / `entities_top_k` /
  `facts_top_k` in `retriever_specific_config` to go higher.
- `node_name=["AI"]` (+ `node_name_filter_operator="OR"|"AND"`): restricts
  graph/chunk/completion types to data remembered with that `node_set`.
  SUMMARIES, CHUNKS_LEXICAL, GRAPH_REPORT, CYPHER, NATURAL_LANGUAGE, CODE and
  SKILLS ignore it; CODING_RULES treats it as the rules node-set name.
- `system_prompt` / `system_prompt_path`: change the answering prompt.
- `response_model=MyPydanticModel`: structured answer, on `r.structured`.
- `include_references=True`: attach the document chunks that support each
  graph edge used (needs `EDGE_EVIDENCE_ENABLED=true`, the default).
- `only_context=True`: return what the LLM would have received instead of
  an answer. `r.text` is the rendered user prompt, `r.system_prompt` the
  system prompt. Pin `query_type` when you use it.
- `retriever_specific_config={...}`: retriever-only options. For the
  agentic extras (`skills`, `tools`, `max_iter`) and `node_type`, call
  `cognee.search()` instead, which takes them as parameters.

### Reading the results

Each item is a Pydantic model with a `source` discriminator: `graph`,
`session`, `trace`, `session_context`, `code`, `tools`, `skills`, or
`system`. Graph items carry `text` (always renderable), `search_type`,
`kind`, `score`, `dataset_id` / `dataset_name`, `metadata`, `raw`, and
`structured`. A `system` item is a status
marker, not data (see "memory warming up" below).

When a query sounds procedural ("how do I…", "runbook", "steps to…") and
exactly one dataset is targeted, recall also runs a small `SKILLS` lookup
and appends hits with `source="skills"`. Disable with
`SKILL_GATE_ENABLED=false`.

## Pitfalls

- **Permissions change what you get back.** With no `datasets`, recall
  searches only datasets the user can read, so a user without grants gets
  one `source="system"` `memory_warming_up` marker from a graph-only recall
  (with `only_context=True` or `RECALL_WARMUP_SHORTCIRCUIT=false` it gets
  `[]`; with session sources included only the graph lane is empty, and
  session and trace hits still come back). Asking for a dataset **id** the user cannot read raises
  `PermissionDeniedError` (HTTP 403). Dataset **names** resolve only among
  the user's own datasets, so a name that is not theirs (even one shared
  with them) raises `DatasetNotFoundError`; use `dataset_ids` for shared
  datasets. See the `cognee-permissions` skill.
- **"Memory warming up".** On an empty graph, a graph-only recall (no
  session sources, not `only_context`) returns one `source="system"` item
  with `status="memory_warming_up"` (or `"build_failed"` plus
  `error_message`) instead of results; a multi-source recall just returns
  no graph results. Wait for the
  remember to finish, or check why it failed.
- **Hybrid silently becomes graph completion** when you pass
  `neighborhood_depth` or `feedback_influence > 0` (including a nonzero
  `DEFAULT_FEEDBACK_INFLUENCE`), or the chunk collection is missing.
  `node_name` stays on hybrid, which filters to that node set. `search()`
  also defers for a custom `node_type` or `node_name` with `node_type=None`;
  `recall()` has no `node_type`. `wide_search_top_k` and `triplet_distance_penalty`
  with hybrid raise `InvalidHybridSearchConfig`; pin
  `GRAPH_COMPLETION` to use them.
- **`SKILLS` and `AGENTIC_COMPLETION` need exactly one dataset.** For
  `SKILLS`, `search()` raises unless exactly one dataset is given.
  `recall()` runs SKILLS per dataset with access control on (zero datasets
  gives `[]`, not an error) and raises only with access control off and not
  exactly one dataset. For
  `AGENTIC_COMPLETION` only `search()` checks it up front, so call it through
  `search()` with one dataset.
- **`code_query` without `scope="code"` raises**, and `scope="tools"` also
  needs `TOOL_CALLS_ENABLED=true`.
- **Latency.** Most completion types make one LLM call; COT,
  DECOMPOSITION, CONTEXT_EXTENSION, GRAPH_SUMMARY_COMPLETION, TEMPORAL,
  FEELING_LUCKY (one call to pick the type, then the chosen type's) and
  AGENTIC_COMPLETION (a loop of up to `max_iter`, default 6) make more. NATURAL_LANGUAGE makes one (no answer call) and retries only on
  an empty or failed query, up to 3 attempts. With `CACHING` and
  `AUTO_FEEDBACK` on (defaults), each answered turn adds one analysis call,
  even without a `session_id`. Set
  `AUTO_FEEDBACK=false` for low-latency reads (see the `cognee-performance`
  skill).

## recall() or search()?

Use `recall()`. Drop to `cognee.search()` only for agentic parameters
(`skills`, `tools`, `max_iter`, `node_type`) as first-class arguments, raw
`SearchResult` objects, or a pinned type with no router. `search()` never
searches the session cache; its `session_id` only adds conversation history
to the prompt. Full guide: `docs/recall-vs-search.md`.

## How it works

`recall()` resolves scope and search type, then calls the same authorized
search `search()` uses: datasets resolve through the permission layer with
`read`, one search per dataset runs concurrently, and results are
normalized and tagged.

- Entry point, scope and type resolution: `cognee/api/v1/recall/recall.py`
- Router: `cognee/api/v1/recall/query_router.py`
- Skill gate: `cognee/api/v1/recall/skill_gate.py`
- Result types: `cognee/modules/recall/types/RecallResponse.py`,
  `SearchResultItem.py`
- Scope names: `cognee/memory/entries.py:normalize_scope`
- Warm-up config (`RECALL_WARMUP_*`): `cognee/modules/recall/config.py`
- Core search and fan-out: `cognee/modules/search/methods/search.py`
- Hybrid fallback rules: `cognee/modules/search/methods/hybrid_deferral.py`
- Registry: `cognee/modules/search/methods/get_search_type_retriever_instance.py`

Examples in `examples/guides/`: `recall_core.py`,
`hybrid_retrieval_recall.py`, `references_example.py`, `temporal_recall.py`,
`sessions.py`.

## Extending it

Adding a search type, per `cognee/modules/retrieval/README.md`:

1. Write the retriever in `cognee/modules/retrieval/` (subclass
   `BaseRetriever` or a completion base).
2. Add the `SearchType` member and its `search_core_registry` entry.
3. Add a row to the README table. A unit test
   (`cognee/tests/unit/modules/retrieval/retriever_readme_index_test.py`)
   fails if the table and registry disagree.
4. Optional: add it to `SEARCH_TYPE_CHOICES` in `cognee/cli/config.py` for
   the CLI, or a regex rule to `query_router.py` for auto-routing. Never
   route a type that can write.
