The @docmd/plugin-okf generates an Open Knowledge Format bundle from your docmd site. This guide explains what the bundle looks like, how to organise your content for the best AI-agent consumption, and how OKF differs from the llms.txt flat-list format.

The mental model: a wiki, not a sitemap

A traditional docs site is a tree — sections and subsections, with pages hanging off each one. A user navigates the tree top-down to find what they need.

An OKF bundle is a wiki — a flat directory of typed concept files with cross-links between them. An AI agent navigates the graph horizontally, following links from one concept to its neighbors.

The two structures look the same on disk (markdown files in directories), but the navigation model is different. The OKF spec’s three design principles are worth quoting in full:

  1. Minimally opinionated. OKF requires exactly one thing of every concept: a type field. Everything else (what types exist, what other fields to include, what sections the body has) is left to the producer.
  2. Producer/consumer independence. A bundle hand-authored by a human can be consumed by an AI agent. A bundle generated by a metadata export pipeline can be browsed in a visualizer. A bundle synthesized by one LLM can be queried by another. The format is the contract; the tooling at each end is independently swappable.
  3. Format, not platform. OKF is not tied to any specific cloud, database, model provider, or agent framework.

What an OKF bundle looks like

site/okf/
├── okf.yaml              ← typed manifest
├── index.md              ← Karpathy-style catalog
├── graph/                ← opt-in: only when plugins.okf.graph: true
│   ├── index.html        ← interactive force-directed viewer
│   ├── graph.json        ← graph data
│   ├── graph.js          ← viewer runtime
│   └── graph.css         ← viewer styles
├── concepts/
│   ├── weekly-active-users.md
│   ├── orders-table.md
│   └── api-authentication.md
└── _meta/
    ├── bundle.json
    └── lint-report.txt

Each concepts/<slug>.md file carries a type field in frontmatter plus the full markdown body of the page. The okf.yaml manifest lists every concept with its type, path, locale, version, and tags — the catalog that an AI agent uses to decide which concepts to read.

What goes in a type

The type field is the only required frontmatter key. It tells the agent what kind of knowledge this concept represents. The @docmd/plugin-okf plugin has a path-prefix type-inference map:

URL prefix Inferred type
/api/ api
/guides/ guide
/reference/ reference
/concepts/ concept
/runbooks/ runbook
/datasets/ dataset
/metrics/ metric
/tables/ table
(anything else) concept (default)

You can override the inferred type with explicit frontmatter:

---
type: api
title: "Authentication API"
description: "OAuth 2.0 + JWT auth flow for the user API."
---

# Authentication API
...

Or use the nested okf.type form:

---
okf:
  type: api
title: "Authentication API"
---

The agent reads the type field first. A concept with type: runbook is treated as a step-by-step playbook (e.g. “how to recover from a partial outage”); a concept with type: api is treated as API reference; a concept with type: dataset is treated as a data dictionary.

OKF is a graph, not a tree. The relationships between concepts are inferred from internal markdown links. If api-authentication.md links to users-table.md, the OKF bundle records that edge in graph.json and the graph viewer draws a line between the two nodes.

The okf-bundle (read: “graph of concepts”) is more useful than a tree because it lets the agent find related concepts the author didn’t think to put in a sub-section. The LLM-wiki pattern that OKF formalises explicitly assumes the agent will follow links to discover adjacent knowledge.

Best practices for cross-links:

  • Link forward — when introducing a concept, link to the concepts it depends on. “To use this, see users table”.
  • Link backward — in the concept that depends on this one, link back. “Used by API auth”.
  • Don’t over-link — every link should add information. Linking every word dilutes the graph and confuses the agent.

Per-page opt-out

Some pages aren’t useful to AI agents — legal boilerplate, internal “about the team” pages, marketing copy. Use frontmatter.okf: false to exclude a single page from the OKF bundle:

---
okf: false
---

# Internal Roadmap (Q3 2026)
...

Or use noindex: true to exclude a page from every downstream consumer (sitemap, search, llms.txt, OKF). The two flags differ:

  • okf: false — excluded from OKF only; still in search and llms.txt
  • noindex: true — excluded from every downstream consumer

How OKF differs from llms.txt

The llms.txt plugin produces a flat list of pages:

- [Page 1](https://example.com/page-1)
- [Page 2](https://example.com/page-2)
- [Page 3](https://example.com/page-3)

The OKF plugin produces a typed graph:

concepts:
  - id: api-authentication
    type: api
    title: "Authentication API"
    path: /api/auth/
    file: concepts/api-authentication.md
    tags: [auth, security]
  - id: users-table
    type: table
    title: "Users table"
    path: /tables/users/
    file: concepts/users-table.md
    tags: [schema, data]

The two complement each other:

  • llms.txt is for flat consumption — “give me everything”. An agent reads the file and has the full text in its context window.
  • OKF is for typed consumption — “give me the schema for table X”. An agent reads the manifest, picks the concepts it needs, and loads them selectively.

For projects with under 50 pages, llms.txt alone is often enough. For projects with 50+ pages, OKF is the more efficient format — the agent doesn’t have to load every page just to find the one it needs.

Common mistakes

1. Skipping the type field

The OKF manifest is most useful when every concept has a distinct type. If 80% of your pages are inferred as concept, the agent can’t tell which are reference docs, which are tutorials, and which are runbooks. Set type: <name> explicitly for every page that has a clear category.

If a page is a dead end (no internal links to or from it), the graph viewer shows it as an isolated node. The agent will read it in isolation, missing the context. Add at least one inbound link (referenced from another page) for every page you want surfaced.

3. Putting internal jargon in description

The description field is shown in the manifest and in llms.txt summaries. An AI agent uses it to decide whether a concept is relevant. Use plain English the agent can match against a user query: “weekly active users for the marketing site, computed from the events stream”, not “WAU (ms)”.

4. OKF for non-AI-agent sites

If your docs site has no AI-agent audience, OKF adds nothing. The @docmd/plugin-okf is enabled by default, so disable it explicitly:

{
  "plugins": { "okf": false }
}

The llms.txt plugin is the right tool for “AI-searchable flat text”; OKF is the right tool for “AI-agent typed knowledge graph”.

How to verify

After docmd build, inspect the bundle at site/okf/:

# The manifest (every concept, type, path)
cat site/okf/okf.yaml | head -30

# The catalog (Karpathy-style grouped by type)
open site/okf/index.md

# The interactive graph (force-directed, theme-aware)
open site/okf/graph.html

# Warnings the plugin produced
cat site/okf/_meta/lint-report.txt

The lint report is the first thing to check — it lists pages without a type field, pages with broken internal links, and orphaned concepts (no inbound links). Fix any of those for a cleaner agent experience.

See also