Query memory with recall()
SkillSearchcognee-recall is a skill that teaches an AI agent to query cognee memory with recall(), the query API that searches the graph and session cache and returns tagged results. It covers how a search type is chosen, how to scope a query to datasets, node sets or sessions, and how to read results and citations. It also helps debug empty or unexpected results.
Then ask your AI: use the Query memory with recall() skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Have a working cognee installation with memory already stored that the agent can read.
What your AI can do with it
- Call recall() to search cognee memory and return tagged results
- Pick a search type explicitly or let the regex router choose one
- Scope queries with datasets, dataset_ids, node sets or sessions
- Request context or citations instead of a generated answer
- Use filters like top_k and structured responses
- Debug empty or unexpected results, including permission-related ones
Getting started
- Have a working cognee installation with memory already stored that the agent can read.
- Make recall() available to the agent, either directly or through the skill.
- Decide whether to pass an explicit query_type or rely on the default auto-routing.
- Narrow the search by passing datasets, dataset_ids, node sets or sessions when you know where the answer lives.
- Read the returned tagged result objects and inspect source and text fields.
What this skill tells your AI
The instructions your AI receives, as published by topoteretes/cognee in .agents/skills/cognee-recall/SKILL.md and read by Ahel’s review.
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.
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
- An explicit
query_type=SearchType.Xalways wins. - Otherwise, with no usable LLM key,
CHUNKS(plain vector search). - 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
- the whole query is one
- 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.
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; reads the Timestamp nodes the default pipeline extracts |
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 atmin(top_k, 10); setchunks_top_k/entities_top_k/facts_top_kinretriever_specific_configto go higher.node_name=["AI"](+node_name_filter_operator="OR"|"AND"): restricts graph/chunk/completion types to data remembered with thatnode_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, onr.structured.include_references=True: attach the document chunks that support each graph edge used (needsEDGE_EVIDENCE_ENABLED=true, the default).only_context=True: return what the LLM would have received instead of an answer.r.textis the rendered user prompt,r.system_promptthe system prompt. Pinquery_typewhen you use it.retriever_specific_config={...}: retriever-only options. For the agentic extras (skills,tools,max_iter) andnode_type, callcognee.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 onesource="system"memory_warming_upmarker from a graph-only recall (withonly_context=TrueorRECALL_WARMUP_SHORTCIRCUIT=falseit 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 raisesPermissionDeniedError(HTTP 403). Dataset names resolve only among the user's own datasets, so a name that is not theirs (even one shared with them) raisesDatasetNotFoundError; usedataset_idsfor shared datasets. See thecognee-permissionsskill. - "Memory warming up". On an empty graph, a graph-only recall (no
session sources, not
only_context) returns onesource="system"item withstatus="memory_warming_up"(or"build_failed"pluserror_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_depthorfeedback_influence > 0(including a nonzeroDEFAULT_FEEDBACK_INFLUENCE), or the chunk collection is missing.node_namestays on hybrid, which filters to that node set.search()also defers for a customnode_typeornode_namewithnode_type=None;recall()has nonode_type.wide_search_top_kandtriplet_distance_penaltywith hybrid raiseInvalidHybridSearchConfig; pinGRAPH_COMPLETIONto use them. SKILLSandAGENTIC_COMPLETIONneed exactly one dataset. ForSKILLS,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. ForAGENTIC_COMPLETIONonlysearch()checks it up front, so call it throughsearch()with one dataset.code_querywithoutscope="code"raises, andscope="tools"also needsTOOL_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. WithCACHINGandAUTO_FEEDBACKon (defaults), each answered turn adds one analysis call, even without asession_id. SetAUTO_FEEDBACK=falsefor low-latency reads (see thecognee-performanceskill).
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:
- Write the retriever in
cognee/modules/retrieval/(subclassBaseRetrieveror a completion base). - Add the
SearchTypemember and itssearch_core_registryentry. - 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. - Optional: add it to
SEARCH_TYPE_CHOICESincognee/cli/config.pyfor the CLI, or a regex rule toquery_router.pyfor auto-routing. Never route a type that can write.
Signals
- GitHub stars
- 32k
- Forks
- 3k
- Last commit
- Oct 2026
Questions
- How is the search type picked?
- An explicit query_type always wins. Otherwise, with no usable LLM key, CHUNKS is used.
- How do I scope a query to datasets, node sets or sessions?
- Pass datasets with names or dataset_ids with UUIDs, and dataset_ids win when both are given. Without datasets, recall searches every dataset the user can read. Scoping also makes the search faster.
Advanced
- Item type
- skill
- Key
cognee-recall-topoteretes- Source
- github.com/topoteretes/cognee