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).
This commit is contained in:
Nicolò Boschi 2026-04-07 10:41:32 +02:00 committed by GitHub
parent f31f82627c
commit f659bb17c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 1 deletions

View file

@ -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.

View file

@ -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.