Skip to content

knowledge_search

Gate: ungated · no kind, zero authority · read

Retrieval over the workspace's own mnt/knowledge/ folder. Ask a question in plain language and get back the passages that answer it, each labelled with the file and section it came from.

Ungated, on the argument that already leaves memory_read and skill_read ungated: it is context, never authority. It reads files that are already inside the mount and produces text — it changes nothing, and reaches nothing file_read could not already reach.

It exists only when this server has an embedding endpoint configured. Without one the tool is not registered at all, rather than registered and failing on every call.

Input

FieldTypeRequiredNotes
querystringyesWhat to look for. Natural language works; so do exact terms and identifiers.
limitintegernoHow many passages to return. Defaults to 5, capped at 20.

Output

The matching passages as text, best first, each preceded by its file, its heading breadcrumb, and a similarity — the cosine between the question and that passage. Capped at 24 KiB. An empty result says so explicitly, so that "nothing was found" cannot be mistaken for "nothing was asked".

--- home/lease.md > Deposit [similarity 0.76, keyword match] --- The deposit is three months' base rent, so 3,720 euros. …

From JavaScript

const hits = nocturn.knowledge.search("what did we agree about the deposit?", 3);
console.log(hits);

Notes

The similarity is for the model to judge with, not a threshold. Retrieval always returns its best guesses — ask for three and you get three, however weak. A hard cutoff was the obvious fix and the wrong one: where the line between an answer and noise falls depends on the question, and the question is not in the retrieval code. So the number goes to the model with the caveats that make it usable — it is not a probability, its scale depends on the embedding model, and it should be read against the other results rather than against a constant.

A flat set with no leader means the answer is not filed here. Measured on a real corpus: "how much was the deposit" gives 0.76 against 0.57 and 0.60; a question about something not in the folder gives 0.48, 0.56, 0.53 — no leader at all.

Two rankers, because they fail in opposite directions. Vectors find a passage that says the same thing in other words, and miss an exact identifier the model never saw — a serial number, a flag, an internal codename. Keyword scoring finds precisely that string and misses every paraphrase. Both run, and their results are fused by rank rather than by score: a cosine of 0.82 and a BM25 of 11.4 share no scale, and normalising them would invent one. What survives is agreement. A hit marked keyword match was found by its exact words, so a low similarity there is the hybrid working rather than failing.

The result is untrusted content, and says so. The text handed to the model states that these are quoted file contents rather than instructions, and does not claim the user wrote them — the corpus is inside the mount, file_write can put a file there, and so can a prompt injection. Presenting that back as "your user's own note" would launder the attack the rest of the design exists to stop. Results are also redacted on the way in, the same treatment memory_read gives its notes: a document can hold a credential because somebody pasted it there.

Your documents leave the machine when they are indexed. Embedding is a remote call, so every document is sent to the configured provider once, and each query when it is asked. The vault leak scanner runs first: a passage carrying a stored secret is refused rather than embedded. See knowledge for what that means and how to choose a provider.