cd /news/agent-protocols/okf-v0-2-frontmatter-what-the-spec-r… · home › topics › agent-protocols › article
[ARTICLE · art-154974] src=dev.to ↗ pub= topic=agent-protocols verified=true sentiment=· neutral

OKF v0.2 frontmatter: what the spec requires, and two ways to check a folder

A developer has published a breakdown of Google Cloud's Open Knowledge Format (OKF) v0.2 spec, noting that only one frontmatter field — a non-empty `type` — is strictly required for a markdown folder to be conformant, with `title`, `description`, `resource` and `tags` merely recommended. The writeup includes a short Python script that walks a directory, skips the reserved `index.md` and `log.md` files, and flags any note lacking a frontmatter block or non-empty `type` while listing missing recommended fields.

by read4 min views7 publishedOct 22, 2026

I make JidoSeal. Free and local; the scan engine is proprietary; JidoSeal also sells optional certificates.

If you keep notes, docs or a knowledge base as markdown with YAML frontmatter, and you point an AI tool at them (Claude Code, Cursor, Copilot, Codex, Gemini CLI, Zed, a local model), Google Cloud's Open Knowledge Format (OKF) is worth ten minutes. It is a small, open spec for exactly that kind of folder: "a directory of markdown files with YAML frontmatter", meant to be "authored by people, generated by agents... and consumed by both". This post covers what v0.2 actually requires, which is less than most people assume, and then two ways to check a folder against it.

The spec is short. You can read all of it at https://github.com/GoogleCloudPlatform/open-knowledge-format/blob/main/SPEC.md. Here is the part that matters for frontmatter.

A bundle is just a folder. Every .md file in it is a "concept document", except two reserved filenames: index.md (a directory listing) and log.md (an update history). Subfolders are fine, and git is the recommended way to ship it.

One field is required: type. Section 4.1 lists it as the only required key, and says "a concept carrying just type is fully conformant". Its values are free text that you choose (policy, procedure, Metric, Playbook...). Nobody registers them centrally, and consumers must handle types they don't recognise.

So this file is valid OKF v0.2:

---
type: policy
---


Employees accrue leave monthly.

Four fields are recommended: title, description (one sentence), resource (a URI for the thing the note describes, if there is one), and tags (a YAML list). If title is missing, a consumer may derive it from the filename.

Optional families, if you want more:

generated: { by, at } records who or what wrote the content. verified is a list of { by, at } entries. A consumer derives a trust tier from it: no by: human:<id> means human-reviewed.status is draft, stable or deprecated, and defaults to stale_after is an absolute instant after which the note counts as stale.sources is a list of entries, each with a required resource. Conformance (section 11) is three rules. Every non-reserved .md file has a parseable YAML frontmatter block. Every block has a non-empty type. index.md and log.md follow their own sections if present. Just as useful is what consumers must not reject a bundle for: missing optional fields, unknown type values, unknown extra keys, broken cross-links, or missing index.md files. Extra keys of your own are fine.

That gives you a concrete thing to check: does every note open with a frontmatter block, and does that block have a non-empty type? Then, softer: which of the four recommended fields are missing?

This reads only top-level key: value lines. That's enough for type, which is a plain string. It skips the reserved filenames, fails any file without a frontmatter block or a non-empty type, and lists the recommended fields that are missing.

import sys, pathlib
RECOMMENDED = ["title", "description", "resource", "tags"]
bad = 0
for p in sorted(pathlib.Path(sys.argv[1]).rglob("*.md")):
    if p.name in ("index.md", "log.md"): continue          # reserved filenames, §3.1
    lines = p.read_text(encoding="utf-8").splitlines()
    if not lines or lines[0] != "---" or "---" not in lines[1:]:
        print(f"FAIL {p}: no frontmatter block"); bad += 1; continue
    fm = lines[1:lines.index("---", 1)]
    keys = {l.split(":", 1)[0].strip(): l.split(":", 1)[1].strip() for l in fm if ":" in l and not l.startswith((" ", "#", "-"))}
    if not keys.get("type"):
        print(f"FAIL {p}: no non-empty 'type'"); bad += 1; continue
    missing = [k for k in RECOMMENDED if k not in keys]
    print(f"ok   {p}" + (f"  (recommended, missing: {', '.join(missing)})" if missing else ""))
sys.exit(1 if bad else 0)

Here it is on a sample folder of six notes, one of which has no frontmatter at all:

$ python3 okf_check.py tiers
ok   tiers/bronze/leave-policy.md  (recommended, missing: title, description, resource, tags)
ok   tiers/gold/leave-policy.md  (recommended, missing: resource, tags)
ok   tiers/mixed/expenses.md  (recommended, missing: description, resource, tags)
ok   tiers/mixed/leave-policy.md  (recommended, missing: resource, tags)
FAIL tiers/mixed/notes.md: no frontmatter block
ok   tiers/silver/leave-policy.md  (recommended, missing: resource, tags)
$ echo $?
1

It exits with 1 when anything fails, so it can go straight into CI or a pre-commit hook. It is honest about its limits. It does not parse YAML properly, so it won't notice a frontmatter block that is broken YAML, and it would accept type: "". Section 11 asks for "parseable" YAML, so if you need that guarantee, swap the keys line for yaml.safe_load and accept one dependency.

To list the notes with no type line at all:

$ grep -rL --include='*.md' -E '^type: *[^ ]' tiers
tiers/mixed/notes.md

That is fast, but it also matches a type: line in the body of a note. For a real YAML read of the frontmatter only, mikefarah's yq (v4) has a front-matter mode:

$ for f in $(find tiers -name '*.md' ! -name index.md ! -name log.md | sort); do printf '%s\t%s\n' "$f" "$(yq --front-matter=extract '.type // "MISSING"' "$f")"; done
tiers/bronze/leave-policy.md    policy
tiers/gold/leave-policy.md  policy
tiers/mixed/expenses.md procedure
tiers/mixed/leave-policy.md policy
tiers/mixed/notes.md    MISSING
tiers/silver/leave-policy.md    policy

Change .type to .description (or any other field) to find the notes that are missing that one.

If you'd rather have your AI tool do the check, I also maintain a free, local MCP server that runs it and lists each file's missing fields: https://github.com/Jidoseal/jidoseal-mcp

── more in #agent-protocols 4 stories · sorted by recency
── more on @google cloud 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/okf-v0-2-frontmatter…] indexed:0 read:4min 2026-10-22 · —