SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

Cambium: govern the docs your agents write

Agent-written docs drift into stale claims and contradictory rules. Cambium answers with a governance kernel and append-only receipts. Who needs it.

What breaks when agents write your documentation

When agents write and update your documentation, governing that corpus becomes a real job. The corpus grows faster than anyone reviews it, so within a few weeks you have stale claims, rules contradicted three files away, no record of who decided what, and no reliable way to tell which file is authoritative. Cambium is one concrete answer to that: a governance standard plus a reference toolset for knowledge repositories maintained with LLM (large language model) agents.

Be honest about scale before going further. Most repositories do not need this. If you run one agent against one repository, skip ahead to the section on who should not adopt a governance kernel, decide there, and save yourself the rest.

Why more markdown does not fix it

The usual reply to documentation drift is another file: AGENTS.md for the agent, CONTRIBUTING.md for the humans. That works while one person reviews every diff. It stops working for a mechanical reason. Nothing inside a markdown file can say which of two contradictory files is authoritative, and nothing in it records that a rule was decided rather than guessed. An agent reading two conflicting instructions picks one of them. Usually it picks whichever sits nearest in its context window, which is an artifact of ordering and not a judgment about your intent. That is the same mechanism behind the instructions agents quietly skip.

If your answer to drift so far has been better file layout, that answer is not wrong. Separating the machine-facing rules from the human-facing prose, which is the point of keeping AGENTS.md and HUMAN.md apart, removes contradictions that one crowded file invites. Pushing per-package rules down the tree, as in nested AGENTS.md files across a monorepo, removes more. Both reduce contradictions between files. Neither produces a record of decisions, and neither helps an agent that was interrupted halfway through a long task and has to work out where it stopped.

What Cambium actually is

Cambium describes itself as a governance standard and reference toolset for knowledge repositories maintained with LLM agents. It is Python, and its tool documentation states that all shipped Python code uses the standard library, so there is nothing to install beyond the repository itself. The license is split by path: Apache-2.0 for Tools/, and CC BY 4.0 (Creative Commons Attribution) for the standard text in kernel/, Card/ and Read Set/. Five parts carry the design.

  • The kernel (kernel/) holds the normative rules: cross-domain governance semantics and invariants, plus named extension points. A profile may fill an extension point. It cannot switch off a kernel requirement.
  • Cards (Card/) are short curated checklists for a chosen task route. The README is blunt that they are "not routes or a second copy of the standard". When a Card is unclear or disputed, its read-back hook resolves through the paired Read Set to the canonical owner, so a checklist can never quietly become the rule.
  • Read Sets (Read Set/) declare in machine-resolvable form which canonical material an actor must have read before acting.
  • The profile (profiles/) is per repository. It states scope, language, architecture, roles, and which extensions are allowed here.
  • .cambium/ is yours. It holds your governance identity, current task state, the Queue, plans, receipts and recovery evidence. Cambium's instruction is to never hand-edit canonical state, because revisions, hashes, receipts and recovery evidence are written together by one owning tool, and editing the file directly leaves the other four out of step.

Under .cambium/ sit three runtime ledgers. The Coverage Ledger records which knowledge objects exist and what their disposition is. The Required Queue holds batch manifests, dependencies and lifecycle states. The Progress Ledger holds the task contract, the whole-task state and the checkpoint. The Progress Ledger is the part that answers "where was I", which is the question an agent with a fresh context window cannot answer from memory.

Pin to a commit, not to main

Cambium's repository was first published on 4 August 2026, and as of 1 September 2026 it has no releases and no tags. Commits land most days, and recent ones move tool interfaces around. Pinning therefore matters more than usual, because an unpinned adoption records a moving target.

git clone https://github.com/KimGLee/Cambium.git
cd Cambium
git log -1 --format=%H

Take the commit hash that prints, check it out, and write it down.

git checkout 78868d038e27ea2856f39934fac92cc046abaeac

That hash was the tip of main on 1 September 2026. Yours will differ, and that is fine as long as it is a hash. The reason to record it is apply_profile_adoption.py, further down: it takes an --upstream-ref argument, and that is where the pin becomes part of your repository's own state. Pass main there and a later audit cannot tell which version of the standard you adopted.

Adopting it on one repository

Every writing tool follows the same convention. Without --apply you get a dry-run plan and nothing changes. With --apply the tool authorizes only the one transaction it names. Read the plan before you run the second command.

python3 Tools/scaffold_profile.py . --profile-id my-profile
python3 Tools/scaffold_profile.py . --profile-id my-profile --apply

The positional argument is the root of the repository being governed, written as . in Cambium's own documentation. Next, find out what the profile still needs before it can be adopted.

python3 Tools/profile_onboarding_status.py . --profile-id my-profile --json
python3 Tools/check_profile.py profiles/my-profile

profile_onboarding_status.py is the tool that lists the configuration questions you have not answered yet, and --json makes that list machine-readable for an agent. Answer the questions in the profile itself. A comment in a pull request is not state. The last step binds your repository to a specific upstream Cambium.

python3 Tools/apply_profile_adoption.py . --plan <plan>.yaml \
  --upstream-root ~/src/Cambium \
  --upstream-ref 78868d038e27ea2856f39934fac92cc046abaeac

That is the dry run. Append --apply to the same line to commit it. Note that two roots are in play: the repository you are governing, and the Cambium checkout you are governing it from.

Now watch the exit codes, because Cambium uses three where most tools use two. 0 is success and 1 is a failure. Exit 2 is a HOLD, which its documentation defines as not success and not an ordinary failure. A HOLD means an operator has to decide something before the work continues. A continuous integration step that tests only for zero treats a hold as a crash. A step that ignores any nonzero result treats it as done. Both throw away the distinction the exit code exists to carry, so wrap these tools with three branches or do not wrap them at all.

