Summary
vault_search's tags filter uses exact-string AND-logic (all attached tags must match a page's frontmatter tags). The agent frequently self-attaches an invented tags filter to a vault_search call — tags derived from the query wording that no page actually carries — which then AND-zeroes an otherwise-good substring/semantic hit. The model reads the empty result as "the page doesn't exist" and hedges/hallucinates absence instead of grounding in a page that is right there.
#674 ("make vault_search's tags-only mode callable") did not fix this interaction.
Evidence (surfaced by the #531 eval diagnostics, PR #)
An eval seeded a vault page incident-escalation.md (content: "page the on-call engineer via Nightwatch, post in #owl-bridge"). Across real runs the model issued:
- Run A:
vault_search {"tags": ["P1","incident","on-call","notification"], "query": "P1 incident on-call notify"} → mode: substring, results: []
- Run B (after adding
tags: [incident, on-call, paging, escalation, notification, P1] to the page): vault_search {"tags": ["incident response","on-call","notification"], "query": "..."} → results: [] — because "incident response" (two words) isn't an exact tag on the page, and AND-logic zeroes the whole match.
Response both times: "I don't have any information … I searched the vault and couldn't find any relevant documents." — a false negative; the page was present.
Adding frontmatter tags to the page only papers over the specific phrases anticipated; the model invents new tag phrases each run, so the tag-enumeration workaround is unbounded whack-a-mole.
Impact
Agent-reliability: the agent can have the answer in the vault and still deny it, purely because it over-specified its own search with a tag phrase the page doesn't carry. This is a correctness/trust issue, not just an eval artifact.
Possible directions (not prescribing)
- Treat model-attached
tags as a soft/OR filter (rank/boost) rather than a hard AND gate, or fall back to the untagged query result set when a tag-filtered search returns empty.
- Normalize space/hyphen/multiword tag variants when matching (
tags.py:normalize_tag currently only lowercases).
- Or steer the tool description to discourage the model from self-attaching speculative tags.
Context
Found while authoring the #528 behavioral suites (source_grounding). The flaky source_grounding case that depended on this path was dropped from that suite (documented there) until this is fixed. The #531 per-turn eval diagnostics (retrieved_candidates: [], the self-attached-tags tool-call args) were what made the root cause visible.
Summary
vault_search'stagsfilter uses exact-string AND-logic (all attached tags must match a page's frontmatter tags). The agent frequently self-attaches an inventedtagsfilter to avault_searchcall — tags derived from the query wording that no page actually carries — which then AND-zeroes an otherwise-good substring/semantic hit. The model reads the empty result as "the page doesn't exist" and hedges/hallucinates absence instead of grounding in a page that is right there.#674("make vault_search's tags-only mode callable") did not fix this interaction.Evidence (surfaced by the #531 eval diagnostics, PR #)
An eval seeded a vault page
incident-escalation.md(content: "page the on-call engineer via Nightwatch, post in #owl-bridge"). Across real runs the model issued:vault_search {"tags": ["P1","incident","on-call","notification"], "query": "P1 incident on-call notify"}→mode: substring, results: []tags: [incident, on-call, paging, escalation, notification, P1]to the page):vault_search {"tags": ["incident response","on-call","notification"], "query": "..."}→results: []— because "incident response" (two words) isn't an exact tag on the page, and AND-logic zeroes the whole match.Response both times: "I don't have any information … I searched the vault and couldn't find any relevant documents." — a false negative; the page was present.
Adding frontmatter tags to the page only papers over the specific phrases anticipated; the model invents new tag phrases each run, so the tag-enumeration workaround is unbounded whack-a-mole.
Impact
Agent-reliability: the agent can have the answer in the vault and still deny it, purely because it over-specified its own search with a tag phrase the page doesn't carry. This is a correctness/trust issue, not just an eval artifact.
Possible directions (not prescribing)
tagsas a soft/OR filter (rank/boost) rather than a hard AND gate, or fall back to the untagged query result set when a tag-filtered search returns empty.tags.py:normalize_tagcurrently only lowercases).Context
Found while authoring the #528 behavioral suites (source_grounding). The flaky
source_groundingcase that depended on this path was dropped from that suite (documented there) until this is fixed. The #531 per-turn eval diagnostics (retrieved_candidates: [], the self-attached-tags tool-call args) were what made the root cause visible.