Oct 2026 • 5 min read

A constitution for a system of agents

The rules for AlanOS were spread across seven documents that quietly disagreed. One register of numbered clauses fixed that, and a single entry test keeps it small.

Context

AlanOS is a personal system made of many parties. Independent domains hold my health records, mail, money and documents. A runtime routes questions between them, models answer, an agent harness carries out tasks, and a console shows me the result. I am a party too: the owner, the one who approves.

Every party needs the same rules. What may a model see? Who may change a domain's files? When does a fact count as true? Those rules lived where rules usually live in software: in prose, across two contracts, four standards and a vision document.

What I started noticing

Each document read well on its own. The trouble showed when two of them answered the same question.

The clearest case was confidential. One document said confidential material never leaves a domain through any tool surface. Another said a local harness acting for me may put confidential content into a model prompt. Health is confidential by default and reached over a local tool surface, so every Health answer broke the first rule while following the second. A conformance test written from one document would have failed the running system.

It was not an isolated slip. Split into single rules, the seven documents held 773. Merged where they truly agreed, they became 526 clauses, with 71 places where two sources disagreed on a binding detail. Prose hides that kind of drift, because a reader resolves it without noticing. A model reading the rules does worse: it picks one side, confidently, and nothing says it picked wrong.

The approach that worked better

I moved every rule into one register, called the constitution, with a few rules of its own.

One clause, one sentence, one id. Each clause has a permanent id, the version it arrived in, and who it binds:

FED-5 · 1.1 · binds federation.
Every party observes at the boundary and does not trust the report, and
this holds equally for domains, models, servers and the orchestrator's
own bookkeeping.

That clause is why I call it a constitution for a system of agents. A model is a party like any other and gets no special trust, and the same clause binds my own code.

It is supreme. Where another document disagrees, the constitution wins. The old contracts and standards stay as commentary: they explain a clause and cite its id, and never restate it. A script writes those citations, and the check fails if a document falls out of date.

Ids are permanent, and change is logged. A retired id is never reused, so EV-4 in a test or a model's answer always means the same thing. A clause changes only through a dated entry in an append-only decision log.

Conformance is measured clause by clause. Each domain declares the version it meets, and a checker reads every repository against every clause that binds it. Failing a clause at or below the declared version is a breach, and the build fails. Failing one above it is distance: work not done yet. The checker also names every clause it cannot verify, with the reason, because a report that stays quiet about what it did not look at reads as a clean bill of health.

The second problem: a constitution that kept growing

A register made amending easy, and feature details started landing as amendments: the shape of a day report, the sound of a voice session, how a work thread is committed. Soon nearly every new feature needed an amendment first.

The fix was an entry test, written into the constitution itself:

Nothing that fails the test is lost. A rule that makes a feature work right moves to a schedule, just as binding but outside the core. A rule that binds one domain moves to that domain's own constitution. Applying the test is a judgement, so it was run three times, twice blind to the earlier results, and a clause moved only when all three agreed. The core came out at about half its size, with every id and every trace kept.

Why this mattered

  • Rules became something code can find. A model, an agent or a test can look up CAP-8 and get one sentence with one meaning.
  • Contradictions became visible. Each disagreement prose had been absorbing turned into a ruling, recorded with its reason.
  • The core stays about trust. What remains is the short list of things that would hurt someone if broken. Feature work moves at its own pace elsewhere.

Trade-offs

  • It reads like law. Clauses are precise and dense, so the reasoning lives in the commentary and a newcomer reads two documents.
  • Checks cover only part of it. Some clauses can only be verified against a running system. Listing them honestly still leaves them unchecked.
  • One person writes, rules and amends. There is no separation of powers in a personal system. The append-only log is the closest thing to it.

What I would keep doing

Write each rule once, as one sentence with a permanent id, and let every other document point at it. Make the checker say out loud what it could not check. And guard the core with one question: if this rule were broken, would anyone be wronged? If not, it belongs somewhere else.