Skip to main content

ai-constitution

A constitutional governance framework for AI agents. Bring your own organization name.

CI License: MIT Python: 3.10+

Most AI agent setups bake the agent's name, the operator's name, and infrastructure details directly into prompt files. Cloning the same governance pattern for a new organization means find-and-replace by hand and hoping you didn't miss anything.

This repo separates the framework — the universal pattern for principal authority, ministries, sherpas, protocols, and lifecycle — from the organization that uses it. One config file (org-config.toml) drives a lossless render of the entire constitution into your own copy.

It's the framework half of a three-repo stack:

Repo Role
ai-constitution (this) Articles, protocols, command surface, render pipeline
ai-ministers Domain-expert minister skills (planning, design, external affairs, resources, review)
ai-sherpa Execution sherpas (boot, exit, onboarding, plus optional scrum, design, nextcloud, crawler)

Status: v0.0.1. The render API and 24 templates are populated. Onboarding sherpa lands in M3 (RAJ-61). Public roadmap in Linear.


If you've never built an agent before

Think of an organization. There's a person at the top — call them the principal — who has authority and sets direction. Below them is a principal secretary: an aide who organizes the work, delegates to specialists, keeps the calendar, and makes sure decisions get carried out.

In this framework, the principal is you (the human). The principal secretary is your AI agent. The specialists are ministers (each one expert in a domain — planning, design, etc.). The errand-runners are sherpas (each one wraps a concrete operation: starting services, shutting down, onboarding a new colleague).

The agent doesn't decide everything itself. When a task comes in, it figures out which minister's domain it belongs to, delegates the thinking, and uses sherpas to execute the result. The principal stays in charge — every decision routes back through them.

The reason this exists: when you write all of that down once as text — articles, protocols, identity — and parameterize the names, any organization can adopt the same pattern. You don't fork prompts; you fill in a config file.

Three repos, four files, one render. That's it.


If you're building agents

The framework is text + a small Python render layer. Here's the shape:

ai-constitution/
├── ai_constitution/          # Python: Constitution.load + render API
├── templates/                # 24 jinja2 templates lifted from raj-sadan
│   ├── CONSTITUTION.toml.j2  # 20 articles
│   ├── AGENT.toml.j2         # operating system for the agent
│   ├── IDENTITY.toml.j2      # the agent's persona
│   ├── PRINCIPAL.toml.j2     # the human at the top
│   ├── CLAUDE.md.j2          # bootloader prompt for Claude Code
│   ├── boot-prompt.md.j2     # session boot template
│   └── protocols/PROTOCOL-*.toml.j2   # 13 protocols, "00".."12"
├── skills/                   # 5 lifecycle commands as Claude Code skills
│   └── {amend, boot, checkpoint, delegate, reboot}/SKILL.md.j2
├── defaults.toml             # baseline values for every variable
└── ai_constitution/schema.py # Pydantic models for org-config.toml

How rendering works

  1. The framework ships templates with {{ org.* }} placeholders.
  2. The consumer writes org-config.toml (or runs the onboarding sherpa to generate it).
  3. ai_constitution.Constitution.load(...) reads defaults.toml, merges the consumer's overrides, validates against the Pydantic schema, and renders every template into a target directory.
  4. The output is plain TOML and Markdown — no template engine ships into the consumer's runtime.

Quick start

pip install ai-constitution

# Render a default "Your Org" bundle just to see the shape
python -m ai_constitution render --output ./my-bundle/

# Or with overrides
python -m ai_constitution render --config my-org.toml --output ./my-bundle/

# Validate an org-config without rendering
python -m ai_constitution validate --config my-org.toml

# See what would change vs. an existing bundle
python -m ai_constitution render --config my-org.toml --output ./my-bundle/ --diff

The variable registry

Every value an organization can override lives under org.*:

[org]
name     = "Acme"
slug     = "acme"
timezone = "Europe/Madrid"

[org.pm]
name  = "Vishal"
title = "Founder"

[org.agent]
name  = "Friday"
emoji = "🤖"

[org.ministries]
enabled = ["planning", "design", "review"]   # subset of the ai-ministers registry

[org.sherpas]
enabled = ["boot", "exit", "onboarding"]     # mandatory three; opt in to more

[org.protocols]
enabled = ["00", "12"]                       # minimum viable: delegation + cognitive continuity

Full registry in CONTRACTS.md. Every variable has a default, so a partial override is fine.

Three-repo relationship

  • ai-constitution ships the framework + render pipeline. It depends on nothing else.
  • ai-ministers ships the prompt skills. The render pipeline pulls in only the ministers in org.ministries.enabled.
  • ai-sherpa ships the execution code. The onboarding sherpa lives here and calls into ai_constitution.Constitution.load + render.

A consumer adopts all three as git submodules (or pip-installs the published packages) and points the renderer at their own org-config.toml.


If you're integrating it into something larger

A few design notes worth knowing before you write code against this:

The render contract is lossless. Same inputs always produce the same bytes. StrictUndefined is on, so a typo in a template raises UndefinedError instead of silently rendering empty. Idempotent re-renders are tested.

