OKF 0.2 explained: the Open Knowledge Format and validation

November 8, 2026·IWE Team

OKF 0.2 is the current version of the Open Knowledge Format, a spec from Google Cloud for knowledge that agents write and maintain. A bundle is a folder of markdown files with YAML frontmatter. There is no SDK and no registry.

This post walks through what the spec asks for: the frontmatter fields, the two reserved files, and the three conformance rules. Then it shows how to scaffold a bundle and validate it with IWE, using real output from iwe 0.25.0. For the short reference version, see the OKF docs page.

What is OKF 0.2

The OKF spec describes a knowledge bundle: a directory tree of markdown files. Each non-reserved file is a concept, one unit of knowledge, such as a table, a metric, or a playbook. A concept’s ID is its path in the bundle without the .md suffix.

You can ship a bundle as a git repository (the spec’s recommendation), an archive, or a subdirectory of a larger repository.

Version 0.2 adds what an agent-written corpus needs for trust. A reader can ask where a concept came from, who checked it, and whether it is still current, and the answers sit in frontmatter. Compared with v0.1, it brings:

  • sources replaces the body # Citations list.
  • generated: { by, at } replaces the old timestamp field.
  • New optional families: verified, status and stale_after.
  • A new concept type, Attested Computation, for values that must be computed a sanctioned way.

Those two replacements are the only breaking changes. Everything else in v0.2 is additive.

OKF frontmatter fields

Every concept starts with a YAML frontmatter block. Only one key is required:

  • type: a short string such as Metric, Playbook or API Endpoint. Types are not registered anywhere, and consumers must accept types they do not know.

The spec recommends four more keys: title, description (one sentence), resource (a URI for the asset the concept describes) and tags. Producers may add any other keys, and consumers must not reject a document because of them.

On top of that, OKF 0.2 defines three optional families. Leaving one out is valid; it only means the signal is not there.

FamilyFieldsWhat it answers
Provenancesources (each entry needs resource; id, title, author, usage_count, last_modified are optional), usage_windowWhat was this built from?
Trustgenerated: { by, at }, verified (one { by, at } or a list of them)Who wrote it, and who confirmed it?
Lifecyclestatus (draft, stable or deprecated; absent means stable), stale_afterIs it current, and until when?

Actors in by fields follow one convention: <producer>/<version> for agents, human:<id> for people and process:<id> for automated processes. Readers derive a trust tier from verified: none means unverified, only non-human actors means machine-confirmed, and any human: actor means human-reviewed.

To attribute one claim to one source, use a markdown footnote whose label is the source’s id. Here is a concept that uses all three families:

---
type: Playbook
title: "Incident response: data freshness alert"
description: Steps to triage a freshness alert on the orders pipeline.
tags: [oncall, incident]
status: stable
generated: { by: human:ahormati, at: 2026-04-12T09:00:00Z }
verified: { by: human:ahormati, at: 2026-06-25T09:00:00Z }
stale_after: 2026-12-31
sources:
  - id: runbook
    resource: https://example.com/runbooks/orders
    title: Orders pipeline runbook
---

# Incident response: data freshness alert

A freshness alert fires when `orders` lags more than 30 minutes behind its SLA.[^runbook]

[^runbook]: Orders pipeline runbook

Attested Computation concepts also carry runtime (required for that type), parameters, computation, executor and attester. Read §10 of the spec if you publish computed figures.

Reserved files: index.md and log.md

Two filenames are reserved at every level of the bundle. You cannot use them for concepts.

index.md (§8) lists what a directory contains, so a person or agent can see what is there before opening anything. It has no frontmatter. The one exception is the bundle-root index.md, which may declare okf_version: "0.2". The body is one or more headings, each followed by a list of links:

---
okf_version: "0.2"
---

# Playbooks

- [Incident response: data freshness alert](playbooks/freshness-alert.md) - Steps to triage a freshness alert on the orders pipeline.

# Metrics

- [Revenue](metrics/revenue.md) - Recognized revenue for a fiscal year.

log.md (§9) records the history of changes in its scope, newest first, grouped under date headings. Those headings must use the ISO 8601 YYYY-MM-DD form:

# Bundle update log

## 2026-11-08

- **Creation**: Added the [Revenue](metrics/revenue.md) metric.
- **Creation**: Established the [freshness playbook](playbooks/freshness-alert.md).

OKF conformance rules

Section 11 of the spec makes a bundle conformant with OKF v0.2 when:

  1. Every non-reserved .md file has a parseable YAML frontmatter block.
  2. Every frontmatter block has a non-empty type.
  3. Every index.md and log.md follows the structure in §8 and §9.

