TL;DR

  • Giving an agent write access to a wiki is a twenty-minute job. The interesting work is stopping it from filling the wiki with plausible sludge.
  • Four page types, each with a contract about what it must contain. An agent writing a runbook and an agent writing a reference page are doing different jobs and need different rules.
  • Staleness is a field, not a vibe. Every page carries who wrote it, when, and how it was verified. Unverified pages are visibly second-class.
  • The write gate is an environment variable, off by default. Read is free; write is a decision.
  • Incidents become pages, or the incident was wasted. That’s the one rule I’d keep if I could only keep one.
  • Things a wiki can’t hold — PDFs, images, rendered one-pagers I need to share with someone outside the cluster — go to a small auth-gated artifact host instead. Don’t paste binaries into a wiki.

The easy part

I have a self-hosted wiki with a GraphQL API and a few hundred pages. Wiring an agent into it took about two hundred lines of Python — a small MCP server with search, read, list, create, and update, flattening the API’s nested responses into markdown so the agent gets text instead of JSON soup. I wrote about the mechanics of that server, and two others, in the MCP server cookbook.

That part works. Agents can find docs, read them, and write them. Which immediately produced a problem I didn’t anticipate: the wiki got worse.

Not wrong, exactly. Longer. Every page an agent touched grew a preamble, a summary, a “Key Considerations” section, and a closing paragraph restating the opening one. Real information got diluted with the kind of prose that reads fine and tells you nothing. And because the agent wrote confidently, stale pages stopped looking stale.

An internal knowledge base that’s plausible but unreliable is worse than no knowledge base, because you stop verifying. That’s the failure mode I spent August fixing, and none of the fixes are about the model.

Four page types, four contracts

The single biggest improvement was refusing to have one “page” concept. There are four, and each one has a contract the writer must satisfy.

1. Runbook. How to do a specific operational task. Contract: numbered steps that can be followed by someone with no context, the exact commands, expected output for each step, and an explicit “how to tell it worked” at the end. No background, no rationale, no history. If a step needs judgement, the runbook says stop and ask rather than describing the judgement.

2. Reference. Current state of a system. Contract: what it is, where it runs, what depends on it, how to reach it, and a verified: date. Reference pages are the ones that rot fastest and hurt most when they do, so they get the strictest staleness treatment.

3. Lesson. Something that went wrong and what we learned. Contract: symptom as observed, the wrong hypothesis (this field is mandatory and it’s the most valuable one), actual cause, fix, and how to recognise it next time. Written after an incident, never before.

4. Decision. Why something is the way it is. Contract: the question, the options considered, what was chosen, and — critically — what would make us revisit it. A decision page without a revisit trigger is just an opinion with a timestamp.

Four types, four templates, and the write tool asks which one it’s producing. This sounds bureaucratic for a one-person operation. In practice it’s the opposite: the contract tells the agent what to leave out, which is the instruction that improves agent-written docs the most. “Runbooks contain no background” removed roughly a third of the words and none of the information.

Staleness is a field

Every page carries a small header:

author:    agent | human
written:   2026-08-04
verified:  2026-08-04 (ran the steps on the bench box)
expires:   90d

Four fields, and each one earns its place.

author distinguishes “an agent inferred this from the code” from “a human did this and it worked.” Both are useful; they are not the same claim and should never look the same.

verified is the one that matters, and it’s separate from written on purpose. An agent can write a runbook by reading the source. That’s a draft. It becomes verified when someone — human or agent — actually executed the steps and reported the outcome. Unverified pages render with a banner saying so.

expires is a soft deadline. Reference pages get 90 days, runbooks 180, lessons and decisions never expire because they’re historical claims about the past. A scheduled job lists expired pages once a week. It doesn’t delete anything; deletion is a human call. It just makes the rot visible, which is enough, because rot is only dangerous while it’s invisible.

That weekly list is the highest-value automation in the whole setup, and it’s about fifteen lines of code.

Write is a decision, read is free

The write tools check an environment variable and refuse if it isn’t set:

if not os.getenv("MCP_WRITE"):
    return "ERROR: write mode disabled. Set MCP_WRITE=1 to enable."

Crude, and correct. The overwhelming majority of agent interactions with the knowledge base are reads — an agent looking up how a system works before touching it. Reads should be frictionless. Writes should require me to have decided, in this session, that documentation is the task.

