From f659bb17c4257a4d3134ebdb6399ec44e5ffd795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Tue, 7 Apr 2026 10:41:32 +0200 Subject: [PATCH] docs: add best practice for filtering recall by memory shape (#856) (#905) Add guidance on using entity labels with `tag: true` to deterministically filter recall results when a bank contains different memory shapes (e.g., concise rules vs. detailed procedures). --- hindsight-docs/src/pages/best-practices.mdx | 46 ++++++++++++++++++++- hindsight-docs/src/pages/faq.mdx | 15 +++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/hindsight-docs/src/pages/best-practices.mdx b/hindsight-docs/src/pages/best-practices.mdx index 4fa2e0fe..0c793e04 100644 --- a/hindsight-docs/src/pages/best-practices.mdx +++ b/hindsight-docs/src/pages/best-practices.mdx @@ -12,7 +12,7 @@ import PageHero from '@site/src/components/PageHero'; - [Core Concepts](#core-concepts) — Memory banks, taxonomy, memory types - [Bank Configuration](#bank-configuration) — Missions, dispositions, entity labels - [Retaining Data](#retaining-data) — Content format, context, document_id, [tags](#tags-naming-conventions), observation scopes -- [Recalling Memories](#recalling-memories) — Budget, tag filtering, include options, query_timestamp +- [Recalling Memories](#recalling-memories) — Budget, tag filtering, entity label filtering, include options, query_timestamp - [Reflecting](#reflecting) — Recall vs reflect, response_schema, auditing - [Mental Models](#mental-models) — When to create, tag strategy, refresh - [Anti-patterns](#anti-patterns) @@ -402,6 +402,50 @@ recall( --- +### Filtering by Memory Shape with Entity Labels + +When a single bank contains semantically similar memories that serve different purposes (e.g., concise operating rules vs. detailed troubleshooting procedures), ranking alone cannot reliably distinguish them — two memories about "entrypoints" will score similarly regardless of whether one is a one-line rule and the other is a multi-step runbook. + +Use [entity labels](/developer/api/memory-banks#entity-labels) with `tag: true` to classify facts at retain time and hard-filter at recall time. + +**1. Define a label group on the bank:** + +```json +{ + "entity_labels": [ + { + "key": "memory_type", + "description": "The type of knowledge: 'rule' for concise operating rules and canonical guidance, 'procedure' for step-by-step technical instructions and troubleshooting notes", + "type": "value", + "optional": false, + "tag": true, + "values": [ + { "value": "rule", "description": "Concise operating rule or canonical guidance" }, + { "value": "procedure", "description": "Step-by-step technical instruction or troubleshooting note" } + ] + } + ] +} +``` + +**2. Retain normally** — the LLM classifies each fact automatically and writes `memory_type:rule` or `memory_type:procedure` as a tag. + +**3. Filter at recall time:** + +```python +# Only rules — procedures are excluded at the database level, not post-filtered +result = client.recall( + bank_id="my-bank", + query="which entrypoint should I use?", + tags=["memory_type:rule"], + tags_match="any_strict" +) +``` + +This is a hard SQL WHERE clause applied across all four retrieval strategies. The unwanted memories never enter the ranking pipeline. + +--- + ### `query_timestamp` Set for time-sensitive queries. Anchors temporal ranking to a specific point in time. diff --git a/hindsight-docs/src/pages/faq.mdx b/hindsight-docs/src/pages/faq.mdx index cf15c74e..865d4003 100644 --- a/hindsight-docs/src/pages/faq.mdx +++ b/hindsight-docs/src/pages/faq.mdx @@ -21,6 +21,7 @@ import PageHero from '@site/src/components/PageHero'; - [When should I use mental models?](#when-should-i-use-mental-models) - [Latency expectations](#whats-the-typical-latency-for-recall-operations) - [Tags, metadata, and entity labels](#does-hindsight-support-metadata-filtering) +- [Controlling which memory types are recalled](#how-do-i-control-which-types-of-memories-are-recalled) - [Recommended format for conversations](#what-is-the-recommended-format-for-retaining-conversations) --- @@ -248,6 +249,20 @@ Metadata is not a filter — use tags when you need recall to be scoped to a sub --- +### How do I control which types of memories are recalled? + +If your bank mixes different shapes of memory (e.g., concise rules and detailed procedures) and recall surfaces the wrong shape for a given query, use **entity labels** with `tag: true` to classify facts during retain and hard-filter them during recall. + +1. Define a label group on the bank with `tag: true` and a controlled vocabulary (e.g., `rule` vs `procedure`) +2. Retain normally — the LLM classifies each extracted fact automatically +3. Pass `tags=["memory_type:rule"]` and `tags_match="any_strict"` at recall time to deterministically include only matching memories + +This is a SQL-level filter applied before ranking, not a scoring signal — the excluded memories never enter the retrieval pipeline. This is more reliable than adjusting ranking weights, which only nudge continuous scores and cannot guarantee ordering. + +See [Best Practices — Filtering by Memory Shape](/best-practices#filtering-by-memory-shape-with-entity-labels) for a full walkthrough, or [Entity Labels](/developer/api/memory-banks#entity-labels) for the configuration reference. + +--- + ### What is the recommended format for retaining conversations? Pass the **entire conversation as a single document** and upsert it as the conversation grows — Hindsight chunks it automatically, so you don't need to split it yourself.