Saltar al contenido principal
Versión: 0.16.1

Knowledge base

An agent forgets everything when a session ends, except what it wrote down. The kit gives every agent with a knowledgeDir a built-in way to keep its notes: an interlinked wiki of pages, with rules in the system prompt, skills to maintain it (the "LLM wiki" pattern) and tools of its own to reach it. Originals the agent works from stay apart, in sourcesDir.

Turning it on​

const config: BaseSessionConfig = {
mode: "guided",
projectDir: workspace,
knowledgeDir: path.join(workspace, "knowledge"),
sourcesDir: path.join(workspace, "sources"), // optional
};

With knowledgeDir set, and unless the spec says knowledgeBase: false:

  • the agent gets the knowledge_* tools (an MCP server, knowledge) and reaches the knowledge base only through them: the file tools can't read, write or search knowledgeDir (the file scope says so, pointing to the tools);
  • a "Knowledge base" section is appended to the system prompt, with the page types and the working rules;
  • the knowledge plugin ships with the kit and is loaded: three skills and three commands.

The file tools stay for the originals (Read, Glob, Grep on sourcesDir) and for extraWritableDirs (Write, Edit too). An agent with only a knowledgeDir has no file tools at all.

Why tools and not files​

The agent works on pages, not files: a page is identified by its type and slug, concept/spring-tides, and links between pages use that id. So the storage can change underneath (markdown files today; a database or a vector store, see Knowledge store) without touching the tools, the prompt or the skills. And the wiki's rules are kept by code: the index is generated, backlinks are computed, links must resolve, pages are never deleted or renamed.

It also saves work. On a sample knowledge base of 33 pages, a /knowledge:lint took 66 tool calls, 175 seconds and 469k input tokens with the file tools, and 13 to 18 calls, about a minute and 200-250k tokens with these tools; an ingest went from 20 calls to 13-15, and both cost a third to two thirds less.

The tools​

ToolWhat it doesPlan mode
knowledge_indexThe catalog: every page, one line each (title, id, what it is), by sectionAllowed
knowledge_search(query)Pages matching words in their title, aliases or content, best first, with the line that matchedAllowed
knowledge_read(page)A page: its fields, its content (links as ids) and the pages that link to it; or "overview"; or "log", the latest entries of the operation log, newest firstAllowed
knowledge_create(type, slug, title, content?, fields?, also?)A new page; without content, the type's template. also creates more pages in the same call, which may link to each other: all or noneDenied
knowledge_edit(page, oldText, newText, fields?)Changes one fragment, unique in the pageDenied
knowledge_rewrite(page, content, fields?)Replaces a page's whole content, keeping its id and the links to it; or the "overview"Denied
knowledge_supersede(page, by, reason?)Marks a page superseded by another, with a notice at its topDenied
knowledge_retire(page, reason)Takes a page whose knowledge was wrong out of the index and the search (kept, restorable), after the person approvesNot offered in autonomous mode; denied
knowledge_log(operation, what, pages?)Adds an entry to the log, dated todayDenied
knowledge_checkThe mechanical problems in one call (see below)Allowed

fields is a list of frontmatter fields to set, [{ "name": "aliases", "value": "king tides" }] (value: null removes one). A summary's file is its original relative to sources/; the store records the original's hash, so list_sources reports it as changed if it changes later.

Pages link by id: [Spring tides](concept/spring-tides). A link to a page that doesn't exist is refused with the reason, so the agent creates it first, or in the same call with also (a summary and the new concepts it feeds usually link to each other). Backlinks aren't written by the agent: knowledge_read returns what links to a page.

knowledge_create without content returns the page type's template; the agent fills it and calls again. The kit's types and their templates:

TypeWhat it holdsFields
summaryOne per ingested source: what it says, key points, the pages it feedsfile or url, ingested
conceptOne idea: definition, explanation, connections, sourcesaliases
entityA concrete thing: a system, a component, an organization, a documentkind, aliases
synthesisAn answer worth keeping: a comparison, an analysis, a reportquestion

Besides the pages there's the overview, a living synthesis of the whole knowledge base, read and rewritten as "overview", and the log of operations, written with knowledge_log and read as "log" (the latest ten entries, newest first: what was done last, and when).

