The problem

Coding agents treat documents as memory. Before an AI writes a line of your code, it reads the notes in your repository — and it believes them. When a source file changed three weeks ago and nobody updated the notes, the agent builds on an expired claim, confidently. You pay twice: once for the wrong code, and again in the tokens it takes to prove nothing broke.

Every tool I found guards the pull request. That protects your next commit. It does nothing about the documents already merged into main, which are already indexed and handed to every agent session, every day.

What Doc Governor does

It does not try to make every document correct. It decides which documents an agent is allowed to read at all.

Each document declares the source files it describes. When it is verified, those files are hashed — not dated. A date is worthless: "verified on the 1st" means nothing if the code changed on the 3rd. On every read, the hashes are recomputed against the working tree and compared. A document that was served one second ago becomes unreadable the moment a dependency changes, with no Doc Governor run in between. Nothing re-ran; the answer still changed.

How AWS makes it work

Strands Agents SDK builds the write path with GraphBuilder. Four constrained roles, split for privilege rather than throughput:

  • The Repair Planner reads one document plus only the changed files that document declared, and returns a bounded plan. It cannot write.
  • The Evidence Auditor is deliberately never shown a document's own status line or verified date — a document claiming to be verified is trying to answer the question being asked about it.
  • The Conflict Resolver sees only the conflicting documents.
  • The Contract Drafter is the only role that may propose prose, and PrivilegeError makes it impossible to construct for a status, evidence, decision, or protected document. That is code, not a prompt instruction.

Amazon Bedrock with Amazon Nova Lite (us.amazon.nova-lite-v1:0) runs every model call. Scoped @tool closures expose only each node's assigned evidence, and a BeforeToolCallEvent hook cancels a disallowed or over-budget call before it executes — a boundary, not an audit log.

GitHub OIDC means no long-lived AWS keys exist anywhere. GitHub Actions trades a short-lived identity token for temporary credentials, and that role can invoke exactly one Nova Lite inference profile. Pull requests from forks get no AWS identity at all.

What I learned

Model output proposes; deterministic code decides. Every identifier the Drafter writes must appear literally in a source file it cites — one invented function name discards the whole draft. Tests prove software runs; they do not prove prose is true, so repair is never approval. A separate read-only reviewer session has to sign off, and its receipt is bound to the exact document hash, dependency fingerprint, and session id.

Challenges

Letting an AI rewrite memory recreates the exact risk I was trying to stop. The hardest bug was friendly error messages: the obvious refusal text names the tool the agent tried to call, but that name is a string the model chose — an agent that has read a governed document can smuggle a sentence of it out through a fake tool name printed into a public trace. The refusal now names the role, never the tool.

Verify it yourself

269 tests, no AWS credentials needed. python scripts/demo.py --mcp-stdio repairs the affected documents, then refuses the unsupported ones through the real MCP server with zero served characters. A separate live run is recorded in submission/: no model doubles, an 89-second publish, an independent reviewer receipt, and a second agent reading the repaired document back through the gate.

It governs itself — the pull request that added this blocked its own README as protected content until I approved it.

Built With

  • amazon-bedrock
  • amazon-nova-lite
  • aws-iam
  • codex
  • github-actions
  • github-oidc
  • mcp
  • model-context-protocol
  • multi-agent
  • python
  • strands-agents
Share this project:

Updates

Submission history