Grounded passage search (RAG) scoped by a spell
search_passagesTHE DEFAULT TOOL FOR QUESTION-SHAPED QUERIES ("wie/warum/was hilft bei X?", "how do I…?"): retrieves the best-matching fulltext passages from the corpus and returns them with citations (source resource, page, heading, source URL) — answer the user FROM the passages and cite each source. (For discovery intent — "finde/empfiehl Materialien" — use search_content instead, or afterwards to offer browsable links.) Keep question topic-only. Ranking is hybrid keyword+vector, so phrase the question as a topical statement that names the subject and the target group ("Friedenserziehung in der Grundschule: Einstieg in das Thema Frieden mit Kindern"), not as the user's literal sentence ("Wie kann ich …?"). Results are capped at two passages per document; a passage with only a snippet and no text has no fulltext yet — say so instead of guessing. Educational-resource passages come only from openly licensed resources (CC0, Public Domain, CC BY, CC BY-SA); other content types are not license-filtered. Scope is required but simple: with no source restriction from the user, pass the content kinds (e.g. kinds:[30142] for educational resources, [30040,30041] for publications, [30023] for articles). Route source restrictions ("nur Content von X") into the scope parameters: a metadata publisher (most organisations — resolve_publisher finds the exact spelling) goes into search as a QUOTED field filter, e.g. search:'publisher.name:"LEHRE LADEN"' (unquoted multi-word names match nothing); a Nostr signing account (resolve_author → pubkey) goes into authors. A published grimoire spell (kind 777, nevent or event id) can replace inline scope entirely; the response carries the canonical spell for whatever scope was used — publish it (e.g. via grimoire) to make the scope reusable. Spells may use $me/$contacts; they resolve to the calling user (pass me if the transport is anonymous). Fails rather than widening scope: an empty scope, unreachable relay (relay_unreachable — tell the user to retry), or unreachable index is a typed error, never a silently unscoped search.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| me | No | Who $me refers to (npub or hex). Defaults to the calling identity. | |
| tag | No | Inline scope: one tag filter, e.g. {letter:"h", values:["<community-pk>"]}. | |
| kinds | No | Inline scope: content kinds (e.g. 30142). | |
| limit | No | Passages to return (1-25, default 10). | |
| since | No | Inline scope: absolute Unix seconds or relative (7d, 1mo, now). | |
| spell | No | Published spell: nevent, note id, or 64-hex event id. | |
| until | No | Inline scope: absolute Unix seconds or relative. | |
| relays | No | Relay selection (list_relays set), by full URL or short name (e.g. "oersi", "sodix"). First mapped relay is used. | |
| search | No | Inline scope: NIP-50 term selecting the EVENTS in scope (distinct from question). Supports field filters; quote multi-word values: publisher.name:"LEHRE LADEN". | |
| authors | No | Inline scope: Nostr event-author pubkeys (hex/npub/$me/$contacts) — resolve names via resolve_author. NOT for metadata publishers; those go into `search`. | |
| question | Yes | The question or topic to find grounding passages for. |