Open Knowledge Format (OKF) bundles
Author and validate Open Knowledge Format bundles with mdsmith: scaffold the config with mdsmith init --starter okf to require a non-empty type on every concept document, validate bundle-relative cross-links with links.site-root, and generate the index.md listing with <?catalog?>.
The Open Knowledge Format (OKF) is a vendor-neutral specification for representing the knowledge an AI agent needs as a plain directory of Markdown files with YAML front matter. Each file is one concept — a table, a dataset, a metric, a playbook, an API. The format is “just files”: no SDK, no runtime, no registry.
mdsmith is a natural authoring and validation tool for OKF, because the
two share a model — Markdown plus front matter, cross-linked files, and
a progressive-disclosure index.md. This guide shows how to keep a
bundle conformant as you edit it: require the one field OKF mandates,
catch broken cross-links, and generate the index from front matter.
# What an OKF bundle looks like
A bundle is a directory tree. Every .md file except the two reserved
names — index.md and log.md — is a concept document with a
non-empty type in its front matter.
sales/
├── index.md # reserved: a listing for progressive disclosure
├── log.md # reserved: a chronological change history
├── datasets/
│ └── sales.md # concept (type: BigQuery Dataset)
└── tables/
├── orders.md # concept (type: BigQuery Table)
└── customers.md # concept (type: BigQuery Table)A concept document carries a small block of front matter for the
structured fields OKF names — type (required), and the recommended
title, description, resource, tags, and timestamp — and a
Markdown body for everything else:
---
type: BigQuery Table
title: Orders
description: One row per completed customer order.
resource: https://console.cloud.google.com/bigquery?d=sales&t=orders
tags: [sales, orders]
timestamp: 2026-05-28T00:00:00Z
---
# Schema
| Column | Type | Description |
| ---------- | ------ | ---------------------------------------- |
| order_id | STRING | Unique order identifier. |
| total_usd | NUMERIC | Order total in USD. |
Part of the [sales dataset](/datasets/sales.md).# Scaffold the config
Run this once at the bundle root:
mdsmith init --starter okfIt writes a ready-to-edit .mdsmith.yml — a plain mdsmith config, no
special OKF runtime — that does two things.
First, it requires a non-empty type on every concept document:
rules:
required-frontmatter:
fields: [type]
exclude: [index.md, log.md]The check is MDS071 required-frontmatter
, scoped to skip
the reserved files. A file with no type, an empty type, or no
front matter at all fails mdsmith check:
sales/tables/orders.md:1:1 MDS071 front-matter "type" is required but missingSecond, it turns off the prose- and size-opinion rules that suit a documentation site but not a data bundle. An OKF concept body may open with prose, so the “first line must be a heading” rule steps aside. Long lines, large files, dense tables, and tight token budgets are all fine in a knowledge bundle, so those checks stand down too:
rules:
first-line-heading: false
line-length: false
max-file-length: false
token-budget: false
paragraph-readability: false
paragraph-structure: false
table-readability: falseMechanical hygiene — trailing whitespace, code fences, blank lines,
link integrity — stays on. The starter pins no Markdown flavor, so GFM
tables in concept bodies are never flagged. Everything past this point
is the rest of what the starter writes (or what you would add by hand);
edit any line to fit your bundle. If you want a stricter type
vocabulary — say, an enum of allowed types — layer a
kind
on top, as shown below.
# Validate cross-links
OKF concept documents link to each other with ordinary Markdown links. The spec supports two forms, and mdsmith handles each:
- Relative links (
[orders](../tables/orders.md)) are resolved against the linking file and validated out of the box. A typo or a moved target failsmdsmith check. - Bundle-relative links (
[orders](/tables/orders.md)), which OKF recommends for stability, begin with/and are read from the bundle root. mdsmith treats a leading-/link as absolute and, by default, skips it — so it is never a false positive, but it is also not checked.
To validate bundle-relative links, point mdsmith at the bundle root
with links.site-root. The starter already sets this — "." is the
directory you run mdsmith check from:
rules:
cross-file-reference-integrity:
links:
site-root: "."With site-root set, [orders](/tables/orders.md) resolves to
tables/orders.md under the root and a missing target is reported.
Anchor checks are skipped for bundle-relative links, so use them for
whole-file references and relative links when you target a heading.
#
Generate index.md with a catalog
An OKF index.md is a bullet list that lets an agent scan a directory
before opening any single file — the same progressive-disclosure idea
covered in the
progressive disclosure guide
. The OKF
shape is one bullet per concept, [Title](link) - description, with
the description taken from each concept’s front matter.
A <?catalog?> directive
generates
exactly that. Put it in each directory’s index.md and let
mdsmith fix keep it in sync:
<?catalog
glob:
- "*.md"
- "!index.md"
- "!log.md"
sort: title
row: "* [{title}]({filename}) - {description}"
?>
<?/catalog?>On mdsmith fix, the directive reads title and description from
every concept’s front matter and rewrites the bullet list between the
markers; the reserved files are excluded by the ! globs. The bundle
root’s index.md is also the one place OKF allows front matter — an
okf_version: "0.1" line declaring the target spec version — and the
starter’s required-frontmatter excludes index.md, so it needs no
type there.
The directive markers are mdsmith-specific. To hand a consumer a
pristine, directive-free copy of the bundle, run
mdsmith export
, which writes the
generated bodies without the surrounding markers.
#
Track changes in log.md
OKF’s other reserved file, log.md, records a bundle’s history with
date-grouped entries, newest first, under YYYY-MM-DD headings:
# Update log
## 2026-05-22
* **Update**: Added the [orders table](/tables/orders.md) reference.mdsmith does not generate log.md — it is authored by hand or by your
producer — but the starter excludes it from the type requirement and
lints it like any other Markdown file, so its headings, lists, and
links stay well formed.
# Tighten per-type structure with a kind
The starter enforces OKF’s single hard requirement. To go further —
make the recommended fields mandatory for your project, pin type to
an enum, or require a heading structure per concept type — declare a
kind with a schema
. A kind matches files by a path
pattern and validates their front matter and headings. The starter
ships this block commented out; uncomment and adapt it:
kinds:
bq-table:
path-pattern: "tables/*.md"
schema:
frontmatter:
type: '"BigQuery Table"'
title: nonEmpty
description: nonEmpty
timestamp: string
sections:
- heading: null
- heading: { regex: '^Schema$' }
kind-assignment:
- glob: ["tables/*.md"]
kinds: [bq-table]Now a tables/*.md file whose type is not exactly BigQuery Table,
or that omits title, or that lacks a Schema section, fails
mdsmith check with a schema
diagnostic. The kind layers
over the base config: the starter’s type requirement still applies to
every other directory.
# Run it in CI
The same two commands serve editing and CI:
mdsmith fix . # rebuild every index.md, normalize formatting
mdsmith check . # read-only: non-zero exit on any violationmdsmith check . is the gate. It walks the bundle, applies your
config, and exits non-zero if any concept document is missing its
type, any cross-link is broken, or any index.md is stale relative
to the front matter it indexes. Wire it into the same pre-commit hook
or CI step you use for the rest of the repository.
# Full example
mdsmith init --starter okf writes this complete .mdsmith.yml for a
bundle whose root is the repository:
front-matter: true
rules:
required-frontmatter:
fields: [type]
exclude: [index.md, log.md]
cross-file-reference-integrity:
links:
site-root: "."
first-line-heading: false
line-length: false
max-file-length: false
token-budget: false
paragraph-readability: false
paragraph-structure: false
table-readability: falseThat is the whole configuration — ordinary, editable mdsmith config.
required-frontmatter carries the type requirement, site-root
turns on bundle-relative link validation, and the disabled rules keep
mdsmith’s prose opinions off a data bundle. Everything else — index
generation, formatting, change-log linting — follows from the
directives and reserved-file conventions in the bundle itself.