Skip to content

vault_search: model-self-attached tags + AND-logic → false-empty results (hallucinated absence) #688

Description

@lmorchard

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions