Every SRE team has a runbook that lies. It describes the architecture from before the migration, names a dashboard that was deleted, and ends with “escalate to Dave,” who left in 2024. Documentation rot is so universal that “the runbook is already lying to you” has become shorthand for the whole genre.
For years the rot was survivable, because the reader was a human who’d squint at the stale instruction and route around it. That defense is now leaving the building: we’re wiring runbooks into retrieval pipelines and handing the answers to on-call agents — mine included. Retrieval-augmented generation turns your runbook corpus from documentation into behavior. Which means retrieval quality just became a production concern, and the runbook that lies is no longer an annoyance. It’s an incident with a delay timer.
This post is about making runbook retrieval trustworthy enough to sit under an agent. It comes with code: runbook-rag-starter (Apache-2.0), the smallest useful version, plus the hardening path in the order the failures actually bite.
Start insultingly simple — on purpose
The starter is about 40 lines of Python around three decisions: a folder of Markdown runbooks, embeddings in a single SQLite file via sqlite-vec, and a CLI — runbook-rag index ./runbooks, then runbook-rag ask "what do we do when checkout-svc latency spikes?". Top-k chunks get stuffed into the prompt; the answer cites the files it used. No Postgres, no vector service, no Docker.
It is deliberately mediocre, and the README says so. Each file is one chunk, so a 50-page runbook is one vector. There’s no keyword fallback, no reranker, no freshness signal, and if retrieval comes back empty the model will improvise. These aren’t oversights — they’re the curriculum. Run your real on-call questions through it, watch exactly where it fails, and you’ll know which of the following sections to build first, with evidence instead of a vendor’s roadmap. (Vector embeddings doing the heavy lifting here, if you want the primer.)
The failures cluster into five patterns, and they’re predictable enough to be a checklist.
Where chatbot RAG intuitions fail on-call
1. On-call queries are full of exact strings. “What’s the runbook for payments-gw-prod-7?” Pure cosine similarity is spectacular at paraphrase and mediocre at identifiers — hostnames, error codes, ticket IDs, flag names get embedded into mush. Chatbot corpora mostly dodge this; on-call queries are made of it. The fix is hybrid retrieval: BM25 keyword search alongside the vector search, merged before ranking. This is the single highest-value upgrade to the naive version, and it’s usually the first failure you’ll observe in replay.
2. Freshness is a correctness property. A news chatbot serving last month’s article is mildly annoying. A retrieval layer serving the pre-migration failover procedure is actively harmful — the words are fluent, the steps are confident, and the topology they describe no longer exists. Runbook RAG needs freshness as a first-class signal: a last_verified date on every document, a staleness penalty at ranking time, an age flag in the answer (“this runbook was last verified 14 months ago”), and expiry for anything past your tolerance. If the corpus has no verification dates, that metadata backfill is the project.
3. Retrieval must respect permissions. Runbooks contain topology, credentials-adjacent detail, and customer names. The moment retrieval sits behind an agent that anyone can query — a Slack bot, an on-call assistant — it will happily surface documents the asker couldn’t open. Permission-aware retrieval (filter by the requester’s ACLs at query time, not index time — people change teams) is table stakes for unified knowledge platforms precisely because retrofitting it is miserable.
4. The corpus is an attack surface. Once agents act on retrieved text, whoever can write to the runbook wiki can influence production actions. That’s memory-and-context poisoning — ASI06 in the OWASP agentic Top 10 — and the defense is treating runbook writes like code: reviewed changes, provenance on every document, and retrieval that surfaces where each answer came from so a poisoned source is findable and evictable rather than ambient.
5. Empty retrieval must not become fiction. When nothing relevant exists, a naive pipeline stuffs the prompt anyway and the model fills the silence — plausible, wrong, mid-incident. Require citations; make “no runbook found” an explicit, honorable answer; and log those misses, because the query log of unanswered on-call questions is the best runbook-writing backlog your team has ever had.
From retrieval to execution — slowly
Reading runbooks is the entry level. The 2026 tooling wave is pushing further — incident.io calls it “intelligent runbook execution”: context-aware workflows where the agent doesn’t just quote the procedure but runs it. That’s also where the blast radius lives, so the promotion path matters. The three-tier model that’s emerging as consensus — advisory → approval-gated → conditional autonomy — maps exactly onto the bounded-autonomy argument I’ve made before: each tier is earned with a measured track record, never granted by roadmap date.
The dependency is directional: execution trust is capped by retrieval trust. An agent with flawless judgment acting on a stale runbook is a flawless executor of the wrong procedure. Harden the retrieval layer first; it’s the foundation the autonomy tiers stand on. (And when the incident’s over, close the loop the other way — the postmortem that updates the runbook is what keeps the corpus worth retrieving from.)
Honest caveats
RAG does not fix wrong documentation — it distributes it more efficiently, with better production values. If your runbooks are rotten, retrieval is an amplifier, and the real fix is the boring loop where every incident review updates or retires the runbook it exercised. Measure retrieval quality separately from answer quality (replay real queries; check the right document lands in the top results) or you’ll tune the model to compensate for a search problem. And a starter repo is a starting point: sqlite-vec on one box is honest about what it is, and what it is not is a multi-tenant, permission-aware knowledge platform.
What to do Monday
- Clone the starter and index your real runbooks.
runbook-rag-starter, ten minutes, your actual corpus. The failures you see are your roadmap. - Replay 20 real on-call questions from your incident channel and score whether the right runbook lands in the top 3. That number is your retrieval baseline, and it’s probably lower than you think.
- Add
last_verifiedto your runbook template today. The metadata is free at write time and unaffordable to reconstruct later. - Route exact-identifier queries through keyword search before investing in anything fancier — hybrid retrieval is the biggest single jump in on-call retrieval quality.
- Log every empty retrieval. Each one is either a missing runbook or a missing alias for an existing one. Both are cheap to fix once you can see them.
The uncomfortable truth about on-call AI is that most of its quality ceiling is set before the model ever runs — by whether the right document exists, is current, and gets retrieved. Teams chase agent quality because it’s exciting, and ignore corpus quality because it’s chores. The chores are the product. Your agent is only ever as honest as the shelf you point it at.