Google's Open Knowledge Format (OKF, v0.1, June 2026) is a directory of markdown concept files that agents and humans read before acting. OpenChainGraph v0.3 produces cryptographically verifiable decision artifacts after acting. They are complementary layers, not competing formats. This guide covers the OKF companion bundle that OCG auto-generates from chaingraph.json in CI: one concept file per live tool, graph edges as markdown links, zero hand-maintenance.
OKF and OpenChainGraph address different stages of an agent's lifecycle. Understanding which layer does what, and why they cannot be collapsed, is the foundation of a correct integration.
consumes/feeds edges, letting a reader follow the chain narrative. OKF is "just files, just markdown, just YAML", a format, not a platform; minimally opinionated; producer/consumer independent. It answers: what does this tool mean and when should I use it?execution_hash (SHA-256 over the sorted-key JSON of its inputs and outputs), a chain block referencing parent hashes, a compliance_flags[] array, and an audit_signature (Ed25519). The hash chain is cryptographically verifiable: re-run the tool with the same inputs, recompute the hash, and confirm the cited value. It answers: what decision was made, on what inputs, by which tool, in which chain?The two layers interlock cleanly: an agent consults the OKF bundle to plan which chain of MCP tools to invoke, then executes the chain and receives OCG artifacts that prove what was decided. The planning surface (OKF) and the proof surface (OCG) never overlap.
An OKF concept document describes a tool. It is not a decision artifact. A concept .md file must never carry an execution_hash, an audit_signature, or any field from the OCG artifact schema. Putting those fields on a concept document would conflate the knowledge layer with the proof layer, making it impossible for a consumer to distinguish "what this tool does" from "what this tool decided." Keep them strictly, permanently separate. The OKF bundle belongs in a okf/ directory committed alongside the graph index; OCG artifacts are ephemeral runtime outputs, never committed to the knowledge repository.
This separation is also why OKF is currently a companion to OCG, not a dependency. Nothing in OCG's verification path reads or depends on the OKF bundle. The bundle is an informational layer for humans and agent planners; removing it would not affect the cryptographic integrity of any artifact.
In OpenChainGraph v0.3, every CI run that changes chaingraph.json automatically regenerates an okf/ directory alongside the graph index. The directory follows OKF's convention: the path is the concept's identity. Rename a file and you break every link pointing at it, so the filenames are derived deterministically from tool_id values in the index and must not be hand-edited.
okf/ ├── index.md # root — progressive disclosure entry point (OKF reserved) ├── log.md # generation history — one line per CI run (OKF reserved) ├── mandate-types/ │ ├── index.md # mandate-type group index │ ├── payment_mandate.md │ ├── payment_policy.md │ ├── settlement_mandate.md │ ├── compliance_mandate.md │ ├── prompt_template.md │ └── …one file per distinct mandate_type └── tools/ ├── index.md # tool list — links to every concept below ├── art-01-ap2-mandate-chain-validator.md ├── art-02-agent-spend-policy-simulator.md ├── art-03-x402-settlement-modeler.md ├── art-04-agent-identity-attestation-checker.md ├── ptg-01-ap2-prompt-template-generator.md └── …one concept per node where status === "live"
The mandate-types/ subdirectory groups tools by domain for human readers. The tools/ subdirectory is the primary machine-readable surface: each concept file corresponds 1:1 to a node in chaingraph.json, and the filename is the node's tool_id value with a .md extension. The root index.md and log.md are OKF reserved filenames: every compliant OKF bundle may include them, and OKF consumers know to look for them as the entry point and change history respectively.
Every file under okf/tools/ is regenerated on every CI run that touches chaingraph.json. Hand edits will be silently overwritten on the next run. To change a concept's title, description, or chain edges, change the corresponding node in chaingraph.json and let CI regenerate the bundle. The only files safe to hand-edit are okf/index.md (if you add a custom preamble) and okf/mandate-types/*.md (narrative prose not derived from the index). Even these should be treated with care: the generator will not touch them, but a future schema change may invalidate their content.
Each file under okf/tools/ is a complete OKF concept document derived directly from the corresponding node in chaingraph.json. The only required OKF frontmatter field is type; all other fields shown here are standard OKF conventions. The body uses ordinary markdown: the chain edges (consumes and feeds) become markdown links pointing at the sibling concept files, which is the crux of the integration: the graph's edge structure becomes a navigable document graph.
Below is the complete generated concept for the art-01 node (AP2 Mandate-Chain Validator), using real data from chaingraph.json.
--- type: DecisionTool title: AP2 Mandate-Chain Validator description: > Validates AP2 v0.2 Intent→Cart→Payment mandate trio: signature-chain integrity, scope/limit consistency, TTL/expiry, over-spend detection, Human-Not-Present autonomous-agent flows. Publishes conformance test-vector fixtures. resource: https://ainumbers.co/chaingraph/art-01-ap2-mandate-chain-validator.html tags: - payment_mandate - wave-1 - mcp:validate_ap2_mandate_chain timestamp: 2026-06-18T00:00:00Z --- # AP2 Mandate-Chain Validator Exports a decision: a conformance verdict over an AP2 v0.2 Intent→Cart→Payment mandate chain, including signature integrity, scope limits, TTL, and Human-Not-Present flow checks. Call this tool via MCP and receive a signed OCG artifact — not an advisory. ## Inputs - intent_mandate — AP2 v0.2 Intent Mandate object (JSON) - cart_mandate — AP2 v0.2 Cart Mandate object (JSON) - payment_mandate — AP2 v0.2 Payment Mandate object (JSON) - agent_context — optional: HNP flag, agent DID, delegation depth ## Outputs - conformance_verdict — PASS / FAIL / PARTIAL per check category - signature_chain_valid — boolean - scope_violations — array of detected scope or limit breaches - compliance_flags[] — per-framework flags (AP2 v0.2, HNP-001) - execution_hash — SHA-256 over sorted-key JSON of inputs + outputs ## Chains **Consumes:** _(root tool — no upstream dependencies)_ **Feeds:** - [Agent Spend-Policy Simulator](art-02-agent-spend-policy-simulator.md) - [x402 Settlement Cost & Finality Modeler](art-03-x402-settlement-modeler.md) - [Agent Identity & Authorization Attestation Checker](art-04-agent-identity-attestation-checker.md) - [ACP Checkout Conformance Validator](art-12-acp-checkout-conformance-validator.md) - [AP2 Prompt Template Generator](../tools/ptg-01-ap2-prompt-template-generator.md)
The Chains section is the structural heart of the integration. The markdown links in "Feeds" are exactly the edges from the node's feeds[] array in chaingraph.json, resolved to relative paths within okf/tools/. An agent or static site following these links traverses the same graph that OCG's execution engine traverses at runtime. The two graphs are synchronized by the generator; they cannot drift as long as CI runs on every index change.
The ptg-01 (AP2 Prompt Template Generator) node has "consumes": [] and "feeds": ["ALL"]; it is a downstream sink that can receive any artifact. Its generated concept document's Chains section reflects this: "Consumes: (standalone, accepts any upstream artifact)" and "Feeds: all tools in the suite." The "ALL" sentinel is the one edge value the generator resolves specially, expanding it to a prose statement rather than a list of links, because enumerating every node would make the concept file noisy and brittle to index changes.
The OKF bundle is produced by a single Node.js script (generate-okf.mjs) that reads chaingraph.json, iterates every node where status === "live", and writes one .md file per node. The script runs in CI on every push that modifies the index, so the bundle is always in sync and never hand-maintained.
The field mapping from graph index to OKF concept element:
| chaingraph.json field | OKF concept element | Notes |
|---|---|---|
| tool_id | File path (okf/tools/{tool_id}.md) + concept identity |
OKF convention: path is identity. Changing tool_id renames the file and breaks inbound links. |
| display_name | Frontmatter title: + h1 heading in body |
Human-readable name. Safe to change without breaking links (only the frontmatter title changes, not the file path). |
| description | Frontmatter description: |
Verbatim from index. Folded YAML scalar, no markdown. |
| url | Frontmatter resource: |
OKF standard field: the canonical URL of the resource being described. |
| mandate_type + wave + mcp_name | Frontmatter tags: array |
E.g. ["payment_mandate", "wave-1", "mcp:validate_ap2_mandate_chain"]. Enables filtering by domain, generation cohort, or MCP tool name. |
| consumes[] / feeds[] | Markdown links in the body Chains section | Each entry resolved to a relative path: {tool_id}.md. The "ALL" sentinel renders as prose. This is the graph edge → document link transformation. |
| status: "live" | Included in bundle | Nodes with status !== "live" are excluded. The bundle always reflects the live production graph. |
The complete generator script:
#!/usr/bin/env node // generate-okf.mjs // Reads chaingraph.json → writes okf/tools/{tool_id}.md for every live node. // Run: node generate-okf.mjs // Requires Node 18+ (fs/promises, no external deps) import { readFile, writeFile, mkdir } from "fs/promises"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; const __dir = dirname(fileURLToPath(import.meta.url)); const INDEX = join(__dir, "chaingraph.json"); const OUT_DIR = join(__dir, "okf", "tools"); const NOW_ISO = new Date().toISOString().replace(/\.\d{3}Z$/, "Z"); // Build a lookup: tool_id → display_name (for resolving consumes/feeds labels) function buildLookup(nodes) { const map = {}; for (const n of nodes) map[n.tool_id] = n.display_name; return map; } // Render YAML frontmatter for a node function frontmatter(node) { const desc = node.description.replace(/\n/g, "\n "); // indent for YAML block scalar const tags = [ node.mandate_type, `wave-${node.wave}`, `mcp:${node.mcp_name}`, ].map(t => ` - ${t}`).join("\n"); return [ "---", `type: DecisionTool`, `title: ${node.display_name}`, `description: >`, ` ${desc}`, `resource: ${node.url}`, `tags:`, tags, `timestamp: ${NOW_ISO}`, "---", ].join("\n"); } // Resolve an edge array to markdown links or prose function edgeLinks(ids, lookup, label) { if (!ids || ids.length === 0) { return `**${label}:** _(root tool — no upstream dependencies)_`; } if (ids[0] === "ALL") { return `**${label}:** _(standalone — accepts any upstream OCG artifact)_`; } const links = ids.map(id => { const name = lookup[id] ?? id; return `- [${name}](${id}.md)`; }).join("\n"); return `**${label}:**\n${links}`; } // Render full concept markdown for a node function renderConcept(node, lookup) { return [ frontmatter(node), "", `# ${node.display_name}`, "", `Exports a decision via [\`${node.mcp_name}\`](${node.url}). ` + `Call this tool through the OpenChainGraph MCP server and receive a ` + `signed OCG artifact with an \`execution_hash\` — not an advisory.`, "", "## Inputs", "", `See the tool's input schema: <${node.url}#manifest>`, "", "## Outputs", "", "- `execution_hash` — SHA-256 over sorted-key JSON of inputs + outputs", "- `compliance_flags[]` — per-framework PASS / FAIL / PARTIAL verdicts", "- `audit_signature` — Ed25519 signature over the execution hash", "- `chain` — parent_hashes[], parent_tool_ids[], chain_depth", "", "## Chains", "", edgeLinks(node.consumes, lookup, "Consumes"), "", edgeLinks(node.feeds, lookup, "Feeds"), ].join("\n"); } // Main async function main() { const raw = await readFile(INDEX, "utf8"); const index = JSON.parse(raw); const live = index.nodes.filter(n => n.status === "live"); const lookup = buildLookup(live); await mkdir(OUT_DIR, { recursive: true }); let count = 0; for (const node of live) { const filename = join(OUT_DIR, `${node.tool_id}.md`); const content = renderConcept(node, lookup); await writeFile(filename, content, "utf8"); count++; } console.log(`[generate-okf] wrote ${count} concept files → ${OUT_DIR}`); console.log(`[generate-okf] index version: ${index.version}, updated: ${index.updated}`); } main().catch(err => { console.error(err); process.exit(1); });
Add this to your CI pipeline as a step that runs after any change to chaingraph.json. The generated files can be committed back to the repository or published as a static bundle; either approach keeps the knowledge layer in sync with the live graph.
In GitHub Actions: add a job step run: node generate-okf.mjs after checkout, then git add okf/ && git commit -m "chore: regenerate OKF bundle" --allow-empty || true to commit any changes. The --allow-empty || true guard prevents the step from failing if nothing changed. Trigger the workflow on paths: ['chaingraph.json'] to limit runs to index changes only. The bundle is fully reversible: deleting okf/ and rerunning the script produces an identical result from the same index version.
OKF reserves two filenames at the bundle root: index.md (progressive-disclosure entry point) and log.md (chronological generation history). A compliant OKF consumer knows to look for these files first. The generator writes them automatically; they may be lightly customized but must not be deleted.
The root index.md:
--- type: KnowledgeIndex title: OpenChainGraph Tool Concepts description: > OKF companion bundle for the AINumbers ChainGraph suite. One concept file per live tool — auto-generated from chaingraph.json. Graph edges (consumes/feeds) are markdown links: follow them to plan a decision chain before calling any MCP endpoint. resource: https://ainumbers.co/chaingraph/chaingraph-hub.html tags: - openchain-graph - v0.3 - okf-companion timestamp: 2026-06-18T00:00:00Z --- # OpenChainGraph Tool Concepts This bundle maps every live tool in the AINumbers ChainGraph suite to an OKF concept document. Use it to understand what each tool does, what it consumes, and what it feeds — then invoke the real MCP endpoint at `https://mcp.ainumbers.co/mcp`. ## By mandate type - [Payment Mandate tools](mandate-types/payment_mandate.md) — AP2 v0.2 mandate validation and related - [Payment Policy tools](mandate-types/payment_policy.md) — spend policy simulation - [Settlement Mandate tools](mandate-types/settlement_mandate.md) — x402 and FX settlement - [Compliance Mandate tools](mandate-types/compliance_mandate.md) — KYA, EU AI Act, sanctions - [Prompt Template tools](mandate-types/prompt_template.md) — artifact-to-LLM prompt generation ## All tools (alphabetical) See [tools/index.md](tools/index.md) for the full list. ## What this bundle is not These concept documents describe tools. They are not OCG decision artifacts. They carry no `execution_hash`, no `audit_signature`, and no compliance verdict. OCG artifacts are produced at runtime by the tools themselves — they are never stored in this knowledge bundle.
The log.md, one chronological line per CI run:
# OKF Bundle Generation Log Each line records a bundle regeneration. Format: `- {ISO date} — generated {N} concepts from chaingraph.json v{version}` - 2026-06-18 — generated 48 concepts from chaingraph.json v1.10.0
The log.md gives any consumer a quick audit trail: how many concepts exist, what index version they were generated from, and when. The generator appends a new line on each run rather than overwriting, so the full history accumulates. If the bundle is ever regenerated from scratch (e.g. after a tool_id rename), the log records the regeneration date and the new concept count.
An OKF consumer (an agent planner, a static site generator, a search index crawler) reads the bundle to build a route through the tool graph before calling any MCP endpoint. The reading process is: start at okf/index.md, follow the mandate-type link to narrow the domain, then follow concept file links (which mirror consumes/feeds edges) to assemble a chain. Once the chain is planned, execute it via the MCP server at https://mcp.ainumbers.co/mcp.
There are two discovery surfaces in OCG v0.3 and they serve different audiences:
| Surface | Format | Primary audience | Use case |
|---|---|---|---|
| DCAT 3.0 graph index | chaingraph.json, machine-readable JSON with typed edges |
Crawlers, automated agent planners, tooling that ingests the full schema | Programmatic chain assembly: parse nodes[], resolve consumes/feeds, build a graph object in memory, traverse it |
| OKF companion bundle | okf/tools/*.md, markdown with YAML frontmatter |
Humans learning the suite; agents with a markdown-first knowledge interface; static sites and search engines | Narrative planning: follow concept links to understand tool semantics, read descriptions, then invoke MCP tools with confidence |
A JavaScript snippet illustrating how an agent planner walks OKF links from a start concept to discover the downstream chain:
/** * walkOkfChain(startConceptMd, fetchFn) * startConceptMd — the markdown text of the starting concept file * fetchFn — async (relativePath: string) => markdown text * * Resolves the "Feeds" links from the start concept, * fetches each linked concept, and returns a flat ordered list * of { toolId, displayName, mcpTag, resourceUrl } for chain planning. * * This mirrors walking chaingraph.json's feeds[] edges — the OKF links * are the same graph, expressed as navigable markdown. */ async function walkOkfChain(startConceptMd, fetchFn) { const visited = new Set(); const chain = []; async function visit(md, depth) { if (depth > 6) return; // guard against deep cycles // Extract title and mcp tag from frontmatter const titleMatch = md.match(/^title:\s*(.+)$/m); const mcpMatch = md.match(/^\s*-\s*mcp:(\S+)/m); const resMatch = md.match(/^resource:\s*(.+)$/m); const displayName = titleMatch?.[1]?.trim() ?? "Unknown"; const mcpTag = mcpMatch?.[1] ?? ""; const resourceUrl = resMatch?.[1]?.trim() ?? ""; chain.push({ displayName, mcpTag, resourceUrl }); // Find all markdown links in the ## Feeds section const feedsSection = md.match(/## Chains[\s\S]*?\*\*Feeds:\*\*([\s\S]*?)(?=\n##|\n---|\Z)/)?.[1] ?? ""; const linkRe = /\[([^\]]+)\]\(([^)]+\.md)\)/g; let match; while ((match = linkRe.exec(feedsSection)) !== null) { const relativePath = match[2]; if (visited.has(relativePath)) continue; visited.add(relativePath); try { const nextMd = await fetchFn(relativePath); await visit(nextMd, depth + 1); } catch { /* skip missing concepts */ } } } await visit(startConceptMd, 0); return chain; } // Usage — plan a chain starting from AP2 Mandate-Chain Validator: const chain = await walkOkfChain( await fetch("https://ainumbers.co/chaingraph/okf/tools/art-01-ap2-mandate-chain-validator.md").then(r => r.text()), path => fetch(`https://ainumbers.co/chaingraph/okf/tools/${path}`).then(r => r.text()) ); // → [{ displayName: "AP2 Mandate-Chain Validator", mcpTag: "validate_ap2_mandate_chain", ... }, ...] // Now call each mcp_name tool in order via https://mcp.ainumbers.co/mcp
The OKF bundle is the narrative planning surface: it is slower to traverse than the JSON index (one HTTP fetch per concept) but richer in human-readable context. For programmatic chain assembly in a tight loop, parse chaingraph.json directly and use its consumes/feeds arrays. Use the OKF bundle for onboarding, documentation, static site generation, and agent planners that benefit from reading concept prose before deciding on a chain. The two surfaces describe the same graph; choose the one that fits the consumer's interface.
Several properties of the OKF integration are non-negotiable constraints, not configuration options. They are stated here as callouts because violating any of them produces a broken or misleading integration.
OCG decision artifacts (the signed JSON objects with execution_hash, audit_signature, and compliance_flags[]) must never appear in, reference, or be embedded in the OKF bundle. Concepts describe tools; artifacts record decisions. If a concept file starts carrying execution hashes or compliance verdicts, the knowledge layer has collapsed into the proof layer, and consumers can no longer distinguish "what this tool can do" from "what it decided on a specific run." Keep the okf/ directory strictly for concept documents.
The Open Knowledge Format was published by Google on 2026-06-12 (GoogleCloudPlatform/knowledge-catalog repository, Google Cloud blog). It is an early-stage open specification at v0.1. The OCG companion bundle adopts OKF as an optional informational layer only. Nothing in OCG's verification path depends on OKF, and the companion bundle is off the verification critical path entirely. If OKF evolves in ways that break the current frontmatter schema, the generator script is the only thing that needs updating; no OCG artifact is affected.
Every file under okf/tools/ is regenerated from chaingraph.json on every qualifying CI run. The bundle is fully reversible: delete okf/tools/ and rerun generate-okf.mjs to restore it identically from the same index version. This means the OKF bundle has zero maintenance burden: tool descriptions, chain edges, and MCP names stay current automatically. The only maintenance touch points are the generator script itself and the hand-editable narrative files (okf/index.md, okf/mandate-types/*.md).
The bundle and the index must never drift. If a tool is added, renamed, or retired in chaingraph.json but the OKF bundle is not regenerated, concept files will reference non-existent tools or miss new ones: broken links and stale narratives. The CI step (§4) guards against this by triggering on paths: ['chaingraph.json']. If you publish the bundle outside CI (e.g. a local preview), run node generate-okf.mjs immediately after any index edit.
Six steps to wire up the OKF companion bundle end-to-end, from generator to consumer. Each step is independently verifiable.
| Step | Action | Tool / verification |
|---|---|---|
| 1 | Point generate-okf.mjs at chaingraph.json and run it locally. Confirm that okf/tools/ contains one .md file per live node and that okf/index.md and okf/log.md exist. |
node generate-okf.mjs → ls okf/tools/*.md | wc -l should equal the count of live nodes in the index |
| 2 | Add the generator as a CI step triggered on changes to chaingraph.json. Commit the generated okf/ directory back to the repository so it is versioned alongside the index. |
GitHub Actions: on: push: paths: ['chaingraph.json']; confirm the workflow creates a chore: regenerate OKF bundle commit on the next index change |
| 3 | Publish okf/ at a stable URL alongside the DCAT graph index. The bundle should be reachable at the same base path as chaingraph.json so relative links between concept files resolve correctly in browsers and agents. |
Fetch https://ainumbers.co/chaingraph/okf/tools/art-01-ap2-mandate-chain-validator.md: expect HTTP 200 with correct frontmatter |
| 4 | Wire your OKF consumer (agent planner, static site, search index) to the bundle. For agents: start at okf/index.md; for search indexers: crawl okf/tools/; for static sites: render the markdown with frontmatter as structured pages. |
Consumer successfully reads okf/index.md, follows a mandate-type link, and arrives at a tool concept file with correct Chains links |
| 5 | Follow consumes/feeds markdown links in concept files to plan a decision chain. Verify that the linked filenames match the tool_id values in chaingraph.json for every live node: no broken links, no missing concepts. |
Run a link-checker against okf/tools/: every [...](*.md) link must resolve to a file that exists in the same directory |
| 6 | Execute the planned chain by calling each MCP tool in consumes/feeds order via https://mcp.ainumbers.co/mcp. Keep the OKF concepts and the resulting OCG artifacts strictly separate: concepts in okf/, artifacts as ephemeral runtime output only. |
Confirm no execution_hash or audit_signature fields appear in any file under okf/; confirm OCG artifacts are never written to okf/ by any pipeline step |
The OKF integration requires no OKF SDK, no Google Cloud dependency, no special runtime, and no changes to the OCG tool implementations. The generator is a single Node.js script with no external npm dependencies (uses only built-in fs/promises and path). OKF consumers need only the ability to read markdown files: any HTTP client, any static site generator, any agent that can fetch text will work. The companion bundle is an additive informational layer: the entire OCG suite functions identically whether the OKF bundle exists or not.