Starting and resuming a task

Before anything else, ask the repository what it already believes.

python3 Tools/check_queue.py . --resume-status

This is the command that makes resumption a property of the repository instead of a property of the agent's memory. An agent that lost its context can run it and learn what was in flight. For work that spans more than one session, copy the shipped task plan template and initialize state.

cp Tools/schemas/task_plan.template.yaml .cambium/deltas/task-plans/TP-001.yaml
python3 Tools/init_state.py . --plan .cambium/deltas/task-plans/TP-001.yaml
python3 Tools/init_state.py . --plan .cambium/deltas/task-plans/TP-001.yaml --apply

init_state.py prints the exact next command, including the revision and hash it expects.

python3 Tools/compile_queue.py . --apply --actor-role integrator \
  --expected-queue-revision REVISION \
  --expected-sha256 SHA256

Copy that line out of the output rather than typing it from memory. The --expected- arguments are a concurrency check: if another actor moved the queue between your read and your write, the hash no longer matches and the compile refuses instead of overwriting someone else's work. Read the result back with python3 Tools/check_queue.py . for the state and python3 Tools/render_queue.py . for a human-readable view. A healthy run shows your batch present with its lifecycle state, and no resume warning.

Every write appends a receipt. Receipts are JSONL (JSON lines, one object per line) and append-only, so the history of who changed shared state is a file you can diff in review, not a chat log somebody has to remember.

Wiring it into Claude Code over MCP

Cambium ships Tools/mcp_server.py and a generator that writes host configuration for you. MCP (model context protocol) is the interface Claude Code and similar harnesses use to reach external tools.

python3 Tools/render_host_configs.py . \
  --projection-target carried-runtime \
  --output-dir /absolute/path/to/corpus/.host-config-staging \
  --distribution-root /absolute/path/to/corpus \
  --workspace-root /absolute/path/to/corpus

Run the same command with --check appended to verify that committed configuration still matches what the generator would produce. That is the form to put in continuous integration, because it fails when someone hand-edits the generated file. The Claude Code output lands at <corpus>/.mcp.json. Codex and Kimi Code get their own files at .codex/config.toml and .kimi-code/mcp.json.

The MCP server preserves each child tool's structured result and exit code and makes no governance judgment of its own, which means the HOLD you would have seen in a terminal is the HOLD the agent sees. Two limits are worth stating. Rendering host configuration is not adoption: it approves no profile and creates no task state. And the server runs wherever you point it, so if your agents work on a server rather than a laptop, it is one more process to place deliberately next to the other MCP servers you host on a VPS.

Who should not adopt a governance kernel

One repository, one agent, one person reading the diffs, and a maintained AGENTS.md: that setup does not need any of the above. The cost here is real, a profile to answer and a state directory whose exit codes you have to respect, and paying it to solve a problem you do not have leaves you with a slower loop and the same documentation.

The line runs roughly here. You want a governance kernel when more than one actor writes shared state, and when someone will later ask which rule was in force at the time. Long tasks that outlive a single session push you the same way, because that is exactly what the Progress Ledger and --resume-status exist for. You do not want one when a careful DESIGN.md that explains why the code is shaped this way and a human review step already catch the contradictions, since those two together are cheaper and you already run them. And if your real pain is agents taking actions you would not have approved, the closer fix is an explicit approval gate on agent actions rather than a documentation standard.

What Cambium does not claim

Its README is unusually direct about its own limits, and reading that section before adopting saves disappointment later. Cambium is not a knowledge base, not a RAG (retrieval augmented generation) engine, not an agent scheduler, and not a default domain policy. It governs the work without supplying the corpus or deciding what the corpus means. It does not ship agent dispatch, isolated worker workspaces, authenticated actor identity, or automatic corpus-wide dependency propagation.

The trust boundary is the part to read twice. Cambium's SHA-256 bindings detect drift and inconsistent history inside your local trust domain. They are not signatures. Without a protected runner or outside attestation, the actor and reviewer labels in a receipt are claims rather than proofs, so anyone with write access to the repository can construct an internally consistent alternative history. That is enough to catch a confused agent, which is the actual threat in most repositories. It is not enough to catch a determined person.

FAQ

Does Cambium replace my AGENTS.md?

No. AGENTS.md is the instruction file your harness loads into context when a session starts. Cambium governs what happens to the corpus after that: which rules are normative, which decisions belong to the operator, and what evidence must exist before work can close. Repositories that adopt it keep AGENTS.md and point it at the adopted profile and the current Queue.

What do I need installed to try it?

Python 3 and git. Cambium's tool documentation states that all shipped Python code uses the standard library, so there are no third-party packages and no virtual environment to build. Clone the repository, check out a specific commit, then run python3 Tools/scaffold_profile.py against the repository you want to govern.

What does exit code 2 mean?

It means HOLD: not success, and not an ordinary failure. Something needs an operator decision before the work can continue. Cambium's tool documentation says callers must preserve the tool's exact result and must not collapse a documented HOLD into either success or failure, so any script or pipeline wrapping these tools has to handle three outcomes.

Is there a stable version I can pin to?

Not a tagged one. As of 1 September 2026 the repository has no releases and no tags, and it was first published on 4 August 2026, so pin to a commit hash instead. Use that same hash for --upstream-ref when you run apply_profile_adoption.py, so your repository's recorded state names the version of the standard it adopted.

Can I use it on a corpus that is not source code?

Yes. Its vocabulary is about knowledge objects, batches and pages rather than files of code. The profile is where a repository declares its own scope, language and architecture, which is how one kernel covers a documentation corpus and a code repository without either inheriting rules written for the other.