Validation lives in two places, deliberately. The Pydantic schema (ai_constitution.schema) catches type errors and unknown fields at config-load time. "Required-ness" — refusing to proceed when org.name is still "Your Org" — is the onboarding sherpa's job, not the schema's. This keeps the schema reusable for non-interactive renders (CI pipelines, programmatic tests).

Auto-derivation only fills empties. If org.slug is empty, the renderer derives it from org.name (kebab-case, max 64 chars). If you set org.slug explicitly, your value wins. Same for org.agent.reports_to (defaults to org.pm.title).

Mandatory sherpas are auto-added. Even if a consumer omits boot, exit, and onboarding from org.sherpas.enabled, the schema adds them back. They're load-bearing for the lifecycle.

No conditional templates. Every variable has a default; templates render against whatever the merged config produces. We avoided {{#if minister.X.enabled }} blocks because they make the templates harder to read for everyone — orgs override the lists in org-config.toml and the rendered output reflects only what's enabled.

No runtime substitution. Templates are rendered once, at onboarding (or after python -m ai_constitution render). The output is plain TOML / Markdown that any agent runner can read. Re-render after a framework upgrade by re-running the renderer; we don't ship a template engine into your runtime.

The mockability contract for sherpas: every sherpa must support --dry-run. v0.0.1 has a known portability gap (the lifted sherpas reference raj-sadan filesystem paths) — see CHANGELOG. v0.2 will close it via injected config.


Why this exists (the long-form rationale)

A few decisions are worth defending in detail.

Why constitution-as-code? Most agent stacks treat governance as ad-hoc prompt scaffolding. That works for one project; it doesn't compose. Treating the constitution as code means you get version control, schema validation, automated tests, diff review, and the ability to upgrade the framework underneath an organization without rewriting their rules. The substrate (Python + jinja2 + TOML) is boring on purpose.

Why parameterization at all? The alternative is hand-forking. raj-sadan accumulated 222 mentions of "Mr. V", 61 of "Raj Sadan", 50 of "Vishal", 11 hardcoded ports, 8 service URLs across 18 files. Hand-forking that for a new org is realistic for one fork; it's not realistic for an ecosystem. The audit (raj-sadan/audit/PARAMETERIZATION.md) walked through every substitution.

Why one-shot render at onboarding rather than runtime substitution? Two reasons. First: simplicity at the consumer side — no template engine in the runtime, no per-request rendering cost. Second: the rendered output is a plain artifact you can grep, edit by hand, and version-control. Runtime substitution couples every consumer to a template engine forever and makes the artifacts harder to debug.

Why scoped variable namespace (org.pm.name) rather than flat (PM_NAME)? It scales. Flat names work for ten variables; the registry has fifty and will grow. Dotted scoping mirrors TOML's table structure and lets us add org.contacts.support_email later without naming collisions.

Why three repos rather than one or twelve? One repo means consumers fork the whole thing to opt out of any minister or sherpa. Twelve repos (one per skill) means version-pinning hell. Three repos splits along the natural seams: framework / policy / execution. The collection repos (ai-ministers, ai-sherpa) hide individual-skill versioning behind a single submodule pin.

Why Mustache-style {{ org.x }} rather than ${org.x}? Cloudflare's WAF flags ${...} as injection in some contexts, and the dollar-brace form conflicts with future TOML-native env reference. Mustache is unambiguous and has parsers in every major language.


Status & roadmap

Milestone Status Linear
M1 — Audit & strategy Done (in review) RAJ-45..50
M2 — Templates + render API Done (in review) RAJ-51..59
M4 — Collection repos Done (in review) RAJ-60, 66..70
M5 — Docs + v0.1.0 release In progress RAJ-71..75
M6 — raj-sadan as consumer Not started RAJ-76..81
M3 — Onboarding sherpa Not started (last by design — it's the integration test) RAJ-61..65

Contributing

This is in active development. The Linear project at the link above tracks the roadmap. Issues welcome via GitHub.

License

MIT.

Credits

raj-sadan (github.com/vraj0703) is the reference implementation that ai-constitution was extracted from.

Metadata

Release files for ai-constitution 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ai-constitution 0.1.3
File Size Uploaded Provenance
ai_constitution-0.1.3.tar.gz 25.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ai-constitution 0.1.3
File Interpreter ABI Platform
ai_constitution-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 41.6 kB

Release files / ai_constitution-0.1.3.tar.gz

Download URL ai_constitution-0.1.3.tar.gz
Size 25.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c5e8d5b185b80e4471cb6d21939eaa763a37812ce96d7312f56b5d20339e47a0
BLAKE2b-256 checksum
How to use checksums
0ebf986d4e17b47660e0739450ba842ee597892251e569e7a851e66fac38b69c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 29, 2026.

Transparency log

Release files / ai_constitution-0.1.3-py3-none-any.whl

Download URL ai_constitution-0.1.3-py3-none-any.whl
Size 16.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1b1a8643f997781ab869d321cd062da6d4170997b7293d89475ad56e653f6747
BLAKE2b-256 checksum
How to use checksums
20538e9d83e2da0cf06df473c5805de672e670a2ee3e49d649e622b5ca291de6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 29, 2026.

Transparency log

Security for ai-constitution 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ai_constitution-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page