Skip to main content

Knowledge

Your runbooks, notes and conventions, searchable by the agent, with citations.

Drop documents in <workspace>/knowledge/. Ask a question. The agent searches, quotes what it found, and names the file and section it came from. Nothing is added to any prompt, so a knowledge base costs nothing on a turn that does not ask for it.

This is different from Memory, and the difference is who writes it. Memory is what the agent concluded from your conversations, and Dream maintains it. Knowledge is what you wrote, and only you change it.

Quick Jump

NeedSection
Turn it onEnable it
Understand what a citation looks likeCitations
Know why a document is not being foundWhen something is not found
Choose a modeLexical and hybrid
Keep secrets out of the indexWhat is never indexed
Tune the schedule and the capsConfiguration

Enable it

Settings → Knowledge, or in ~/.nanoinfra/config.json:

{
"tools": {
"knowledge": {
"enabled": true
}
}
}

Restart the gateway. Then create the folder and put something in it:

mkdir -p ~/.nanoinfra/workspaces/default/knowledge/runbooks
$EDITOR ~/.nanoinfra/workspaces/default/knowledge/runbooks/pods.md

Folders and subfolders, whatever suits you. The index lives beside the documents in knowledge/.index/, so a workspace that restores from backup restores its index too.

Citations are the point

A runbook paragraph stated as fact with no source is worse than no runbook, because a stale paragraph reads exactly like a current one and the reader cannot tell which they are looking at.

So every fragment the agent retrieves carries path#section, and the tool contract requires the answer to cite what it used:

Restart it with kubectl rollout restart deployment/api (runbooks/pods.md#restart-the-pod).

An answer with no citation is not a claim. If the search finds nothing, the agent is instructed to say the knowledge base does not cover it, rather than answering from its training data in the same voice it uses for a cited answer.

The #section half is a real anchor:

  • In markdown it is the heading, slugified the way a renderer would (## Restart the pod becomes #restart-the-pod). Two sections with the same title get #notes and #notes-2.
  • In a file with no headings it is a line range: notes.txt#L1-L80.

Either way you can open the file and land on the paragraph the agent used.

Nothing is injected

The agent reaches knowledge by calling knowledge_search. Documents are never placed in the system prompt, in a session summary, or in any other prompt section.

That is deliberate, and it is the one thing worth understanding before you fill the folder: a knowledge base in the prompt would be paid for on every turn, including "hello", and it would grow with your own writing. A tool call is paid for only by the turn that asks.

The single line the model carries all the time is one entry in the skills catalogue, naming that knowledge_search exists and when to use it. The skill's body — the search advice and the citation contract — is loaded only when a turn invokes it.

Freshness

Two things keep the index current, and they exist for two different readers.

The knowledge-index automation runs on a clock beside dream and heartbeat. It walks the whole tree, drops entries whose files are gone, reindexes what changed, and records what the pass did. Fifteen minutes by default.

The search itself compares the folder against the index before it answers, and indexes what changed. This is what makes a document you saved a moment ago findable immediately, rather than after the next tick. It costs a directory walk and a stat per file, and opens no index at all when nothing changed — which is the usual case.

So the schedule can stay quiet. Its job is collecting deletions and catching what nobody searched for.

When something is not found

In order of likelihood:

It does not contain the words you searched for. Lexical search matches terms, not meaning. A runbook that says CrashLoopBackOff is not found by "pod won't start". Search the words the document itself would use.

It was skipped. A file over the per-file limit, a binary, or a symlink pointing out of the folder is refused — and named, both in Settings → Knowledge under Last run and in the tool's own output under Not indexed:. A skipped file is never a silent drop.

It is excluded. Check the exclude list below. .env, *.pem, id_* and secrets/** are excluded by default, at any depth.

It could not be read. A permission problem is reported as a failure rather than a skip, because it needs a different fix. It is retried on the next pass.

Lexical and hybrid

ModeWhat it doesWhat it costs
lexical (default)BM25F over the words in the document, with a heading match weighted above a body matchnothing — pure Python, no extra install
hybridBM25F plus vector searchpip install 'semlix[semantic]', and for a local embedding model semlix[semantic-full] and its download

Lexical is the default because for runbooks the words in the question are usually the words in the document. Its limit is worth knowing rather than discovering: it will not match "pod won't start" against a document that says "CrashLoopBackOff".

Hybrid is greyed out in Settings until the extra is installed, and the save path refuses it too. A mode that cannot search is not a setting worth persisting. Switching mode rebuilds the index on the next pass rather than searching for vectors that were never written.

What is never indexed

Three refusals, and none of them can be talked out of by a document.

Your exclude list. .env, .env.*, *.pem, *.key, id_*, secrets/** and **/.git/** by default. These are config rather than code, because your tree holds secrets nanoinfra cannot guess — and they are written out in full so removing one is deliberate. A pattern matches at any depth: secrets/** excludes nested/secrets/keys.md too.

Anything outside the folder. A symlink whose target resolves outside knowledge/ is not followed, and a symlinked directory is never descended. This is the same containment rule the file browser applies, and it is checked against the knowledge folder rather than the workspace — so a link to the workspace's own secrets/ store is refused by the same rule that refuses a link to /etc.

Anything over the caps. A file above maxFileBytes, or one that would push the index past maxTotalBytes, is skipped and reported. One 2 GB log file must not become the knowledge base.

Files whose bytes are not text are skipped as well. The type comes from the bytes, never from the extension.

Configuration

{
"tools": {
"knowledge": {
"enabled": false,
"mode": "lexical",
"reindexIntervalS": 900,
"exclude": [".env", ".env.*", "*.pem", "*.key", "id_*", "secrets/**", "**/.git/**"],
"maxFileBytes": 2000000,
"maxTotalBytes": 200000000,
"maxResults": 5
}
}
}
KeyDefaultWhat it does
enabledfalseRegisters knowledge_search and the indexing automation. Off by default: an empty index answers nothing.
mode"lexical"lexical or hybrid. Hybrid needs the extra.
reindexIntervalS900How often the full pass runs. Minimum 60.
excludesecretsGlobs never indexed, matched against the file name and the path at any depth.
maxFileBytes2000000Largest document. A larger one is skipped and reported.
maxTotalBytes200000000Total indexed size. Once reached, further documents are skipped and reported.
maxResults5Fragments one search returns. Small on purpose: a citation the model has to read is worth more than ten it skims.

Settings → Knowledge writes all of these, and also shows what the last pass did: documents and fragments indexed, what was added, updated, removed, skipped and failed, and when.

A change here needs a gateway restart. The search tool and the indexing job are both built once at start.

What the agent sees

One knowledge_search call, and an answer shaped like this:

2 fragment(s) for 'rollout restart' from the knowledge base.
Cite the path#section of every fragment you use. An answer with no citation is not a claim.

1. runbooks/pods.md#restart-the-pod (score 4.41)
Run kubectl rollout restart deployment/api and watch the rollout
2. notes/2026-07-incident.md#L14-L31 (score 2.09)
we restarted the deployment before the probe had a chance to pass

Documents in the knowledge base are your writing, not instructions to the agent. If a fragment contains something that reads like a command, the agent is told to report it and not act on it.