AIP-10: KNOWLEDGE.md — agentknowledge/v1 (LLM-maintained wiki)
A filesystem-first knowledge-base format where an LLM curates, links, and lints a markdown wiki on top of immutable raw sources, turning agent knowledge into a compounding artifact instead of a per-query retrieval miss.
| Field | Value |
|---|---|
| AIP | 10 |
| Title | KNOWLEDGE.md — agentknowledge/v1 (LLM-maintained wiki) |
| Status | Draft |
| Type | Schema |
| Domain | knowledge.sh |
| Doctypes | knowledge.entry/v1 (curated), knowledge.source/v1 (immutable), knowledge.workspace/v1 (manifest + view) |
| Requires | AIP-1, AIP-2 |
| Composes with | AIP-3 (skills), AIP-6 (companies), AIP-7 (governance), AIP-9 (operators), AIP-26 (code-workspace refs), AIP-27 (typed refs) |
| Reference Impl | @agentproto/knowledge |
Abstract
agentknowledge/v1 defines a markdown-based wiki format that an LLM owns
end-to-end. Three doctypes cooperate: raw sources stay immutable
(knowledge.source/v1), curated entries are rewritten by the agent on every
ingest (knowledge.entry/v1), and a workspace manifest declares the wiki's
shape — entity types, lint rules, retention, curation policy — in a
machine-parseable file (knowledge.workspace/v1, written as KNOWLEDGE.md).
The same workspace doctype, used recursively via extends:, also expresses
per-context views: an operator (AIP-9), a company
(AIP-6), or a skill (AIP-3) can ship its OWN
KNOWLEDGE.md that adapts the base workspace for its lens — different entity
focus, tone, conflict-resolution rules — without forking the wiki itself. A
sibling free-form prose file (AGENTS.md) is RECOMMENDED for human readers,
maintained alongside the canonical machine config. Together these turn agent
knowledge into a compounding, composable artifact instead of a stateless RAG
retrieval, and make the resulting knowledge base portable across runtimes.
Motivation
Most agent knowledge today lives in one of two places: an opaque vector store rebuilt at query time (RAG), or a vendor-specific "memory" object that doesn't survive across runtimes. Both treat knowledge as a retrieval problem. Neither produces an artifact a human or a different agent can read, audit, or fork.
Andrej Karpathy's "LLM Wiki" pattern (April 2026) reframes the problem: treat raw sources as source code, treat the LLM as a compiler, and let it produce a structured wiki — a compiled knowledge artifact that compounds across ingests. AIP-10 codifies that pattern as a portable file format so that:
- A wiki built in one runtime can be opened, queried, and extended in another.
- The workspace manifest (
KNOWLEDGE.md) becomes the unit of trade — domain experts ship a workspace shape, runtimes execute it; a sibling human-readableAGENTS.mddocuments intent for readers and reviewers. - Cross-references, contradictions, and provenance live in the files themselves, not in a query-time prompt.
- Different consumers can read the same wiki through different lenses.
An operator focused on research wants Concept entries surfaced first;
the same wiki seen by a sales operator wants Customer and Deal entries.
Rather than fork the wiki per consumer, AIP-10 lets each consumer ship
a small
KNOWLEDGE.mdthat extends the workspace and overrides the bits that matter for its context. The wiki is one; the views are many.
This last point is the structural reason KNOWLEDGE.md is one doctype used
in two modes: a workspace-root manifest at the wiki root, and a view
in any operator/company/skill folder that wants its own lens. Composition is
the same mechanism used by Tailwind presets, designkit overrides, and the
profile registry pattern that shows up across this AIP family — the wiki
ships a base shape, and consumers compose narrower shapes on top.
Prior art: Karpathy's
llm-wiki gist,
AGENTS.md, Anthropic's "Agent Skills" pattern
(AIP-3), the filesystem-first lineage of
AIP-6/AIP-7/AIP-8.
Specification
A conforming agentknowledge/v1 package is a directory tree of four layers:
the workspace manifest, the immutable sources, the curated entries, and the
optional human-readable schema file. Per-context views live wherever the
consumer that owns them lives.
my-wiki/
├── KNOWLEDGE.md # workspace manifest (REQUIRED, root, machine config)
├── AGENTS.md # human-readable schema (RECOMMENDED, prose companion)
├── _index.md # generated catalog (REQUIRED, root)
├── _log.md # append-only activity log (REQUIRED, root)
├── _manifest.json # provenance/dedup manifest (REQUIRED, root)
├── sources/ # raw sources (immutable; LLM reads, never writes)
│ ├── 2026-04-15-paper.pdf
│ └── 2026-04-20-meeting.md
├── entities/ # one page per real-world entity
│ └── andrej-karpathy.md
├── concepts/ # one page per abstract concept
│ └── compounding-knowledge.md
├── summaries/ # one page per ingested source
│ └── 2026-04-15-paper.md
└── timelines/ # optional ordered narratives
└── 2026-q2-research.mdPer-context views live alongside their consumer, not under the wiki root. Conventional locations:
operators/research-analyst/KNOWLEDGE.md # extends ../../my-wiki/KNOWLEDGE.md
companies/acme/KNOWLEDGE.md # extends ../../my-wiki/KNOWLEDGE.md
skills/sales-assist/KNOWLEDGE.md # extends ../../my-wiki/KNOWLEDGE.mdA view's extends: field points to a parent KNOWLEDGE.md (workspace root
OR another view), and appliesTo: binds the view to one or more
operator/company/skill workspace refs. The runtime resolves the chain on
load and exposes the merged effective config to the consumer.
Layer 1 — Raw sources (sources/)
The runtime MUST treat any file under sources/ as immutable. The LLM
reads these files but MUST NOT modify, rename, or delete them. New
sources are added by humans (or upstream automation) and trigger ingest.
Layer 2 — Wiki pages (everywhere except sources/, KNOWLEDGE.md, and AGENTS.md)
Every wiki page is markdown with YAML frontmatter:
---
schema: knowledge/v1
slug: <kebab-case-page-id>
kind: entity | concept | summary | comparison | timeline
title: <human-readable title>
sources: # provenance — refs into sources/
- sources/2026-04-15-paper.pdf
- sources/2026-04-20-meeting.md
refs: # OPTIONAL — AIP-27 Ref[]: what this page
# POINTS AT in other workspaces (a code
# file/symbol in an AIP-26 workspace, a
# page in another wiki). Canonical
# scalar form is AIP-27 compact. See
# "Cross-workspace references (AIP-27)".
- github:agentproto/ts:packages/runtime/src/http-server.ts # code, other workspace
- wiki:platform/http-server # page, other wiki
confidence: 0 .. 1 # OPTIONAL, default 1.0
updated_at: <ISO 8601>
supersedes: [<slug>] # OPTIONAL — earlier pages this replaces
contradicts: [<slug>] # OPTIONAL — pages whose claims conflict
metadata: # OPTIONAL — vendor extensions
<vendor>:
<field>: <value>
---
# <title>
<body — prose, tables, code, headings>The slug is the page's canonical identity: a bare kebab-case token
([a-z0-9-]+, no /), unique within the wiki, equal by convention to the
page filename without its .md extension. It is REQUIRED. A runtime MAY
namespace its internal node identifier by the page's containing directory
(e.g. <dir>/<slug>) for retrieval or graph indexing, but that namespacing is
the runtime's own concern and MUST NOT leak into the frontmatter contract: a
conforming host MUST accept the bare frontmatter slug, MUST NOT require it to
carry a path prefix, and MUST NOT reject a page whose slug equals its path
basename. A runtime that refuses a conformant bare slug — or that forces the
author to omit slug or spell it as a non-kebab path — is non-conforming;
the portable wiki keeps its bare slugs and the runtime derives whatever
internal id it needs from them.
Three reference surfaces exist on a page and MUST NOT be conflated:
[[slug]]body links — intra-wiki cross-references between pages of this wiki. Cross-references between pages of the same wiki MUST use the wikilink syntax[[slug]]or markdown links to relative.mdpaths; the runtime MUST be able to resolve both forms.sources:frontmatter — provenance IN: the rawsources/files this page was distilled FROM (Layer 1).refs:frontmatter — references OUT: what this page is ABOUT / POINTS AT in other workspaces (see Cross-workspace references (AIP-27)).
refs: is OPTIONAL and, when present, MUST be an array of
AIP-27 Ref values in AIP-27 compact form (e.g. github:…,
local:…, git:…, url:…, or the wiki:<wiki-slug>/<page-slug> /
ws://wikis/… spelling for cross-wiki pages). It is DISTINCT from both sources: (raw-source
provenance, where the knowledge came from) and [[slug]] body links
(intra-wiki navigation): refs: is the typed, cross-workspace "this page is
about that thing" edge. A runtime MUST NOT treat a refs: entry as a
provenance source, and MUST NOT require its target to exist inside this wiki.
Cross-workspace references (AIP-27)
The refs: page field carries AIP-27 Ref values so a
knowledge page can point OUT of the wiki: at a code file or symbol in an
AIP-26 code-workspace, at a resource on the web, or at a page
in another wiki. refs: is the typed, machine-resolvable answer to "what is
this page about, elsewhere?" — the edge a graph runtime traverses to walk
code↔knowledge.
Each refs: entry is a base ref — an AIP-27 compact form or object form —
OPTIONALLY carrying an AIP-10-owned #symbol=<name> addressing fragment (see
below). A runtime MUST first strip any #symbol= fragment, then parse the
remaining base ref with an AIP-27-conformant parser, and MUST NOT redefine
that grammar. Any AIP-27 kind is admissible; the kinds a knowledge page uses
in practice are local, github, git, url (code / documents) and the
wiki kind — compact wiki:<wiki-slug>/<page-slug>, URI-spelled
ws://wikis/<wiki-slug>/<page-slug> — for pages in other wikis (see
Cross-wiki references).
Code references (AIP-26 workspaces)
A page distilled from, or documenting, code addresses that code with a
file-collection ref (AIP-27 §Base collections). The code
lives in a DIFFERENT workspace than the wiki, so github: (or a
ws://workspaces/<slug>/… form) that names the other workspace explicitly is
the primary spelling:
# A pr-review knowledge page that is ABOUT the HTTP server it reviewed:
refs:
- github:agentproto/ts:packages/runtime/src/http-server.ts # code in another repo
- github:agentproto/ts:packages/runtime/src/http-server.ts#symbol=serve # a symbol within it
- local:packages/runtime/src/http-server.ts # ONLY in a monorepo (see below)The github/local base bodies are exactly the file addresses
AIP-26 uses for its code.sources[] (github = owner/repo
- repo-relative path;
local= workspace-relative path).local:resolves against the CITING wiki's own workspace root, so it addresses code cross-workspace ONLY when the wiki and the code-workspace share one filesystem root (a monorepo); otherwise usegithub:or thews://workspaces/<slug>/…form, which name the other workspace explicitly.
#symbol=<name> is an AIP-10-owned addressing fragment, NOT part of
AIP-27's grammar. AIP-27 reserves # for its #sha256= suffix and requires
# to be percent-encoded inside path bodies, so a #symbol= fragment is
opaque to a strict AIP-27 parser (it would raise InvalidRefBody, not
silently strip). A runtime MUST therefore STRIP any trailing #symbol=<name>
from the ref string BEFORE handing the remaining, pure-AIP-27-conforming base
body to the parser. A code-aware runtime MAY then resolve the stripped symbol
name to a span inside the file — only AFTER AIP-27 has resolved the file
itself; a runtime that ignores the fragment resolves the whole containing file
(graceful degradation, never an error). The fragment lives entirely in
AIP-10's layer and neither extends nor redefines AIP-27.
Cross-wiki references
AIP-10 today describes a SINGLE wiki, but a refs: entry MAY point at a page
in ANOTHER wiki, via the AIP-27 wiki kind (the wikis → wiki row of
AIP-27 §Reference syntax, a multi-segment body). It has two
equivalent spellings — the compact form (canonical for frontmatter scalars)
and the ws:// URI form — and a host MUST accept both on input:
wiki:<wiki-slug>/<page-slug> # compact — canonical in refs:
ws://wikis/<wiki-slug>/<page-slug> # equivalent ws:// URI spelling# A page in the "product" wiki that is about a page in the "platform" wiki:
refs:
- wiki:platform/http-server # cross-wiki page ref (compact)
- wiki:platform/rate-limiting<wiki-slug> names a wiki the host knows; <page-slug> is that wiki's
Layer-2 page slug. This ref is tenant-local by the AIP-27 mandate (a host
MUST resolve it in the citing wiki's tenant scope and MUST reject
cross-tenant bindings). It is DISTINCT from [[slug]], which stays
intra-wiki: [[slug]] never crosses a wiki boundary; wiki:… always
does.
The cross-wiki ref SYNTAX is normative here; building and traversing the
graph is a RUNTIME concern. Per the Query contract, a
wiki is queryable with file reads alone and a runtime MAY add auxiliary
indices (BM25, embeddings, graph) on top. A runtime MAY therefore index the
refs: edges — code↔knowledge and wiki↔wiki — and expose graph traversal
(this is the spec a graph runtime such as gbrain implements), but the wiki
files remain the source of truth and no index is required for conformance.
Layer 3 — Human-readable schema (AGENTS.md)
A RECOMMENDED root file describing, in prose, how the LLM should curate
the wiki. It exists for human readers and review tooling — it is the
companion artifact to the canonical machine-readable
KNOWLEDGE.md (Layer 4).
Conforming wikis SHOULD ship both: KNOWLEDGE.md for runtimes and
linters to consume programmatically, AGENTS.md for humans to read
during onboarding, review, or governance approval.
Earlier drafts of this AIP made AGENTS.md REQUIRED and treated it as
the schema of record. That role now belongs to KNOWLEDGE.md; the prose
file is downgraded to RECOMMENDED so that automated pipelines can ship
without it, while community spec compatibility (notably
agents.md) is preserved for hosts that want to
co-publish.
When present, AGENTS.md SHOULD contain at least:
- Page conventions — required frontmatter, naming, allowed
kinds, body structure for each kind. (MirrorsentityTypesinKNOWLEDGE.md.) - Ingest workflow — what the LLM does when a new source appears in
sources/: which pages to read, which pages to update, when to create new pages, how to update_index.mdand append to_log.md. - Contradiction policy — how to resolve conflicts (recency,
source authority, observation count) and how to flag unresolved
conflicts via
contradicts. (Mirrorscuration.conflictResolutioninKNOWLEDGE.md.) - Lint rules — which orphans/stale-claims/missing-concepts the LLM
should surface during a maintenance pass. (Mirrors
lintsinKNOWLEDGE.md.)
A host MAY treat AGENTS.md as the source of truth for human-facing
display and KNOWLEDGE.md as the source of truth for programmatic
behaviour. When the two disagree, runtimes MUST prefer KNOWLEDGE.md;
linters SHOULD surface the divergence as a wiki_schema_drift finding so
human authors can re-sync the prose.
Layer 4 — Workspace manifest (KNOWLEDGE.md)
KNOWLEDGE.md is the canonical, machine-parseable workspace manifest.
It encodes everything AGENTS.md describes in prose — entity types,
lint rules, retention, curation policy — into a YAML frontmatter that
runtimes can validate, merge, and diff. The body of KNOWLEDGE.md
remains free-form markdown for any prose the manifest author wants to
ship inline.
The same doctype, knowledge.workspace/v1, is used in TWO modes:
- Workspace-root mode —
<wiki>/KNOWLEDGE.md, noextends. Declares the base shape: what entity types exist, what lints run, what tone the curator agent uses, what retention applies to sources. - View mode —
<consumer>/KNOWLEDGE.md,extends:set to a parentKNOWLEDGE.mdpath. Adapts the base for a specific operator (AIP-9), company (AIP-6), or skill (AIP-3). View mode is the mechanism that lets one wiki serve many lenses without forking.
Frontmatter shape
---
schema: knowledge.workspace/v1
name: <kebab-case-id> # required
title: <human-readable> # required
description: <one-paragraph purpose> # required
version: <semver> # required, the WORKSPACE version
# (bump on shape changes)
# Composition (view mode only)
extends: ../path/to/parent/KNOWLEDGE.md # OPTIONAL — relative path to
# parent; recursive merge
appliesTo: # OPTIONAL — bind this view to
# specific consumers OR dimensions
- ws://operators/<slug> # AIP-9 operator
- ws://companies/<slug> # AIP-6 company
- ws://skills/<slug> # AIP-3 skill
- <dimension>/<value> # dimension ref, e.g.
# region/fr, compliance/gdpr,
# org/acme, tier/exec
# Cross-AIP refs
curator: ws://operators/<slug> # OPTIONAL — AIP-9 operator that
# curates this workspace
governance: <path-or-ref> # OPTIONAL — AIP-7 policy or
# audit binding
# Entity model — what TYPES of entries this workspace recognizes
entityTypes: # array; merge-by-name vs parent
- name: <PascalCase>
fields: [<field>, ...] # canonical fields
icon: <emoji> # OPTIONAL display hint
description: <prose> # OPTIONAL
parent: <PascalCase> # OPTIONAL — extends another
# local type
# Lint rules — what the curator agent checks every maintenance pass
lints: # array; merge-by-id vs parent
- id: <kebab-id> # required, stable
kind: require-source | max-age | min-confidence | broken-ref
| orphan | custom
appliesTo: <EntityType> | "*"
severity: error | warn | info
params: # kind-specific
<key>: <value>
# Source registry behavior
sources:
retention: forever | days:<n>
signing: required | optional | none # composes with AIP-7 signing
hashAlgo: sha256 | sha512 | blake3
authorityDefault: primary | secondary | rumour
# Curation behavior
curation:
tone: <free-form> # e.g. "academic", "sales"
depth: shallow | medium | deep
autoLink: byName | manual | off
conflictResolution: defer | recency | authority
| observation-count | keep-both
newEntryThreshold: <prose> # when to promote a mention to
# a full entry
# Query hints — how consumers should retrieve from this view
queryHints:
preferRecent: true | false
preferAuthoritative: true | false
scopeTo: [<EntityType>, ...] # OPTIONAL — narrow query default
# Display / UX hints (agnostic to runtime)
display:
homePage: <slug> # OPTIONAL — landing entry
defaultGrouping: kind | tag | source
metadata: # vendor extensions, namespaced
layer: # OPTIONAL (view mode) — composition mode
mode: lens | constraint # default lens. See "Layer mode" below.
<vendor>:
<field>: <value>
---
# <body — markdown prose>
Conventional sections in the body include:
- ## Purpose — what this workspace is for, who uses it
- ## Conventions — naming, style, what to avoid
- ## When to extend vs replace — composition guidance
- ## Examples — short snippets of typical entriesComposition semantics
When a runtime loads a KNOWLEDGE.md whose frontmatter declares
extends:, it MUST:
- Walk the parent chain. Recursively load the parent referenced by
extends:, then that parent's parent, until a manifest with noextendsis reached (the workspace root). Maximum chain depth is eight. Hosts MUST detect cycles by tracking visited absolute paths. - Treat both depth overflow and cycle detection as warnings, not
errors. A view whose chain is malformed MUST still load — the
runtime falls back to the local manifest only and surfaces a
knowledge_extends_cycle(orknowledge_extends_depth_exceeded) warning to the consumer's debug surface. - Tolerate a missing parent. If
extends:points to a path that does not exist, the runtime emitsknowledge_extends_missingas a warning and uses the local manifest only. View activation does not abort. - Merge bottom-up. Walk the chain from the workspace root toward the leaf view, merging each manifest into the accumulator using the strategy below.
Merge strategy (child wins on conflicts):
| Field | Strategy | Notes |
|---|---|---|
name, title, description, version | override | Child's identity wins; the runtime exposes both. |
extends | not inherited | Local-only field. |
appliesTo | not inherited | Local-only binding. |
curator, governance | override | Child can rebind. |
entityTypes | merge-by-name | A child entry with the same name replaces the parent's; new names are appended. Subtyping is explicit via parent:. |
entityTypes[].fields | union | Child fields are appended to parent's; duplicates collapsed. |
lints | merge-by-id | Child lint with same id replaces parent's; new ids are appended. |
sources.* | override per leaf field | retention, signing, hashAlgo, authorityDefault each independently override. |
curation.* | override per leaf field | Same shape as sources. |
queryHints.* | override per leaf field | scopeTo is replaced wholesale by child if present. |
display.* | override per leaf field | |
metadata | deep-merge | Recursive merge; vendor namespaces accumulate. |
The runtime MUST expose both the merged effective config AND the resolution chain (ordered list of absolute paths consumed during merge). Consumers use the merged config; tooling uses the chain to explain why a field has the value it does.
Dimension refs
appliesTo accepts, alongside the ws://operators|companies|skills/*
consumer refs, dimension refs of the form <dimension>/<value>:
region/fr, compliance/gdpr, org/acme, tier/exec. A dimension ref
binds a view to a facet of the resolution context rather than a single
named consumer, so one view can adapt the workspace for "every operator
running in France" or "any tier-exec recall". The dimension namespace is
open: hosts register which dimensions they resolve (a host that does not
know compliance/* simply never activates such a view). A view bound to
a dimension the host cannot resolve is inert, not an error; a view bound
to a malformed ref (no /, empty value) emits
knowledge_appliesto_unresolvable.
Layer mode — lens vs constraint
A view declares its composition mode via metadata.layer.mode (default
lens):
lens— the view adapts the workspace and is freely overridable by higher-precedence layers and by guild-local edits. Org house-style, tier tone, regional preferences are lenses.constraint— the view is a floor. Higher-precedence layers and guild-local edits MAYextenda constraint view (add entries, add fields) but MUST NOT shadow, soften, or tombstone its protected entries (its ownentries/*and thelintsit declares). A compliance or legal view (compliance/gdpr,region/frlabour law) ships as a constraint so a downstream org pack cannot silently bury it.
A host MUST surface, per merged field and per resolved entry, whether it
originated from a constraint layer (so a reviewer sees a value is
protected). Two constraint layers that conflict on the same protected
entry are a governance escalation, not a silent child-wins merge — the
host emits knowledge_constraint_conflict and keeps both for review.
Plane-precedence invariant
Composition happens on two planes and they resolve different things; the invariant binds them:
- Manifest-merge plane (
extends/appliesTo, child-wins) resolves the effective shape/lens — entity types, lints, tone, query hints. - Path-shadow plane (the mounted entry tree) resolves entry
content — a higher layer's
entries/x.mdshadows a lower layer's at the same path.
Invariant. The guild-writable (highest-precedence) layer always shadows pack content on the path-shadow plane — EXCEPT a
constraint-mode layer's protected entries, which neither higher packs nor guild edits may shadow or tombstone. They may onlyextend(author additional entries at different paths). A constraint thus overrides ordinary precedence: it is the one case where a lower layer wins.
Tombstone (whiteout)
The path-shadow plane is union + shadow only: a higher layer can
replace a lower entry by re-authoring the same path, but cannot
remove one (e.g. a US guild dropping an inherited region/fr entry).
A higher layer removes a lower-layer entry with a tombstone: a
zero-byte marker file at the sibling path <entry-path>.whiteout
(to drop entries/foo.md, author entries/foo.md.whiteout). A marker
file is used rather than a frontmatter flag so the resolution stays a
pure path operation — hosts need not parse entry bodies to list a
directory. When resolving the mounted tree a host MUST:
- resolve each path top-down (highest-precedence layer first); the first
layer that declares either the entry or its
.whiteoutmarker decides. A real entry → present with that layer's content; a.whiteoutfirst → the path is absent fromreaddir/walkand reads return not-found, as if no layer declared it. - hide
.whiteoutmarkers themselves fromreaddir/walkoutput.
Because resolution is top-down, a higher layer re-authoring a real entry naturally overrides a lower tombstone, and a tombstone only suppresses layers below the one declaring it.
- Constraint entries are non-tombstoneable and non-shadowable. A
constraint-mode layer's protected entries are pinned ABOVE all higher layers, so by precedence neither a higher real entry nor a.whiteoutcan shadow or remove them. A host that detects a higher layer attempting to shadow a protected path emitsknowledge_constraint_conflict; a.whiteouttargeting one emitsknowledge_tombstone_blocked. In both cases the constraint content wins.
Cross-AIP refs
KNOWLEDGE.md is the binding surface where agentknowledge/v1 meets
the rest of the AIP family:
| Field | References | Purpose |
|---|---|---|
curator | AIP-9 operator | Names the operator the host should activate when running ingest, curation, or lint passes against this workspace. |
governance | AIP-7 policy / audit ref | Binds the workspace (or view) to a governance policy. Schema-poisoning mitigations and source-mutation audits flow through this ref. |
appliesTo | AIP-3 skill, AIP-6 company, AIP-9 operator, or a dimension ref (<dimension>/<value>) | A view declares which consumers OR dimensions it adapts the workspace for. Hosts MUST refuse a view whose appliesTo references a non-existent consumer or a malformed dimension ref (knowledge_appliesto_unresolvable). A view bound to a dimension the host does not resolve is inert, not refused. |
extends | another KNOWLEDGE.md | Composition. |
refs (Layer-2 page field) | AIP-27 Ref[] — local / github / git / url / ws://… | AIP-10 is a consumer of AIP-27: a page's refs: field points OUT at code files/symbols in an AIP-26 workspace and at pages in other wikis (ws://wikis/<wiki-slug>/<page-slug>). AIP-10 is also a producer in the AIP-27 registry — the wikis collection row addresses AIP-10 wikis. See Cross-workspace references (AIP-27). |
appliesTo is not inherited. A view binds to its own consumers; a
parent's bindings do not leak into the child. This is the rule that
makes the registry-of-views pattern coherent — every view declares its
own scope.
Workspace mode vs view mode — composability table
| Aspect | Workspace-root mode | View mode |
|---|---|---|
| File path | <wiki>/KNOWLEDGE.md | <consumer>/KNOWLEDGE.md |
extends: | absent | required (otherwise it's a workspace, not a view) |
appliesTo: | absent (a workspace has no single consumer) | OPTIONAL but conventional |
| Effective shape | the manifest as written | merge of the chain, child wins |
| Mutability | edits gated by governance | local edits adapt the lens, do not affect the workspace |
| Use cases | wiki authors, schema designers | operator/company/skill teams who want their own lens |
| Validation | full schema check | schema check + chain validation |
| Lifecycle | versioned with the wiki | versioned with the consumer |
The same knowledge.workspace/v1 doctype, the same file name, the same
schema. Only the location and the presence of extends: distinguish.
Required generated files
_index.md — content catalog. Lists every page (excluding sources/)
grouped by kind, with the slug, title, and a one-line summary
extracted from the page body. The runtime MUST regenerate _index.md
on every ingest.
_log.md — append-only activity log. Every ingest that processes ≥1
source, query that produced a new page, and lint pass MUST append a line
(an ingest that skips every source — see the Ingest contract's idempotency
step — processes nothing, appends nothing, and stays a true no-op):
## [<ISO 8601>] <event-type> | <subject>
- <bullet 1>
- <bullet 2>event-type ∈ manual.
_manifest.json — provenance/dedup manifest. A JSON object mapping every
already-processed source to the pages it produced and the hash it was
processed at:
{
"version": 1,
"hashAlgo": "sha256",
"sources": {
"sources/2026-04-15-paper.pdf": { "contentHash": "ab12…", "slugs": ["compounding-knowledge", "andrej-karpathy"] },
"sources/2026-04-20-meeting.md": { "contentHash": "cd34…", "slugs": ["2026-04-20-meeting"] }
}
}Each entry maps sourceId → { contentHash, slugs }, where sourceId is the
sources/-relative path of the raw source, contentHash is the digest of
that source's bytes computed with the workspace's sources.hashAlgo (Layer 4
KNOWLEDGE.md; default sha256), and slugs is the array of every Layer-2
page the source produced or touched — one source can create or update many
pages (Ingest steps 3–5). The runtime MUST record hashAlgo in the manifest
so a reader can verify a contentHash without re-reading KNOWLEDGE.md. The
idempotency check keys on contentHash (source BYTES) ALONE: editing
KNOWLEDGE.md or AGENTS.md changes no contentHash and so does NOT
re-trigger unchanged sources — re-curation after a schema change is an
explicit operation, never an automatic side effect. The runtime MUST update
_manifest.json in the same transaction as _index.md and _log.md on
every ingest that processes a source.
Ingest contract
When a runtime ingests source S:
- The runtime MUST compute
S'scontentHashwith the workspace'ssources.hashAlgoand lookS'ssourceIdup in_manifest.json. If a manifest entry exists whosecontentHashis unchanged, the runtime MUST skipS— it MUST NOT re-distill the source and MUST NOT create or mutate any page for it. This is the idempotency guarantee: re-running ingest over an unchangedsources/tree is a no-op, and the same source never produces a duplicate page. A source whosesourceIdis absent, or present with a differentcontentHash(the bytes changed), is (re)processed by the remaining steps. - The runtime MUST read
Sand the currentAGENTS.md. - It MUST identify wiki pages affected by
S(entities mentioned, concepts touched, conflicting claims) by reading_index.mdplus the relevant page bodies. - It MUST produce page diffs — minimal markdown patches per affected page — and apply them atomically (all or nothing). Monolithic rewrites of unaffected pages are non-conforming.
- It MUST create new pages for entities/concepts not yet covered.
- It MUST update
_index.md, upsertS's entry in_manifest.json(sourceId → { contentHash, slugs },slugslisting every page created or touched in steps 3–5), and append to_log.md— all in the same transaction. - It SHOULD set
confidenceandsupersedesbased on the schema's contradiction policy. Unresolved conflicts MUST be flagged viacontradicts.
Query contract
Querying a wiki MUST be possible with file reads alone — no runtime DB or vector index is required to be conforming. A runtime MAY add auxiliary indices (BM25, embeddings, graph) on top, but the wiki files remain the source of truth.
Lint contract
A maintenance pass MUST detect:
- Orphans — pages with no inbound links from
_index.mdor other pages. - Stale claims — pages whose
sourcesare all older than a schema-defined threshold and have not been re-confirmed. - Unresolved contradictions — pages with
contradictspopulated. - Broken refs — wikilinks/markdown links pointing to missing pages.
The Broken refs lint (the broken-ref lint kind) applies to intra-wiki
[[slug]] and relative-markdown links ONLY. It MUST NOT flag refs:
frontmatter entries: a refs: target is cross-workspace by design and is
validated by AIP-27 resolution (or left unresolved), NEVER by wiki-local page
existence. A refs: entry whose target does not exist inside this wiki is
correct, not broken.
Lint output is appended to _log.md as an event of type lint.
Vendor extensions
Implementations MAY add fields under metadata.<vendor> (e.g.
metadata.guilde, metadata.simone). Vendor fields MUST NOT change the
meaning of any field defined in this AIP, and a runtime MUST ignore
vendor extensions it does not understand.
Rationale
Why filesystem-first. Following AIP-6/7/8: the wiki is the folder. Adapters project it into databases or vector stores; the canonical representation stays portable.
Why mandatory _index.md and _log.md. The ingest contract requires
the LLM to update both atomically. Making them part of the spec — rather
than implementation detail — lets a third party verify after the fact
that the wiki was maintained according to its schema, and lets a runtime
detect a poorly-applied ingest by inspecting log + index alone.
Why a provenance/dedup manifest (_manifest.json). _log.md records
what happened for humans; _index.md catalogs what exists for readers.
Neither answers the question ingest actually needs before it does any work:
"have I already processed these exact bytes, and if so which pages did they
become?" Without a machine-readable sourceId → { contentHash, slugs } map, a
re-run either re-distills every source (wasteful, non-deterministic LLM
output) or risks emitting a second page for a source already covered. Making
the manifest a REQUIRED generated file turns idempotency into a checkable
property: a third party can verify that ingest skipped unchanged sources by
diffing _manifest.json against the sources/ tree, and the runtime gets an
O(1) skip check keyed on the existing sources.hashAlgo rather than
re-reasoning over prose. It is generated integrity metadata, not a new
authority — the wiki files remain the source of truth.
Why refs: (typed cross-workspace references), and why a new field. A
page has three reasons to name something, and collapsing them loses
information. sources: is provenance IN — the raw bytes the page was
distilled from; [[slug]] is intra-wiki navigation — an edge to another
page of this wiki. Neither can express "this page is about that code file
in another workspace" or "…that page in another wiki". That third relation is
references OUT, and it wants a typed value, not a string — hence a new field
holding an AIP-27 Ref[]. The name refs: was chosen over
related: deliberately: it maps one-to-one onto AIP-27's own Ref term, so
the field reads as exactly what it holds ("the typed refs this page is
about"), whereas related: is a vaguer word that invites overloading with
[[slug]]-style intra-wiki links and blurs the very split this field exists
to draw. The crisp pairing is sources: (provenance IN) vs refs:
(references OUT) vs [[slug]] (navigation WITHIN) — three fields, three jobs,
no ambiguity. Reusing AIP-27 rather than inventing a local encoding also means
the same parser, resolver, and ws:// spelling the rest of the family already
uses apply unchanged.
Why the bare slug binds the runtime, not the other way around. The slug
is the wiki's portable page identity, so it must stay a bare kebab token — the
same value a [[slug]] link, an _index.md row, and a _manifest.json entry
all reference. A retrieval or graph runtime often wants a path-namespaced node
id (notes/foo vs pr-reviews/foo) to keep same-named pages in different
directories distinct; that is legitimate, but it is the runtime's internal
derivation. Making the frontmatter carry the prefixed form would break the
no-slash kebab rule and couple the portable artifact to one runtime's indexing
scheme — the exact non-portability this AIP exists to avoid. Hence the
direction of the obligation: the wiki keeps bare slugs, and a conforming
runtime MUST accept them and derive its own ids. A runtime that rejects a
conformant slug (forcing the author to omit it or spell a path) is
non-conforming — a real case observed against a graph backend that derived the
node id from the file path and then refused a differing frontmatter slug,
which would have silently eroded conformance had the wiki bent to it.
Why the cross-wiki ref syntax is normative but the graph is not. AIP-10
is filesystem-first: a wiki must be queryable with file reads alone. So the
spec pins the one thing that must be portable — the ws://wikis/<wiki-slug>/<page-slug>
SYNTAX for addressing a page across wikis, aligned exactly with AIP-27's
wikis collection — and deliberately stops there. Building an index over the
refs: edges and traversing code↔knowledge / wiki↔wiki as a graph is a
runtime optimization, already permitted by the Query contract's "MAY add
auxiliary indices (BM25, embeddings, graph)" clause. Fixing the syntax while
leaving the index optional lets a graph runtime (e.g. gbrain) implement
traversal without forcing every conforming host to ship a graph engine, and
keeps two hosts interoperable at the file level even when only one indexes.
Why a workspace manifest (KNOWLEDGE.md). Prose describes intent;
machines need contracts. Earlier drafts of this AIP made AGENTS.md the
schema of record, which works for a single team but breaks the moment
multiple consumers want to share a wiki. A YAML manifest is what lets a
runtime know, without re-reading prose, that an entry of type
Investor is required to have a lead_partner field, that lint rule
require-source runs at severity error on Concepts, that this wiki
retains sources forever. The manifest is also the surface that
composition operates on — merging YAML is mechanical, merging prose is
interpretive. Splitting the canonical config (KNOWLEDGE.md) from the
human-readable companion (AGENTS.md) lets each artifact do what it's
good at, and avoids forcing tooling to parse natural language.
Why one doctype for both workspace root and view. The alternative is
two doctypes — knowledge.workspace/v1 for the root and
knowledge.workspace.view/v1 for the per-consumer adaptation. Two
doctypes means two schemas to maintain, two validators to ship, and an
asymmetric merge surface. One doctype with extends: collapses the two
into a single mental model: a workspace IS its own view of itself, and
every view IS a workspace bound to a different consumer. The same
schema validates both, the same merge algorithm applies recursively,
and the same authoring skill (./resources/aip-10/draft/skills/author-knowledge/SKILL.md)
walks an agent through both flows.
Why composition over inheritance hierarchies. A wiki could ship a
single workspace and then run a query-time prompt that reshapes results
per consumer. That couples consumer behaviour to runtime prompts —
which means swapping runtimes loses the lens. Composition via on-disk
extends: chains keeps the lens portable: the same operator,
re-instantiated in a different runtime, still gets the same merged
config because the merge runs against files, not prompts. This is the
registry-of-views pattern: the wiki is the registry, each KNOWLEDGE.md
is a registered view, and consumers pick a view by location.
Why AGENTS.md is RECOMMENDED, not REQUIRED. Conforming wikis
SHOULD ship both KNOWLEDGE.md and AGENTS.md. Automated pipelines —
and there will be many in the lifetime of this AIP — only need
KNOWLEDGE.md to operate. Forcing them to also write prose creates
drift between the two files; downgrading AGENTS.md to a recommendation
acknowledges that prose is for humans and machines should be free to
operate on machine config alone. Linters SHOULD flag drift between the
two when both are present.
Why contradicts and supersedes are first-class. Knowledge is not
monotonic. A spec that pretends contradictions don't exist forces the
LLM to silently overwrite — losing provenance and audit ability. Making
both relations explicit lets humans and other agents reason about why
a page reads the way it does.
Why no vector store in the spec. Retrieval is a runtime concern. Mandating a specific index would couple the spec to today's tooling; forbidding indices would punish runtimes that already have them. The spec defines what's on disk; runtimes choose how to reach it.
Why depth-cap and cycle-detection are warnings, not errors. A
malformed extends: chain is a configuration bug — but a consumer
whose view fails to load loses ALL of its lens, including the parts
that don't depend on the broken parent. The runtime degrades gracefully
to the local manifest and surfaces the issue, instead of refusing to
activate the consumer. This matches the broader AIP family's preference
for partial-availability over hard-fail.
Reference Implementation
packages/agent-framework/src/wiki —
parser, ingest pipeline, lint pass, and BM25 retrieval. Used by Guilde
(per-guild knowledge base, Librarian operator) and Simone (per-user
personal codex, written by the Council standing pass).
The implementation defines the working schema during the Draft phase; this AIP will absorb the normative text in full as part of moving Draft → Review.
Backwards Compatibility
Not applicable — this AIP introduces a new spec.
Security Considerations
The wiki is write surface for an LLM. Threats:
- Prompt injection via sources — a malicious source instructs the LLM to make harmful edits across the wiki. Mitigation: ingest runs in a sandboxed prompt context; the LLM MUST NOT execute instructions embedded in source bodies, only summarize them.
- Schema poisoning — an attacker rewrites
KNOWLEDGE.md(orAGENTS.md) to relax contradiction policy, expand the LLM's authority, or silently raise lint severities toinfo. Mitigation: both files SHOULD be subject to the same governance gate (AIP-7) as any contract — changes go through approval. Thegovernance:field inKNOWLEDGE.mdmakes this binding explicit; views that override the parent's governance MUST be reviewable through the same gate (a child cannot escape a parent's policy by pointinggovernance:elsewhere unless the parent permits it). - View shadowing — a malicious view
extends:a benign workspace but overrideslintsorcuration.conflictResolutionto silently weaken the curator agent. Mitigation: hosts MUST expose the resolution chain alongside the merged config so reviewers can audit what came from where; governance policies SHOULD restrict which lints a view is allowed to soften. A legal/compliance baseline SHOULD ship as aconstraint-mode view so it cannot be shadowed or tombstoned by a higher layer or a guild edit — the floor rule turns an otherwise-silent override into aknowledge_constraint_conflict/knowledge_tombstone_blockedwarning. - Confidence laundering — an LLM marks low-quality syntheses as
confidence: 1.0. Mitigation: confidence values written by the LLM during ingest are advisory; downstream consumers MAY weight them against source recency and observation count. - Cross-tenant leakage — when multiple tenants share a runtime, a
wiki ingest pulls a source from the wrong tenant. Mitigation: runtime
MUST scope
sources/reads to the wiki's tenant; the spec is filesystem-first and inherits whatever isolation the host provides. - Manifest integrity vs authority —
_manifest.jsonis integrity metadata, NOT a trust root. ItscontentHashlets a runtime detect change (and thus skip unchanged sources); it does not by itself prove a source is authentic — an attacker who can rewrite a source undersources/can also rewrite its manifest entry. Provenance authenticity belongs to thegovernance:signing gate (AIP-7), not to this file. The manifest carries its ownhashAlgo(mirroringsources.hashAlgo) to keep the hash algorithm agile: assha256weakens, a workspace re-baselines tosha512/blake3and the recordedhashAlgotells a reader which digest a storedcontentHashwas computed with, so verification never silently compares across algorithms. - Cross-workspace ref resolution — a
refs:entry (url:,github:,ws://…) is an AIP-27Ref: an identity, not trusted bytes. A runtime that resolves one MUST apply AIP-27's own safeguards (path-escape rejection onlocal,http(s)-only onurl, tenant-local resolution ofws://) and MUST treat fetched bytes as untrusted until validated.refs:never bypasses source immutability (Layer 1): it points at other workspaces, it does not import them intosources/.
Resources
Supporting artifacts for AIP-10. Links open the file on GitHub — markdown and JSON render natively in GitHub's viewer. Browse the full resource tree →
- ADAPTER.mdaip-10/draft/ADAPTER.md
- EXAMPLES.mdaip-10/draft/EXAMPLES.md
- KNOWLEDGE.schema.jsonaip-10/draft/KNOWLEDGE.schema.json
- A6-declarative-autopromote.mdaip-10/draft/proposals/A6-declarative-autopromote.md
- A8-appliesTo-uri-widening.mdaip-10/draft/proposals/A8-appliesTo-uri-widening.md
- SKILL.mdaip-10/draft/skills/author-knowledge/SKILL.md
- SKILL.mdaip-10/draft/skills/curate-wiki/SKILL.md
AIP-9: OPERATOR.md — agentoperators/v1 (operator runtime protocol)
A single canonical operator shell — pluggable profile, skills, tools, memory, governance — that any agent runtime can implement and any conforming workflow can dispatch to.
AIP-11: LESSON.md — agentlearning/v1 (distilled lessons from experience)
A markdown format for storing the transferable lessons an agent extracts from successful and failed runs — title, trigger, evidence, outcome — and a contract for how runtimes distill them and inject them back into future turns.