What knowledge_check finds​

  • broken links (to pages that don't exist, or relative links to missing files; a link to the overview, index or log file is fine when the file exists);
  • orphan pages (nothing links to them; summaries and syntheses aside, which the index reaches);
  • links to retired pages;
  • summaries whose original is gone;
  • with a sources folder: originals that are new (not ingested), changed after their ingest, or missing, and the passages that cite a retired original.

The index and backlinks can't drift, so there's nothing to check there.

Your own page types​

An agent with its own kinds of notes (a course's topics and activities) declares them, and they work like the kit's four: the same tools, in the index under their own section, with their own template and fields.

const spec: AgentSpec<Config> = {
// …
knowledgePageTypes: [
{
type: "topic",
dir: "", // at the knowledge folder's root
indexSection: "Topics",
description: "A topic of the course: what it covers and the students' mastery of it.",
template: "## Goals\n- <What the students learn>\n\n## Sessions\n- <Plan>",
indexFields: ["mastery"], // shown in the index line: (mastery: 3)
},
{ type: "activity", dir: "activities", indexSection: "Activities", description: "A class activity.", template: "## Steps\n…" },
],
};

The description reaches the model in the prompt section and in knowledge_create's description, so the agent knows when to create one. A type with dir: "" keeps its pages at the root of the knowledge folder, telling them apart by their type field. A declared type with the name of a kit's type replaces it.

On disk​

The kit's store keeps the layout the knowledge base always had, so an existing one works as is:

knowledge/
├── index.md the catalog, generated after every change
├── log.md the operation log
├── overview.md the living synthesis
├── summaries/<slug>.md one page per ingested source
├── concepts/<slug>.md one page per idea
├── entities/<slug>.md one page per concrete thing
├── syntheses/<slug>.md answers worth keeping
└── <slug>.md pages of a declared type with dir: ""

Each page is markdown with a YAML frontmatter (type, title, the fields, updated); links are stored as relative paths, so the files read well in an editor or on GitHub, and come back to the agent as ids. The agent creates the pages as it goes; you don't need to create anything but the folder.

The rules the agent follows​

The prompt section tells the agent, among other things:

  • start from knowledge_search or knowledge_index, then read only the pages the task needs;
  • link by id; change a page by fragment; never delete or rename one: supersede or retire it;
  • log each operation when it's done;
  • every claim is traceable to a summary page, an original, or clearly labelled web content;
  • contradictions are kept with their attribution, not overwritten;
  • write pages in the language of the conversation.

Skills and commands​

SkillWhat it does
knowledge:knowledge-ingestIngest one source: its summary page, the concept and entity pages it touches, and the log; and what to do when an original was wrong or replaced.
knowledge:knowledge-queryAnswer a question from the knowledge base, citing its pages, filing the answer back as a synthesis when worth keeping.
knowledge:knowledge-lintHealth-check: knowledge_check for the mechanical problems, then duplicates, missing pages, contradictions and provenance.
CommandWhat it does
/knowledge:ingest <files or topic>Ingest the given material, or every original not ingested yet.
/knowledge:query <question>Answer from the knowledge base.
/knowledge:lintCheck the whole knowledge base, fix what's mechanical, report the rest.

If your spec lists its skills, these three are added automatically.

Sources: originals kept as obtained​

sourcesDir holds the material the agent works from: files the person drops in, and files the agent saves there. The agent can read and search it but never write or edit it: the file scope denies it, with a message pointing to the notes folder instead.

The agent keeps it with the kit's tools (server sourceFiles), never with the file tools:

ToolWhat it doesModes
list_sourcesEvery original with its status, type, size, pages (PDF) or slides (PPTX), provenance, the version it replaces and its summary pagesAll, plan included
extract_textA DOCX, PPTX or XLSX original as markdown, which Read can't readAll, plan included
save_to_sourcesCopies a file from this run's folder inAll but plan
download_to_sourcesDownloads an original from an http(s) URL straight inAll but plan
request_fileAsks the person for a file and copies it inNot autonomous, not plan
retire_sourceTakes a wrong or superseded original out, after the person approvesNot autonomous, not plan

Status of each original​

list_sources tells the agent what to do next:

StatusMeaning
newNo summary page points to it: ingest it. Files the person copies in by hand show up here.
ingestedA summary page points to it (its frontmatter file:), and it hasn't changed since.
changedIt changed after its ingest (the person replaced it by hand): update its summary.
missingThe kit knew it, but the file is gone (deleted by hand): its summary points nowhere.
presentThere's no knowledge folder to compare with.

The kit keeps the bookkeeping in a manifest inside the folder, sources/.agent-kit/sources.json, where the file tools can't write: each original's hash, size, provenance (from the run, a URL, the person, or copied by hand) and the hash it had when a summary page first pointed to it. A PDF's pages and a PPTX's slides are counted without parsing them, so the agent can read a long one in parts.

Adding originals​

save_to_sources({ source: "downloads/slides.pdf", destination: "topic-3/slides.pdf" })
download_to_sources({ url: "https://example.com/syllabus.pdf", destination: "topic-3/syllabus.pdf" })
request_file({ description: "The official syllabus of the module, to build the calendar from it" })
  • save_to_sources takes source relative to this run's folder (runDir), where a browser or another tool typically downloads files; the file tools can't reach it. It tolerates accented file names in a different Unicode normalization (a browser download on macOS, say).
  • download_to_sources downloads up to 50 MB over http or https, without the content going through the model's context. A web page is also kept as its main content in markdown next to it (web/rules.html and web/rules.md), to quote it literally and read it again; WebFetch only returns a summary. That needs three optional libraries in your agent, npm install @mozilla/readability linkedom turndown; without them only the HTML is kept, and the tool says so.
  • request_file shows the person a panel with the description; they give a path (dragging the file into the terminal pastes it) or press Enter if they don't have it. It's copied with the person as its provenance.
  • destination is relative to sourcesDir; hidden folders are the kit's.
  • Nothing is ever overwritten: an existing destination is an error asking for another name.
  • A file identical to one already there isn't copied again: the tool returns that one's path.
  • A new version goes under a new name with replaces set to the old one (topic-3/slides-v2.pdf replacing topic-3/slides.pdf); both are kept and the manifest links them.

Read reads PDFs and images, so a saved original of those kinds is readable right away. It can't read DOCX or PPTX (confirmed: it refuses them as binary files); extract_text reads them, and XLSX:

extract_text({ source: "topic-3/slides.pptx", from: 1, to: 10 })
  • DOCX: headings, paragraphs, lists and tables.
  • PPTX: a section per slide, its title and text as a list, and its speaker notes, which often carry the explanation; from/to pick slides of a long deck (list_sources gives the count).
  • XLSX: a table per sheet, up to 200 rows (the rest are counted).
  • Images are left out, and counted.

It needs the optional mammoth, fflate and turndown libraries (see Installation); without them it says what to install. Customize save_to_sources' description for your domain with saveToSourcesDescription in the spec.

Retiring an original​

An original that was wrong (the wrong course's slides) or that a better one replaces is taken out with retire_source, never deleted:

retire_source({ source: "topic-3/slides.pdf", why: "replaced", reason: "a newer edition", replacedBy: "topic-3/slides-v2.pdf" })
  1. The person approves it in a panel; rejected, nothing changes.
  2. The file moves to sources/.agent-kit/retired/, and the manifest records why. Deleting it for good is the person's, by emptying that folder.
  3. Its summary page is marked: status: retired and a notice not to rely on it, if it was wrong; status: superseded with a link to the replacement's summary, if it was replaced.
  4. The tool reminds the agent to update the index and fix the pages that cite it; the knowledge-ingest skill says how.

The plan gate denies every tool here but list_sources and extract_text, and request_file and retire_source don't exist in autonomous mode.

With the file tools instead​

knowledgeTools: "files" keeps the knowledge base as it was before the tools: the file tools on knowledgeDir, the rules about index.md, links and the log in the prompt, and a fourth skill with the page templates (knowledge:knowledge-pages). Same layout on disk, so an agent can switch either way.

const spec: AgentSpec<Config> = { /* … */ knowledgeTools: "files" };

Your own rules instead​

An agent that wants plain notes, or rules entirely its own, turns the built-in knowledge base off and keeps knowledgeDir for the file tools:

const spec: AgentSpec<Config> = {
buildSystemPrompt: (config) => `${loadPrompt("system.md")}\n\n${myNotesRules(config)}`,
// …
knowledgeBase: false,
};

The pieces are exported to reuse them selectively: knowledgePromptSection(projectDir, knowledgeDir, sourcesDir?, { tools?, pageTypes? }), knowledgePluginRoot("tools" | "files"), and the store and its tools (see Knowledge store).