Knowledge store
The knowledge base's tools work on a KnowledgeStore, never on files. The kit ships one over markdown files; an agent can plug in another one (a database, a vector store) and the tools, the prompt and the skills stay the same.
The kit's store
createFileKnowledgeStore(knowledgeDir, { pageTypes? }) keeps pages as markdown files in the layout the knowledge base always had (see On disk). buildSessionOptions() creates it for you, with spec.knowledgePageTypes, and returns it as knowledgeStore, so a host can read the knowledge base too (to show it in a desktop app, say):
const { options, knowledgeStore } = await buildSessionOptions(config, runDir, spec);
const topics = (await knowledgeStore?.list())?.filter((page) => page.type === "topic");
It's usable on its own as well, in a script or a test:
import { createFileKnowledgeStore } from "@falkenslab/agent-kit";
const store = createFileKnowledgeStore("course/knowledge");
console.log(await store.index());
const report = await store.check();
The interface
interface KnowledgeStore {
types(): readonly PageType[];
list(): Promise<PageInfo[]>; // every page but the retired ones
read(id: string): Promise<KnowledgePage | null>; // with linkedFrom: the pages that link to it
create(type: string, slug: string, title: string, content: string, fields?: FieldChanges): Promise<string>;
createMany(pages: readonly NewPage[]): Promise<string[]>; // links among them allowed; all or none
edit(id: string, oldText: string, newText: string, fields?: FieldChanges): Promise<void>;
rewrite(id: string, content: string, fields?: FieldChanges): Promise<void>;
supersede(id: string, by: string, reason?: string): Promise<void>;
retire(id: string, reason: string): Promise<void>;
search(query: string, limit?: number): Promise<SearchHit[]>;
index(): Promise<string>; // the catalog, linked by id
log(operation: string, what: string, pages?: readonly string[]): Promise<void>;
recentLog?(limit?: number): Promise<string[]>; // optional: the latest log entries, newest first
check(): Promise<CheckReport>;
overview(): Promise<string>;
writeOverview(content: string): Promise<void>;
}
What a store must keep, whatever it stores the pages in:
- Ids are
type/slug, and links in content are[text](type/slug): return them that way fromread()andindex(), whatever you keep internally (the kit's store writes file links inindex.mdon disk, but the tools get ids).parseId()andlinkedIds()are exported to help. - Links must resolve:
create,createMany,edit,rewriteandwriteOverviewrefuse a link to a page that doesn't exist, with a message the model can act on (the tools pass errors through as they are). - Pages are never deleted or renamed.
supersedeandretiremark them (fields.status:supersededorretired); a retired page leaveslist(),index()andsearch(), butread()still returns it. editreplaces exactly one occurrence, and fails if there's none or several.recentLog()is optional: without it,knowledge_read("log")says the store can't show its log.check()returns broken links, orphans and links to retired pages.- A summary's
ingestedis the store's: set when it's created or rewritten, never taken from the caller. Itsfileis kept as given. A store knows nothing of the sources folder (see Knowledge base and sources).
BUILT_IN_PAGE_TYPES are the kit's types (summary, concept, entity, synthesis, preference) with their templates; a store gets the agent's declared ones too, and should treat a page's type as a label, so it can hold any type.
Plugging in your own
import type { AgentSpec, KnowledgeStore } from "@falkenslab/agent-kit";
import { createPgKnowledgeStore } from "./pgStore.js"; // yours
const spec: AgentSpec<Config> = {
// …
knowledgeStore: (config) => createPgKnowledgeStore(process.env.DATABASE_URL!, { pageTypes: myTypes }),
};
With knowledgeStore, the kit doesn't touch knowledgeDir's files; the knowledge extension still needs knowledgeDir set (it keeps the file tools out of that folder).
A vector store usually keeps the curated pages as the source of truth and indexes them for search(): similarity search on embeddings of each page (or each section), with the same SearchHit result. Anthropic has no embeddings API; Voyage AI is the usual choice, and local options exist (LanceDB or sqlite-vec with a local model). index() and check() don't change.
Wiring the tools yourself
A host that builds its own session options gets the same tools with createKnowledgeServer(store, options):
import { createKnowledgeServer } from "@falkenslab/agent-kit";
mcpServers: {
knowledge: createKnowledgeServer(store, { runDir, interactive: true }),
},
interactive adds knowledge_retire, which asks a person first; leave it off where there's nobody to ask. Name the server knowledge, so the plan gate, the step gate and the tool labels recognize its tools.