The alternative — always-on writes — produces a specific pathology I saw before I added the gate: an agent finishing a task and then “helpfully” documenting it, on its own initiative, in a new page that duplicates two existing pages. Three pages now describe the same subsystem slightly differently. Which one is true? All of them were, when written.

There’s a second, harder-edged rule for updates: an agent may append to a page or correct a factual error, but replacing a page wholesale needs a human. Wholesale rewrites are where institutional memory quietly disappears — the awkward caveat that someone added three years ago because of an outage gets smoothed away by a tidier version, and nobody notices until the outage happens again.

Incidents become pages

If I could keep one rule, it’s this one: every incident produces a lesson page, and the page cites the incident.

The mechanism is deliberately low-tech. When something breaks and gets fixed, the agent that helped fix it writes the lesson page while the context is still live: symptom, wrong hypothesis, real cause, fix, recognition signature. I review it, mostly to check the wrong-hypothesis field is honest, and it goes in.

Why that field matters: the symptom-to-cause mapping is what you can look up. The wrong hypothesis is what you’d have believed instead, and it’s the thing that actually saves the hour. One of mine reads, roughly, “network capture showed the packets arriving, so the network looked fine — but packet capture taps before the firewall, so a dropped packet still shows up in the capture.” The cause was a firewall rule. The lesson is that my diagnostic tool was lying to me in a specific, repeatable way. No amount of reading the firewall config would have taught me that; only having been wrong does.

Pages like that are the ones I actually return to. They also age well, because they’re claims about the past, which is the only kind of claim that doesn’t rot.

What the wiki can’t hold

A wiki is for text. About a third of what I need to hand someone isn’t text: a rendered one-page summary, a PDF, a set of photos, a case-study document that someone outside my network needs to open in a browser and can’t be emailed a 40MB attachment of.

Pasting those into a wiki works badly — binaries bloat the backing store, versioning is meaningless, and access control is page-shaped rather than file-shaped. So they go somewhere else: a small artifact host, objects in S3-compatible storage, served through the cluster’s ingress behind single-sign-on. Publishing is one command that uploads the file, regenerates an index page, and hands back a URL.

Two modes, and the distinction is the entire security model:

  • Private (default). Behind SSO. Two accounts can open it. This is where anything with a real name, a client detail, or a dollar figure lives.
  • Public. An explicit /pub/ prefix, no auth, shareable with anyone. Requires me to have typed the word “public”.

Default-private with an explicit opt-in is the only arrangement I trust myself with. The inverse — public by default with an opt-in to lock it down — fails the first time someone is in a hurry, and the failure is permanent because links get forwarded.

The same artifact host is how I collaborate with someone outside my setup entirely. They send me a document, an agent on my side renders and publishes it, and they get a link that works on their phone. No shared drive, no account provisioning, no VPN. It’s a surprisingly good pattern for “I need one other person to see this one thing.”

Gotchas

Agents duplicate rather than update. Given a choice between finding the existing page on a topic and writing a new one, an agent will write a new one, because writing is easier than searching. Force a search step: the write tool should require a “I looked for existing pages and here’s what I found” argument. Trivial to implement, dramatically fewer duplicates.

Flat structures, fewer hallucinations. When the tool returns markdown lists rather than nested JSON, the agent’s summaries get noticeably more accurate. My theory is that deeply nested responses give a model too many chances to attach the wrong value to the wrong key. Whatever the reason, flatten your tool output.

“Verified” must mean executed. Not “reviewed”, not “looks right”. If nobody ran the steps, it’s unverified, and mislabelling it destroys the value of the field for every other page.

Don’t let the knowledge base become the changelog. Git already records what changed and when. The wiki records what’s true now and what we learned. Every time I’ve blurred that line, the wiki filled with narrative history nobody reads.

A weekly staleness report is worth more than any writing improvement. Fifteen lines. Lists expired pages. Nothing else in this post has as good a ratio.

Where this sits

A few hundred pages, four page types with contracts, staleness as a visible field, writes gated behind a flag, incidents converted into lesson pages on the day, and an auth-gated artifact host for everything that isn’t text.

The agents write most of it now. What changed isn’t their prose — it’s that the system makes a bad page look bad, which is the only thing that reliably keeps a knowledge base honest whether the author is a model or a tired human at 11pm.