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
Links
- OpenSLO, object model naming donor, no runtime dependency
- Open Knowledge Format, the frontmatter-graph convention this builds on
- Knowledge Context Protocol, where the
valid_from/valid_until/supersedesfield names come from - codeberg.org/daniel-ciaglia/slo.okf