The rest is deliberately soft. A consumer must not reject a bundle for missing optional fields, unknown types, unknown keys, broken links or a missing index.md.

Validate an OKF bundle with IWE

IWE already works on markdown, frontmatter and links, so an OKF bundle is an ordinary IWE workspace. It has no special OKF mode. Instead, iwe init --okf writes three document schemas, one for each conformance rule.

Scaffold the bundle

In an empty directory:

iwe init --okf
0 files here
initialized .iwe/config.toml
wrote .iwe/schemas/okf.yaml
wrote .iwe/schemas/okf-index.yaml
wrote .iwe/schemas/okf-log.yaml
wrote index.md
try: iwe normalize --dry-run · iwe find --fuzzy <query>

The generated index.md holds only the version declaration, and .iwe/config.toml sets refs_extension = ".md" so links keep the .md suffix that OKF readers expect. The config also binds each schema to its files. The ! patterns keep the concept schema off the reserved files:

[schemas.okf]
match = ["**", "!index", "!**/index", "!log", "!**/log"]

[schemas.okf-index]
match = ["index", "**/index"]

[schemas.okf-log]
match = ["log", "**/log"]

What each schema checks:

  • okf.yaml: every concept has a non-empty type, and the optional families are well-formed when they are present.
  • okf-index.yaml: index.md has no frontmatter besides okf_version, and its body is sections of link lists.
  • okf-log.yaml: log.md has one title section with YYYY-MM-DD date groups under it.

Run the validator

With the playbook, a Revenue metric, the index and the log from above in place:

iwe schema validate

It prints nothing and exits with 0. Now break the bundle on purpose. Add a concept with no type and an unknown status, give playbooks/index.md a title, and change the log heading to ## Nov 8, 2026:

log › Bundle update log: required section matching "^\d{4}-\d{2}-\d{2}$" is missing
  hint: ISO 8601 date group, newest first
log › Bundle update log › Nov 8, 2026: unexpected section
  hint: a single title section holds the whole history
metrics/churn › frontmatter: "type" is a required property
  hint: OKF v0.2 concept document — frontmatter with a non-empty type (SPEC §4.1, §11)
metrics/churn › frontmatter › status: "archived" is not one of "draft", "stable" or "deprecated"
  hint: OKF lifecycle (SPEC §5.4); omit when stable
playbooks/index › frontmatter: Additional properties are not allowed ('title' was unexpected)
  hint: OKF v0.2 index file — no frontmatter (okf_version allowed at bundle root); sections of link bullets (SPEC §8)

The exit code is 1, so the same command works as a CI gate. Each line names the document, the path to the problem and the rule it breaks. A file with no frontmatter at all fails the same way, with "type" is a required property.

Because these schemas describe body structure as well as frontmatter, they cover all three conformance rules. A frontmatter-only linter cannot check the index.md and log.md shapes. See iwe schema for the rest of the command.

Dates in stale_after

In iwe 0.25.0, the scaffolded okf.yaml checks stale_after, last_modified and usage_window as dates, such as 2026-12-31. Both template bundles write them that way. The spec shows full datetimes such as 2026-12-31T00:00:00Z, and with the default schema that value fails:

playbooks/freshness-alert › frontmatter › stale_after: "2026-12-31T00:00:00Z" is not a "date"

If your producer writes datetimes, change format: date to format: date-time for that field in .iwe/schemas/okf.yaml. After that change, a date-only value is the one that fails.

Bring an existing workspace into line

You do not need to start over. Set refs_extension = ".md" and run iwe normalize, add type where it is missing, and copy the three schemas and bindings from a scaffolded project. The OKF docs page lists the steps.

Query OKF frontmatter

OKF fields are ordinary frontmatter, so iwe find filters on them with the query language. Run against the example bundle:

iwe find --filter '{status: draft}' -f keys
metrics/revenue

The trust and provenance families work the same way. List every concept that someone or something has verified, or every concept a given person wrote:

iwe find --filter '{verified: {$exists: true}}' -f keys
iwe find --filter "{'generated.by': human:ahormati}" -f keys

Both print playbooks/freshness-alert. To find concepts that are already stale, compare stale_after with today’s date. On a copy of the marketing template this returned two documents:

iwe find --filter '{stale_after: {$lte: 2026-11-08}}' -f keys
data/competitors/billingbear.example
data/metrics

That gives an agent, or a weekly job, a plain list of what to re-check.

Reference OKF bundles

Both IWE workspace templates are conformant OKF v0.2 bundles and pass iwe schema validate with no output:

Clone one to see the frontmatter families and the index.md shape in a real bundle.

To start, run iwe init --okf in a new folder, then follow the OKF docs page.

Search

Loading pages…