SLO OKF - documenting SLI/SLO/alert/runbook chains without inventing yet another schema

At work I currently have to produce actual SLO definitions, the kind that get read at 2am by someone (or something) who is not me. So I went looking for a format instead of inventing my own.

I had OpenSLO on my radar for a bit, a solid object model for SLIs/SLOs/alerts. Then I came across Google’s Open Knowledge Format (OKF), a much more general “markdown with frontmatter, linked into a graph” convention.

OKF is upfront about who it’s written for: not just a human skimming docs, but an autonomous agent hopping through the same bundle, oncall bot or otherwise, following typed links instead of grepping prose.

Combining OKF and OpenSLO

OpenSLO wants to be executable: budgetingMethod, objectives[], the works. But most of what I actually need to write down is documentation about an SLO: target, rationale, who owns it, why 99.9% and not 99.99%. The Prometheus recording rule or Alertmanager rule that actually computes something already exists elsewhere and does not need to be reinvented in YAML.

So the rule became: a concept file computes nothing. type: SLO is prose with a target attached, not a spec. If you want the thing that evaluates burn rate, follow the resource field to the real Alertmanager rule.

OKF supplies the “prose in a graph” part almost for free: any .md with type frontmatter is a concept, done. What it does not supply is a typed-relationship vocabulary, links are just prose in OKF’s own spec, which is fine for a human skimming markdown and useless for a validator, or for an agent that needs to jump straight from an alert to its runbook without parsing sentences to find the link. So the vocabulary I wrote adds structured reference fields (slo.sli, alert.runbook, journey.slos, …) that a Python CLI checks for cardinality, orphans, and dangling links.

---
type: SLO
title: Checkout API availability SLO
sli: slis/checkout-availability
target: "99.9%"
time_window: 30d rolling
owner: checkout-team
reviewed: 2026-07-15
review_interval: 90d
---

Here’s the full VOCABULARY.md for reference.


After implementing a Critical Customer Journey and its dependecies, you’ll get something like this.

❯ tree -A bundle
bundle
├── alerts
│   ├── checkout-error-budget-burn.md
│   └── payment-latency-error-budget-burn.md
├── datasources
│   └── prometheus-prod.md
├── index.md
├── journeys
│   └── checkout.md
├── log.md
├── metrics
│   ├── checkout-requests-good.md
│   ├── checkout-requests-total.md
│   └── payment-latency-p95.md
├── runbooks
│   └── checkout-degraded.md
├── slis
│   ├── checkout-availability.md
│   └── payment-latency.md
├── slos
│   ├── checkout-availability-slo.md
│   └── payment-latency-slo.md
└── subsystems
    ├── cart-service.md
    ├── checkout-api.md
    └── payment-service.md

I tasked Claude to build a CLI (derived from Google’s reference implementation), and extended it by validating links and adding a review sub command.

❯ .venv/bin/okf-validator --help
usage: okf-validator [-h] {validate,review,visualize,index} ...

Validate and visualize OKF bundles for the SRE OKF vocabulary (see VOCABULARY.md).

positional arguments:
  {validate,review,visualize,index}
    validate            Check a bundle against VOCABULARY.md (field pass + graph pass).
    review              Flag concepts whose 'reviewed' (or 'created') date plus 'review_interval' has elapsed (VOCABULARY.md §2).
    visualize           Generate a self-contained HTML graph view of a bundle.
    index               Generate index.md files for progressive disclosure (OKF spec §6).

options:
  -h, --help            show this help message and exit

The whole bundle renders as a self-contained HTML graph too, click a node to see its frontmatter, rendered body, and typed links in and out:

A very important part: staleness

A pile of Markdown starts rotting the moment you save it. So every operationally dangerous concept (SLO, Alert, Runbook) is required to carry owner, reviewed, and review_interval. Today I added a review subcommand that walks the whole bundle and tells you who is overdue:

❯ .venv/bin/okf-validator review ../bundle
[ok] alerts/checkout-error-budget-burn.md (Alert) alerts/checkout-error-budget-burn: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] alerts/payment-latency-error-budget-burn.md (Alert) alerts/payment-latency-error-budget-burn: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] journeys/checkout.md (CustomerJourney) journeys/checkout: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] runbooks/checkout-degraded.md (Runbook) runbooks/checkout-degraded: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] slos/checkout-availability-slo.md (SLO) slos/checkout-availability-slo: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] slos/payment-latency-slo.md (SLO) slos/payment-latency-slo: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] subsystems/cart-service.md (Subsystem) subsystems/cart-service: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] subsystems/checkout-api.md (Subsystem) subsystems/checkout-api: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)
[ok] subsystems/payment-service.md (Subsystem) subsystems/payment-service: due in 90d (due 2026-10-13, based on reviewed: 2026-07-15, interval 90d)

9 concept(s) with a review_interval checked, 0 overdue, 0 unresolvable

Worth saying out loud: a green reviewed date is attestation, not correctness. Someone clicked “yep, still true”, it does not mean it still is. But an obviously stale runbook is at least honest about it, and that beats false confidence at 2am.

Where it stands

One worked example (a checkout journey, cart to payment to confirmation), a Python validator with a field pass and a graph pass, and an HTML graph viewer for browsing the result. No generators yet, Terraform/ArgoCD mapping is sketched but not built.


Generators

Terraform

I implemented Terraform modules for the 9 arche types to write bundle files from where the resources are defined.

  • If you create a database -> add it as subsystem
  • if you drive metrics through Datadog provider -> add it to the bundle

Check them out: generators/terraform/MAPPING.md


Footnotes