From 3ecdf4f9aec32316d637a37b95688e088edc40c9 Mon Sep 17 00:00:00 2001 From: r266-tech Date: Fri, 12 Jun 2026 08:47:24 +0800 Subject: [PATCH] docs(observations): document exact scope filtering --- hindsight-docs/docs/developer/api/recall.mdx | 9 ++++++++- hindsight-docs/docs/developer/api/reflect.mdx | 2 +- hindsight-docs/docs/developer/observations.mdx | 2 ++ skills/hindsight-docs/references/developer/api/recall.md | 9 ++++++++- .../hindsight-docs/references/developer/api/reflect.md | 2 +- .../hindsight-docs/references/developer/observations.md | 2 ++ 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hindsight-docs/docs/developer/api/recall.mdx b/hindsight-docs/docs/developer/api/recall.mdx index 7d31f8e510..9611ec7458 100644 --- a/hindsight-docs/docs/developer/api/recall.mdx +++ b/hindsight-docs/docs/developer/api/recall.mdx @@ -171,6 +171,7 @@ The `tags_match` parameter controls the filtering logic: | `any_strict` | Excluded | Memory has **at least one** of the specified tags | | `all` | Included | Memory has **all** of the specified tags | | `all_strict` | Excluded | Memory has **all** of the specified tags | +| `exact` | Excluded | Memory has **exactly** the specified tag set | #### Scenario setup @@ -271,6 +272,12 @@ Use this for strict scope enforcement where a memory must explicitly belong to * A memory with tags `["user:alice", "team", "project:x"]` will still match a filter of `["user:alice", "team"]` under `all_strict` — extra tags on the memory are not a problem. The filter only requires the memory to contain **at least** the specified tags. ::: +#### `exact` — set equality, excludes untagged + +Returns memories whose tag set is exactly equal to the specified tags, regardless of tag order. Unlike `all_strict`, memories with extra tags do not match. + +Use this when filtering a precise observation scope returned by `GET /v1/default/banks/{bank_id}/observations/scopes`, where `["user:alice"]` should not also match observations scoped to `["user:alice", "project:x"]`. + ### tag_groups `tag_groups` is a list of compound boolean tag filters. The groups in the list are AND-ed together at the top level. Each group is a recursive boolean expression: a **leaf** node `{tags, match}`, or a **compound** node `{and: [...]}`, `{or: [...]}`, or `{not: ...}`. @@ -283,7 +290,7 @@ A memory with tags `["user:alice", "team", "project:x"]` will still match a filt { "tags": ["step:5", "step:8"], "match": "any_strict" } ``` -`match` accepts the same values as `tags_match`: `any`, `all`, `any_strict`, `all_strict`. Defaults to `any_strict`. +`match` accepts the same values as `tags_match`: `any`, `all`, `any_strict`, `all_strict`, `exact`. Defaults to `any_strict`. #### Compound nodes diff --git a/hindsight-docs/docs/developer/api/reflect.mdx b/hindsight-docs/docs/developer/api/reflect.mdx index 14e99c6b47..925c219062 100644 --- a/hindsight-docs/docs/developer/api/reflect.mdx +++ b/hindsight-docs/docs/developer/api/reflect.mdx @@ -95,7 +95,7 @@ An optional JSON Schema object. When provided, the LLM generates a response that ### tags -Filters which memories the agent can access during reflection. Works identically to [recall tags](./recall#tags) — only memories matching the specified tags are considered. The `tags_match` parameter controls the matching logic (`any`, `all`, `any_strict`, `all_strict`) with the same semantics as recall. +Filters which memories the agent can access during reflection. Works identically to [recall tags](./recall#tags) — only memories matching the specified tags are considered. The `tags_match` parameter controls the matching logic (`any`, `all`, `any_strict`, `all_strict`, `exact`) with the same semantics as recall. diff --git a/hindsight-docs/docs/developer/observations.mdx b/hindsight-docs/docs/developer/observations.mdx index e367fa8e30..c5c3cc4ae0 100644 --- a/hindsight-docs/docs/developer/observations.mdx +++ b/hindsight-docs/docs/developer/observations.mdx @@ -175,6 +175,8 @@ By default, observations are scoped to all of a memory's tags combined. The `obs See [`observation_scopes` in the Retain API](./api/retain#observation_scopes) for the full explanation and options. +To inspect the scopes that already exist in a bank, call `GET /v1/default/banks/{bank_id}/observations/scopes`. The response lists each exact tag set with its observation count; the empty tag list is the global scope. Use a returned scope as `tags` with `tags_match: "exact"` when you need to filter to that precise observation scope without also matching observations that carry extra tags. + --- ## Observations Mission diff --git a/skills/hindsight-docs/references/developer/api/recall.md b/skills/hindsight-docs/references/developer/api/recall.md index 3cd339b74c..fe47a9c09c 100644 --- a/skills/hindsight-docs/references/developer/api/recall.md +++ b/skills/hindsight-docs/references/developer/api/recall.md @@ -324,6 +324,7 @@ The `tags_match` parameter controls the filtering logic: | `any_strict` | Excluded | Memory has **at least one** of the specified tags | | `all` | Included | Memory has **all** of the specified tags | | `all_strict` | Excluded | Memory has **all** of the specified tags | +| `exact` | Excluded | Memory has **exactly** the specified tag set | #### Scenario setup @@ -515,6 +516,12 @@ Use this for strict scope enforcement where a memory must explicitly belong to * > **💡 Extra tags are fine** > A memory with tags `["user:alice", "team", "project:x"]` will still match a filter of `["user:alice", "team"]` under `all_strict` — extra tags on the memory are not a problem. The filter only requires the memory to contain **at least** the specified tags. +#### `exact` — set equality, excludes untagged + +Returns memories whose tag set is exactly equal to the specified tags, regardless of tag order. Unlike `all_strict`, memories with extra tags do not match. + +Use this when filtering a precise observation scope returned by `GET /v1/default/banks/{bank_id}/observations/scopes`, where `["user:alice"]` should not also match observations scoped to `["user:alice", "project:x"]`. + ### tag_groups `tag_groups` is a list of compound boolean tag filters. The groups in the list are AND-ed together at the top level. Each group is a recursive boolean expression: a **leaf** node `{tags, match}`, or a **compound** node `{and: [...]}`, `{or: [...]}`, or `{not: ...}`. @@ -527,7 +534,7 @@ A memory with tags `["user:alice", "team", "project:x"]` will still match a filt { "tags": ["step:5", "step:8"], "match": "any_strict" } ``` -`match` accepts the same values as `tags_match`: `any`, `all`, `any_strict`, `all_strict`. Defaults to `any_strict`. +`match` accepts the same values as `tags_match`: `any`, `all`, `any_strict`, `all_strict`, `exact`. Defaults to `any_strict`. #### Compound nodes diff --git a/skills/hindsight-docs/references/developer/api/reflect.md b/skills/hindsight-docs/references/developer/api/reflect.md index a5100e1b66..722f56811c 100644 --- a/skills/hindsight-docs/references/developer/api/reflect.md +++ b/skills/hindsight-docs/references/developer/api/reflect.md @@ -173,7 +173,7 @@ rm -f schema.json ### tags -Filters which memories the agent can access during reflection. Works identically to [recall tags](./recall#tags) — only memories matching the specified tags are considered. The `tags_match` parameter controls the matching logic (`any`, `all`, `any_strict`, `all_strict`) with the same semantics as recall. +Filters which memories the agent can access during reflection. Works identically to [recall tags](./recall#tags) — only memories matching the specified tags are considered. The `tags_match` parameter controls the matching logic (`any`, `all`, `any_strict`, `all_strict`, `exact`) with the same semantics as recall. ### Python diff --git a/skills/hindsight-docs/references/developer/observations.md b/skills/hindsight-docs/references/developer/observations.md index e0c1826432..4e5564fa00 100644 --- a/skills/hindsight-docs/references/developer/observations.md +++ b/skills/hindsight-docs/references/developer/observations.md @@ -183,6 +183,8 @@ By default, observations are scoped to all of a memory's tags combined. The `obs See [`observation_scopes` in the Retain API](./api/retain#observation_scopes) for the full explanation and options. +To inspect the scopes that already exist in a bank, call `GET /v1/default/banks/{bank_id}/observations/scopes`. The response lists each exact tag set with its observation count; the empty tag list is the global scope. Use a returned scope as `tags` with `tags_match: "exact"` when you need to filter to that precise observation scope without also matching observations that carry extra tags. + --- ## Observations Mission